AutomationFlowsAI & RAG › Publish Weekly Smb Blog Posts with Perplexity, Claude, Gemini, Supabase, and…

Publish Weekly Smb Blog Posts with Perplexity, Claude, Gemini, Supabase, and…

Original n8n title: Publish Weekly Smb Blog Posts with Perplexity, Claude, Gemini, Supabase, and Gmail

ByPedro Olavarria @polavarria on n8n.io

This workflow runs weekly to generate, research, write, illustrate, and publish a new blog post by combining Supabase (content + storage), Perplexity (topic + research), Anthropic Claude (writing), Google Gemini (cover image), and Gmail (notification). Runs every Friday at 10:00…

Cron / scheduled trigger★★★★☆ complexityAI-powered24 nodesHTTP RequestPerplexityGmailGoogle Gemini
AI & RAG Trigger: Cron / scheduled Nodes: 24 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #16466 — we link there as the canonical source.

This workflow follows the Gmail → Googlegemini recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "Autonomous Weekly Blog Engine (Perplexity + Claude + Gemini + Supabase)",
  "nodes": [
    {
      "id": "4fd9545f-95ff-40bf-8ea1-cc04f2cfb58a",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2432,
        -1168
      ],
      "parameters": {
        "width": 480,
        "height": 816,
        "content": "## Autonomous Weekly Blog Engine \n\n### How it works\n\n1. Triggers every Friday at 10am ET to fetch published blog titles.\n2. Builds topic context and generates a fresh topic using AI models.\n3. Researches the topic, builds a request, and writes a blog post.\n4. Parses the blog post, generates, and uploads a cover image.\n5. Sets the cover URL, publishes the content, and notifies the user.\n\n### Setup steps\n\n- [ ] Configure the schedule trigger to the desired time if different.\n- [ ] Set up API credentials for Supabase, Perplexity, and other external services used.\n- [ ] Ensure the Gmail node is configured with the correct account for notifications.\n- [ ] Customize HTTP request URLs with your Supabase project details.\n\n### Customization\n\nTopic generation and image styles can be customized in the code nodes and AI model configurations."
      },
      "typeVersion": 1
    },
    {
      "id": "675aea04-5034-4fbb-b681-d870d94c1b49",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1872,
        -1136
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 304,
        "content": "## Scheduled trigger\n\nTriggers the workflow every Friday at 10am ET."
      },
      "typeVersion": 1
    },
    {
      "id": "f95fa441-dd2e-4f20-bf8e-4afffba61c08",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1600,
        -1168
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 320,
        "content": "## Fetch blog titles\n\nFetches existing blog titles from Supabase to prevent duplicates."
      },
      "typeVersion": 1
    },
    {
      "id": "60ea36fc-9af7-4995-8b9b-ead53c53bf22",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1328,
        -1136
      ],
      "parameters": {
        "color": 7,
        "width": 384,
        "height": 528,
        "content": "## Generate blog topic\n\nBuilds context, generates a new blog topic, and logs associated costs."
      },
      "typeVersion": 1
    },
    {
      "id": "05397cf6-7231-4e0e-8fa0-ec44ec0cc196",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -912,
        -1136
      ],
      "parameters": {
        "color": 7,
        "width": 576,
        "height": 544,
        "content": "## Research and prepare post\n\nResearches the topic, builds and sends the AI prompt, then logs costs."
      },
      "typeVersion": 1
    },
    {
      "id": "9ad20acf-98f6-4190-bac6-5cf6165a8e01",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -304,
        -1136
      ],
      "parameters": {
        "color": 7,
        "width": 544,
        "height": 304,
        "content": "## Image generation and upload\n\nParses the post, generates a cover image, and uploads it to storage."
      },
      "typeVersion": 1
    },
    {
      "id": "c30a0701-56af-4b66-a5b0-e327f3cb567a",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        272,
        -1120
      ],
      "parameters": {
        "color": 7,
        "width": 656,
        "height": 272,
        "content": "## Finalize and notify\n\nSets cover URL, publishes to Supabase, and sends a Gmail notification."
      },
      "typeVersion": 1
    },
    {
      "id": "91c7af49-d92f-41d3-add4-115622fe4332",
      "name": "When Every Friday 10am ET",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1824,
        -1008
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 0 10 * * 5"
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "fe1d3693-43fe-4b81-a726-bd1847edafef",
      "name": "Fetch Published Blog Titles API",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1552,
        -1008
      ],
      "parameters": {
        "url": "https://YOUR-PROJECT.supabase.co/rest/v1/blog_posts?select=title&status=eq.published",
        "options": {},
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "supabaseApi"
      },
      "typeVersion": 4.4
    },
    {
      "id": "bdf919fa-20bb-4b7e-aa8f-f6166c62248f",
      "name": "Build Blog Topic Context",
      "type": "n8n-nodes-base.code",
      "position": [
        -1280,
        -1008
      ],
      "parameters": {
        "jsCode": "const allItems = items;\nconst titles = allItems.map(i => i.json.title).filter(Boolean);\nconst titlesList = titles.length > 0 ? titles.join(', ') : 'None yet';\nconst weekNum = Math.ceil((new Date() - new Date(new Date().getFullYear(), 0, 1)) / 604800000);\nconst areas = [\n  'AI automation for small businesses, practical use cases and ROI',\n  'Cybersecurity threats and protection for small businesses',\n  'Cloud infrastructure and migration for growing businesses',\n  'Managed IT support and operational efficiency',\n  'AI governance, data security, and compliance for SMBs',\n  'How automation eliminates manual repetitive work',\n  'Website automation and 24/7 lead generation',\n  'Business strategy and competing with larger companies using AI',\n  'Data management and analytics for informed decisions',\n  'IT cost reduction and technology ROI'\n];\n// One-shot SEO seed: write the \"AI workflow automation\" guide next (2,900/mo keyword),\n// then auto-revert to the normal rotation once a post with that phrase is published.\nconst seedTopic = 'A practical guide to AI workflow automation for small businesses: how to automate manual, repetitive processes step by step, with real use cases and ROI. Target the search phrase \\\"AI workflow automation\\\".';\nconst seedDone = titles.some(t => /workflow automation/i.test(t));\nconst topicArea = seedDone ? areas[weekNum % areas.length] : seedTopic;\nreturn [{ json: { published_titles: titlesList, topic_area: topicArea, title_count: titles.length } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "dc64f1f8-8488-451d-a7b4-4fbe19c0059e",
      "name": "Perplexity Fresh Topic",
      "type": "n8n-nodes-base.perplexity",
      "maxTries": 4,
      "position": [
        -1088,
        -1008
      ],
      "parameters": {
        "model": "sonar-pro",
        "options": {},
        "messages": {
          "message": [
            {
              "content": "=You are a content strategist for [Your Company], an AI automation company targeting small and mid-size businesses in your region.\n\nAlready published blog titles:\n{{ $json.published_titles }}\n\nFocus area this cycle: {{ $json.topic_area }}\n\nGenerate ONE new blog topic that:\n- Is not similar to any already published title above\n- Is relevant to AI automation, IT, cybersecurity, or business efficiency for SMBs\n- Is timely and searchable in 2026\n- Is specific, not generic\n\nReturn ONLY the topic as a single sentence. No explanation, no options, no preamble. Just the topic."
            }
          ]
        },
        "simplify": true,
        "requestOptions": {}
      },
      "retryOnFail": true,
      "typeVersion": 1,
      "waitBetweenTries": 5000
    },
    {
      "id": "c68e4399-c7a3-4ade-91aa-ba62fc9b59ef",
      "name": "Perplexity Research Topic",
      "type": "n8n-nodes-base.perplexity",
      "maxTries": 4,
      "position": [
        -864,
        -1008
      ],
      "parameters": {
        "model": "sonar-pro",
        "options": {},
        "messages": {
          "message": [
            {
              "content": "=Research the following topic for a business blog post: {{ $json.message }}\n\nReturn key insights, trends, real-world examples, statistics, pain points for small businesses, and how AI automation helps.\n\nKeep the response under 800 words. Use plain text only. No markdown formatting, no bold with asterisks, no tables, no brackets, no citation numbers in square brackets. Write in clean paragraphs."
            }
          ]
        },
        "simplify": true,
        "requestOptions": {}
      },
      "retryOnFail": true,
      "typeVersion": 1,
      "waitBetweenTries": 5000
    },
    {
      "id": "d5159e99-a2cd-499e-aca3-00dbe5f85955",
      "name": "Prepare Claude AI Request",
      "type": "n8n-nodes-base.code",
      "position": [
        -672,
        -1008
      ],
      "parameters": {
        "jsCode": "const topic = $('Perplexity Fresh Topic').first().json.message || '';\nconst research = $('Perplexity Research Topic').first().json.message || '';\nconst prompt = `You are writing blog posts for [Your Name], President of [Your Company], an AI automation company in your region. Tagline: [Your tagline]\n\nBlog topic: ${topic}\n\nResearch notes: ${research}\n\nAdmin voice rules, non-negotiable:\n- Direct, confident, no fluff\n- Conversational, like talking to a business owner over coffee, not pitching them\n- No buzzwords: no leverage, streamline, empower, cutting-edge, game-changer, synergy, revolutionize\n- No em dashes, use commas instead\n- Short punchy sentences mixed with longer ones for rhythm\n- If something is broken in how businesses operate, say it straight\n- Dry humor is fine, forced positivity is not\n- Speak to SMB owners as equals, not as a salesman\n\nStructure every post exactly like this:\nLine 1: Title, compelling and SEO-friendly, no markdown, just the text. VARY THE TITLE STRUCTURE across posts; do NOT default to the formula \"How your region SMBs Can Use AI-Driven...\". Rotate freely among angles: a bold claim, a question, a \"X ways to...\" list, a problem-then-fix, a \"Stop doing X\" hook, a number or stat lead, or a \"The real reason...\" angle. Specific and human, never formulaic. Do not begin with \"How your region SMBs Can Use\" unless it is genuinely the best fit (rarely).\nLine 2: EXCERPT: two sentences max, punchy, for the blog card\nLine 3: META: 155 characters max for SEO\nLine 4: CATEGORY: one of: AI Automation, Cybersecurity, IT Support, Cloud Services, Business Strategy, AI Governance\nLine 5: READTIME: estimated minutes\nLine 7 onward: Full blog post body\n\nBlog body rules:\n- 600 to 900 words\n- Use H2 subheadings to break up sections, no hashtag markdown, clean HTML h2 and h3 tags only\n- No bullet point walls, write in paragraphs like a human\n- Reference your region or local SMBs at least twice\n- End with a CTA mentioning https://https://your-website.com/contact\n- Every sentence must earn its place, no fluff, no filler\n\nReturn the complete post exactly as structured. Nothing else.`;\nconst body = { model: 'claude-sonnet-4-6', max_tokens: 4000, messages: [{ role: 'user', content: prompt }] };\nreturn [{ json: { requestBody: JSON.stringify(body) } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "d436f81a-2456-4c45-ac22-69f688ab8ee7",
      "name": "Post to Anthropic API",
      "type": "n8n-nodes-base.httpRequest",
      "maxTries": 4,
      "position": [
        -480,
        -1008
      ],
      "parameters": {
        "url": "https://api.anthropic.com/v1/messages",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ $json.requestBody }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "anthropic-version",
              "value": "2023-06-01"
            },
            {
              "name": "content-type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "anthropicApi"
      },
      "retryOnFail": true,
      "typeVersion": 4.4,
      "waitBetweenTries": 5000
    },
    {
      "id": "3aa8a3cc-a356-47c0-9211-ca61fabcb9a3",
      "name": "Parse Blog Content",
      "type": "n8n-nodes-base.code",
      "position": [
        -256,
        -1008
      ],
      "parameters": {
        "jsCode": "const raw = items[0].json.content[0].text;\nconst topicText = $('Perplexity Fresh Topic').first().json.message;\nconst slug = topicText.toLowerCase().replace(/[^a-z0-9\\s-]/g, '').replace(/\\s+/g, '-').substring(0, 80);\nconst now = new Date();\nconst slugFull = 'blog-' + slug + '-' + now.getFullYear() + '-' + String(now.getMonth()+1).padStart(2,'0');\nconst lines = raw.split('\\n');\n// Robust header parse: Claude sometimes omits the EXCERPT:/META:/CATEGORY:/READTIME:\n// prefixes and emits bare lines separated by blanks (June 12 run published with\n// empty category+excerpt). Strategy: prefer prefixed lines; otherwise fall back to\n// the first five NON-EMPTY lines as title/excerpt/meta/category/readtime; validate\n// category against the known set; never publish empties.\nconst grab = (pref) => { const l = lines.find(x => x.trim().toUpperCase().startsWith(pref)); return l ? l.trim().substring(pref.length).trim() : ''; };\nconst nonEmpty = []; const neIdx = [];\nlines.forEach((l, i) => { if (l.trim()) { nonEmpty.push(l.trim()); neIdx.push(i); } });\nconst title = (grab('TITLE:') || nonEmpty[0] || 'Untitled').trim();\nlet excerpt = grab('EXCERPT:') || nonEmpty[1] || '';\nlet metaDescription = grab('META:') || nonEmpty[2] || '';\nlet category = grab('CATEGORY:') || nonEmpty[3] || '';\nlet readTimeRaw = grab('READTIME:') || nonEmpty[4] || '';\nconst CATS = ['AI Automation','Cloud Services','Cybersecurity','Managed IT','Data Management','Network Solutions','Website Development'];\nif (!CATS.includes(category)) {\n  const found = nonEmpty.slice(1, 7).find(x => CATS.includes(x));\n  category = found || 'AI Automation';\n}\nif (excerpt.startsWith('<') || excerpt.length < 20) { excerpt = metaDescription && !metaDescription.startsWith('<') ? metaDescription : (title + ' - what your region SMBs need to know.'); }\nif (excerpt.length > 300) excerpt = excerpt.substring(0, 297) + '...';\nconst readTime = parseInt(readTimeRaw) || 4;\nconst headerEnd = neIdx[4] !== undefined ? neIdx[4] + 1 : 6;\nconst content = lines.slice(headerEnd).join('\\n').trim();\nreturn [{ json: { title, slug: slugFull, excerpt, seo_meta_description: metaDescription, category, read_time_minutes: readTime, content, status: 'published', author: '[Your Company]', tags: [category, 'AI', 'Small Business', 'your region'], published_at: new Date().toISOString() } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "d773d7b8-5814-482a-8d91-d53ab8eec779",
      "name": "Post to Supabase API",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        592,
        -1008
      ],
      "parameters": {
        "url": "https://YOUR-PROJECT.supabase.co/rest/v1/blog_posts",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"title\": {{ JSON.stringify($('Parse Blog Content').first().json.title) }},\n  \"slug\": {{ JSON.stringify($('Parse Blog Content').first().json.slug) }},\n  \"excerpt\": {{ JSON.stringify($('Parse Blog Content').first().json.excerpt) }},\n  \"content\": {{ JSON.stringify($('Parse Blog Content').first().json.content) }},\n  \"category\": {{ JSON.stringify($('Parse Blog Content').first().json.category) }},\n  \"tags\": {{ JSON.stringify($('Parse Blog Content').first().json.tags) }},\n  \"author\": \"[Your Company]\",\n  \"status\": \"published\",\n  \"published_at\": {{ JSON.stringify($('Parse Blog Content').first().json.published_at) }},\n  \"seo_meta_description\": {{ JSON.stringify($('Parse Blog Content').first().json.seo_meta_description) }},\n  \"read_time_minutes\": {{ $('Parse Blog Content').first().json.read_time_minutes }},\n  \"cover_image_url\": {{ JSON.stringify($('Set Cover Image URL').first().json.cover_image_url) }}\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Prefer",
              "value": "return=representation"
            }
          ]
        },
        "nodeCredentialType": "supabaseApi"
      },
      "typeVersion": 4.4
    },
    {
      "id": "5f53e876-42bd-4e2c-a375-779f93a3b844",
      "name": "Send Publish Email to Admin",
      "type": "n8n-nodes-base.gmail",
      "position": [
        784,
        -1008
      ],
      "parameters": {
        "sendTo": "you@example.com",
        "message": "=<div style=\"font-family: Arial, sans-serif; max-width: 680px; margin: 0 auto; color: #1a1a2e;\"><table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\"><tr><td style=\"background: #1B4F8A; padding: 24px 32px; border-radius: 8px 8px 0 0;\"><h1 style=\"color: #ffffff; margin: 0; font-size: 22px;\">Blog Post Published</h1><p style=\"color: #DDDDDD; margin: 4px 0 0; font-size: 14px;\">[Your Company] Autonomous Blog Engine</p></td></tr></table><div style=\"padding: 32px;\"><h2 style=\"color: #1B4F8A; margin-top: 0;\">{{ $('Parse Blog Content').item.json.title }}</h2><table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"margin-bottom: 24px;\"><tr><td style=\"background: #EBF2FB; border-left: 4px solid #1B4F8A; border-radius: 8px; padding: 16px 20px;\"><p style=\"margin: 6px 0;\"><strong>Category:</strong> {{ $('Parse Blog Content').item.json.category }}</p><p style=\"margin: 6px 0;\"><strong>Read Time:</strong> {{ $('Parse Blog Content').item.json.read_time_minutes }} minutes</p><p style=\"margin: 6px 0;\"><strong>Slug:</strong> {{ $('Parse Blog Content').item.json.slug }}</p><p style=\"margin: 6px 0;\"><strong>SEO Meta:</strong> {{ $('Parse Blog Content').item.json.seo_meta_description }}</p></td></tr></table><p style=\"font-weight: bold; color: #333;\">Excerpt:</p><p style=\"color: #555;\">{{ $('Parse Blog Content').item.json.excerpt }}</p><p style=\"margin-top: 24px; font-size: 14px; color: #555;\">This post is now live on your-website.com/blog. [Your Company] renders it automatically from Supabase.</p><p style=\"color: #999; font-size: 12px; text-align: center; margin-top: 32px;\">[Your Company] Autonomous Blog Engine | [Your tagline]</p></div></div>",
        "options": {
          "ccList": "you@example.com",
          "appendAttribution": false
        },
        "subject": "=Blog Published: {{ $('Parse Blog Content').item.json.title }}"
      },
      "typeVersion": 2.2
    },
    {
      "id": "a6fa62c4-e8e8-48a7-a1ef-9b3f6e6c9e72",
      "name": "Log Writing Blog Costs",
      "type": "n8n-nodes-base.executeWorkflow",
      "position": [
        -480,
        -768
      ],
      "parameters": {
        "mode": "each",
        "options": {
          "waitForSubWorkflow": false
        },
        "workflowId": {
          "__rl": true,
          "mode": "id",
          "value": "iIpOTUGlzIpxptWQ"
        },
        "workflowInputs": {
          "value": {
            "model": "={{ $('Post to Anthropic API').item.json.model || '' }}",
            "provider": "anthropic",
            "node_name": "Write Blog Post",
            "request_id": "={{ $('Post to Anthropic API').item.json.id || '' }}",
            "agent_label": "",
            "input_tokens": "={{ $('Post to Anthropic API').item.json.usage?.input_tokens || 0 }}",
            "output_tokens": "={{ $('Post to Anthropic API').item.json.usage?.output_tokens || 0 }}",
            "workflow_name": "={{ $workflow.name }}"
          },
          "mappingMode": "defineBelow"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "7ccfb5c8-3dbb-40ce-8e07-eb12521ad545",
      "name": "Log Topic Generation Costs",
      "type": "n8n-nodes-base.executeWorkflow",
      "position": [
        -1088,
        -784
      ],
      "parameters": {
        "mode": "each",
        "options": {
          "waitForSubWorkflow": false
        },
        "workflowId": {
          "__rl": true,
          "mode": "id",
          "value": "iIpOTUGlzIpxptWQ"
        },
        "workflowInputs": {
          "value": {
            "model": "={{ $('Perplexity Fresh Topic').item.json.model || 'sonar-pro' }}",
            "provider": "perplexity",
            "node_name": "Generate Fresh Topic",
            "request_id": "={{ $('Perplexity Fresh Topic').item.json.id || '' }}",
            "agent_label": "",
            "input_tokens": "={{ $('Perplexity Fresh Topic').item.json.usage?.prompt_tokens || 0 }}",
            "cost_override": "0.005",
            "output_tokens": "={{ $('Perplexity Fresh Topic').item.json.usage?.completion_tokens || 0 }}",
            "workflow_name": "={{ $workflow.name }}"
          },
          "mappingMode": "defineBelow"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "15d6aaa8-e71e-4018-9260-f0bef87bb6b3",
      "name": "Log Research Costs",
      "type": "n8n-nodes-base.executeWorkflow",
      "position": [
        -864,
        -784
      ],
      "parameters": {
        "mode": "each",
        "options": {
          "waitForSubWorkflow": false
        },
        "workflowId": {
          "__rl": true,
          "mode": "id",
          "value": "iIpOTUGlzIpxptWQ"
        },
        "workflowInputs": {
          "value": {
            "model": "={{ $('Perplexity Research Topic').item.json.model || 'sonar-pro' }}",
            "provider": "perplexity",
            "node_name": "Research Topic",
            "request_id": "={{ $('Perplexity Research Topic').item.json.id || '' }}",
            "agent_label": "",
            "input_tokens": "={{ $('Perplexity Research Topic').item.json.usage?.prompt_tokens || 0 }}",
            "cost_override": "0.005",
            "output_tokens": "={{ $('Perplexity Research Topic').item.json.usage?.completion_tokens || 0 }}",
            "workflow_name": "={{ $workflow.name }}"
          },
          "mappingMode": "defineBelow"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "dab6c5a6-68b7-444b-b760-3b65701f7b2d",
      "name": "Google Gemini: Create Cover Image",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "maxTries": 4,
      "position": [
        -80,
        -1008
      ],
      "parameters": {
        "prompt": "={{ \"A clean, modern, professional editorial illustration representing: \" + $json.title + \". Topic category: \" + $json.category + \". Style: minimalist magazine-cover aesthetic, dark navy (#0B2545) base with soft orange (#F97316) accents, generous negative space, wide 16:9 composition, no people's faces, no embedded text, no captions, no logos. High quality, sharp, professional.\" }}",
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-3.1-flash-image-preview",
          "cachedResultName": "models/gemini-3.1-flash-image-preview"
        },
        "options": {
          "binaryPropertyOutput": "data"
        },
        "resource": "image"
      },
      "retryOnFail": true,
      "typeVersion": 1.2,
      "waitBetweenTries": 5000
    },
    {
      "id": "6818af19-c9f9-4dde-a232-506f5da0c6ce",
      "name": "Upload Image to Supabase",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        96,
        -1008
      ],
      "parameters": {
        "url": "=https://YOUR-PROJECT.supabase.co/storage/v1/object/social-images/blog-covers/{{ $('Parse Blog Content').first().json.slug }}-cover.png",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "binaryData",
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "x-upsert",
              "value": "true"
            },
            {
              "name": "Content-Type",
              "value": "image/png"
            }
          ]
        },
        "inputDataFieldName": "data",
        "nodeCredentialType": "supabaseApi"
      },
      "typeVersion": 4.2
    },
    {
      "id": "974bf153-f9ac-4f0b-8057-1e4122f7f99c",
      "name": "Set Cover Image URL",
      "type": "n8n-nodes-base.set",
      "position": [
        320,
        -1008
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "2054b50a-3bb2-4ee5-a648-fe28cc53d174",
              "name": "cover_image_url",
              "type": "string",
              "value": "={{ 'https://YOUR-PROJECT.supabase.co/storage/v1/object/public/social-images/blog-covers/' + $('Parse Blog Content').first().json.slug + '-cover.png' }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "name": "Sticky: Setup",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2432,
        -1688
      ],
      "parameters": {
        "color": 4,
        "width": 460,
        "height": 300,
        "content": "## Setup\n\n**1. Replace the placeholders** in node names/prompts:\n- `[Your Company]`, `[Your Name]`\n- `your-website.com` (your site)\n- `YOUR-PROJECT` (your Supabase project, e.g. YOUR-PROJECT.supabase.co)\n\n**2. Connect credentials** on the relevant nodes:\n- Supabase, Perplexity, Anthropic (Claude), Google Gemini, Gmail\n\n**3. Adjust the schedule** in the trigger if you don't want Fridays at 10am.\n\n**4. Optional:** the cost-logging nodes call your own token-logging sub-workflow. Delete them if you don't track AI cost."
      },
      "typeVersion": 1
    }
  ],
  "settings": {
    "executionOrder": "v1"
  },
  "connections": {
    "Parse Blog Content": {
      "main": [
        [
          {
            "node": "Google Gemini: Create Cover Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Cover Image URL": {
      "main": [
        [
          {
            "node": "Post to Supabase API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post to Supabase API": {
      "main": [
        [
          {
            "node": "Send Publish Email to Admin",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post to Anthropic API": {
      "main": [
        [
          {
            "node": "Log Writing Blog Costs",
            "type": "main",
            "index": 0
          },
          {
            "node": "Parse Blog Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Perplexity Fresh Topic": {
      "main": [
        [
          {
            "node": "Log Topic Generation Costs",
            "type": "main",
            "index": 0
          },
          {
            "node": "Perplexity Research Topic",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Blog Topic Context": {
      "main": [
        [
          {
            "node": "Perplexity Fresh Topic",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload Image to Supabase": {
      "main": [
        [
          {
            "node": "Set Cover Image URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Perplexity Research Topic": {
      "main": [
        [
          {
            "node": "Log Research Costs",
            "type": "main",
            "index": 0
          },
          {
            "node": "Prepare Claude AI Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Claude AI Request": {
      "main": [
        [
          {
            "node": "Post to Anthropic API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When Every Friday 10am ET": {
      "main": [
        [
          {
            "node": "Fetch Published Blog Titles API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Published Blog Titles API": {
      "main": [
        [
          {
            "node": "Build Blog Topic Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini: Create Cover Image": {
      "main": [
        [
          {
            "node": "Upload Image to Supabase",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow runs weekly to generate, research, write, illustrate, and publish a new blog post by combining Supabase (content + storage), Perplexity (topic + research), Anthropic Claude (writing), Google Gemini (cover image), and Gmail (notification). Runs every Friday at 10:00…

Source: https://n8n.io/workflows/16466/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

kisisel asistan. Uses toolWorkflow, toolHttpRequest, toolCalculator, toolThink. Scheduled trigger; 43 nodes.

Tool Workflow, Tool Http Request, Tool Calculator +15
AI & RAG

This template uses the Apify LinkedIn Profile Scraper, which is a community node only available in self-hosted n8n installations. The LinkedIn scraping step is optional and can be removed for n8n Clou

HTTP Request, Perplexity, Slack +8
AI & RAG

Fetch user-specific research papers from arXiv on a daily schedule, process and structure the data, and create or update entries in a Notion database, with support for data delivery Paper Topic: singl

Chain Llm, Google Gemini Chat, HTTP Request +3
AI & RAG

An end-to-end automation system that monitors TikTok accounts for new 3-image carousel posts, extracts text overlays and visual layouts using AI vision analysis, translates content into English, and a

HTTP Request, Move Binary Data, Google Gemini +5
AI & RAG

Complete PostgreSQL-backed system: Keyword scoring → AI research → Multi-part content generation → fal.ai Nano Banana image generation → WordPress publishing

WordPress, OpenAI, Perplexity +8