{
  "name": "AI Social Poster \u2014 Facebook (Google Drive + Gemini Vision)",
  "nodes": [
    {
      "id": "sticky-main",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -864,
        -128
      ],
      "parameters": {
        "width": 480,
        "height": 656,
        "content": "## AI Social Poster \u2014 Facebook (Google Drive + Gemini Vision)\n\n### How it works\n\nRuns on a schedule, grabs the next image from a Google Drive folder, sends it to Gemini Vision for a Facebook caption, then posts the image and caption to your Facebook Page via the Graph API.\n\n### Setup steps\n\n- Add Google Drive OAuth2, Google Gemini, and Facebook Graph API (Page Access Token) credentials\n- Fill in the Config node: your Facebook Page ID (Page Settings \u2192 About \u2192 Page ID), CTA link, brand context\n- Point the Google Drive node at your own image folder, then activate\n\n### Customization\n\nChange the Schedule Trigger's interval, edit the Gemini prompt for a different caption tone, or swap the Drive folder for a different image source."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-trigger-config",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -304,
        -80
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 320,
        "content": "## Trigger & Config\n\nRuns on a schedule, then sets your Facebook Page ID, CTA link, and brand context for the rest of the workflow to use."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-fetch",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        176,
        -80
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 320,
        "content": "## Fetch the Image\n\nFinds the next unprocessed image in your Google Drive folder and downloads its binary data."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-caption",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        640,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 368,
        "content": "## Generate the Caption\n\nGemini Vision reads the image and writes a Facebook caption as JSON, using the brand context from Config."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-publish",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        912,
        -96
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 336,
        "content": "## Post to Facebook\n\nPosts the image URL and generated caption to your Facebook Page via the Graph API's /photos endpoint."
      },
      "typeVersion": 1
    },
    {
      "id": "trigger-1",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -260,
        80
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "daysInterval": 3,
              "triggerAtHour": 19,
              "triggerAtMinute": 30
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "config-1",
      "name": "Config",
      "type": "n8n-nodes-base.set",
      "position": [
        -20,
        80
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a1",
              "name": "facebookPageId",
              "type": "string",
              "value": "REPLACE_WITH_YOUR_PAGE_ID"
            },
            {
              "id": "a2",
              "name": "ctaLink",
              "type": "string",
              "value": "https://your-website.com/contact"
            },
            {
              "id": "a3",
              "name": "brandContext",
              "type": "string",
              "value": "We help small businesses automate repetitive work with AI."
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "drive-search-1",
      "name": "Search files and folders",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        220,
        80
      ],
      "parameters": {
        "limit": 1,
        "filter": {
          "driveId": {
            "__rl": true,
            "mode": "list",
            "value": "My Drive"
          },
          "folderId": {
            "__rl": true,
            "mode": "list",
            "value": "REPLACE_WITH_YOUR_FOLDER_ID",
            "cachedResultName": "Social Media Images"
          }
        },
        "options": {
          "fields": [
            "*"
          ]
        },
        "resource": "fileFolder",
        "operation": "search"
      },
      "typeVersion": 3
    },
    {
      "id": "drive-download-1",
      "name": "Download file",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        440,
        80
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        },
        "options": {},
        "operation": "download"
      },
      "typeVersion": 3
    },
    {
      "id": "gemini-analyze-1",
      "name": "Analyze an image",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        688,
        80
      ],
      "parameters": {
        "text": "=You are a senior performance-marketing copywriter. Analyze the attached image and write a Facebook caption for this business: {{ $('Config').first().json.brandContext }}\n\nStyle rules:\n- Avoid generic AI phrases (\"game-changing\", \"unleash\", \"let's dive in\")\n- Direct, almost dry tone with clear expert authority; vary sentence length (short punchy lines + explanatory ones)\n- Structure: ALL-CAPS headline focused on the result -> body using Problem/Agitation/Solution tied to the image -> 3 measurable benefits as bullets (\ud83d\ude80/\u2705) -> a line of dots (....) -> closing CTA with this link: {{ $('Config').first().json.ctaLink }} -> hashtags\n- Output ONLY valid JSON: {\"facebook_caption\": \"...\"} with real line breaks encoded as \\n\\n inside the string, no markdown fences",
        "modelId": {
          "__rl": true,
          "mode": "id",
          "value": "models/gemini-2.5-flash"
        },
        "options": {},
        "resource": "image",
        "inputType": "binary",
        "operation": "analyze"
      },
      "typeVersion": 1.1
    },
    {
      "id": "fb-post-1",
      "name": "Post to Facebook",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        960,
        80
      ],
      "parameters": {
        "url": "={{ 'https://graph.facebook.com/v23.0/' + $('Config').first().json.facebookPageId + '/photos' }}",
        "method": "POST",
        "options": {},
        "sendQuery": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "url",
              "value": "={{ $('Search files and folders').item.json.thumbnailLink.replace(/=s220$/, '=s2000') }}"
            },
            {
              "name": "caption",
              "value": "={{ JSON.parse($json.content.parts[0].text.replace(/```json|```/g, '')).facebook_caption }}"
            }
          ]
        },
        "nodeCredentialType": "facebookGraphApi"
      },
      "typeVersion": 4.2
    }
  ],
  "settings": {
    "executionOrder": "v1"
  },
  "connections": {
    "Config": {
      "main": [
        [
          {
            "node": "Search files and folders",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download file": {
      "main": [
        [
          {
            "node": "Analyze an image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze an image": {
      "main": [
        [
          {
            "node": "Post to Facebook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search files and folders": {
      "main": [
        [
          {
            "node": "Download file",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}