8
n8n 한국어amn8n.com

AI 블로그 생성기 (Gemini, Replicate 이미지 생성, Supabase 게시 및 Slack 포함)

고급

이것은자동화 워크플로우로, 25개의 노드를 포함합니다.주로 If, Set, Code, Cron, Wait 등의 노드를 사용하며. 뉴스에서 게시까지의 자동화된 블로그 생성, Gemini, Ideogram 및 Slack 사용

사전 요구사항
  • Slack Bot Token 또는 Webhook URL
  • 대상 API의 인증 정보가 필요할 수 있음

카테고리

-
워크플로우 미리보기
노드 연결 관계를 시각적으로 표시하며, 확대/축소 및 이동을 지원합니다
워크플로우 내보내기
다음 JSON 구성을 복사하여 n8n에 가져오면 이 워크플로우를 사용할 수 있습니다
{
  "id": "EmPnnzwJEHxMuJaw",
  "meta": {
    "instanceId": "bd69d47c91060511db2b31f757484463dd5af5fe7228f5cd6f51444aefa5ac55",
    "templateCredsSetupCompleted": true
  },
  "name": "AI Blog Creator with Gemini, Replicate Image, Supabase Publishing & Slack",
  "tags": [],
  "nodes": [
    {
      "id": "e45d33d9-2fc2-476c-b0ff-63d16b30111a",
      "name": "산업 동향 가져오기",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        224,
        -240
      ],
      "parameters": {
        "url": "https://newsapi.org/v2/everything?q=AI automation SaaS&sortBy=publishedAt&pageSize=10",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpQueryAuth"
      },
      "credentials": {
        "httpQueryAuth": {
          "id": "XbH4j2OBjd3qNhPr",
          "name": "newsapi"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "2c641b4b-9ce0-472d-a970-714d6a630f0c",
      "name": "Supabase에 게시",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2496,
        -240
      ],
      "parameters": {
        "url": "https://your.supabase.co/functions/v1/blog-api",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "title",
              "value": "={{ $json.title }}"
            },
            {
              "name": "slug",
              "value": "={{ $json.slug }}"
            },
            {
              "name": "excerpt",
              "value": "={{ $json.excerpt }}"
            },
            {
              "name": "content",
              "value": "={{ $json.content }}"
            },
            {
              "name": "image_url",
              "value": "={{ $json.image_url }}"
            },
            {
              "name": "published",
              "value": "true"
            }
          ]
        },
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "jaWa5lNkOeQCkOcg",
          "name": "UTSLsuperbase"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "17fcce85-bdf1-4c21-848a-3ce667e3aab5",
      "name": "Slack 알림",
      "type": "n8n-nodes-base.slack",
      "position": [
        2720,
        -240
      ],
      "parameters": {
        "text": "=✅ *New Blog Published!*  \n*Title:* {{$json['title']}}  \n*Slug:* {{$json['slug']}}  \n*URL:* https://yoururl.com/blog/{{$json['slug']}}",
        "channel": "#blog-automation",
        "attachments": [],
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "id": "O5jKBGGMM6lHXuRS",
          "name": "Slack account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5ecb7538-6358-4d89-ac55-8e4539f8d42a",
      "name": "모델에 메시지 보내기",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        448,
        -240
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-2.5-flash",
          "cachedResultName": "models/gemini-2.5-flash"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "=Act as an AI market analyst. Based on these current trends and articles:\n\"{{ $json.articles }}\"\nGenerate 1 trending blog topic ideas relevant to SaaS, AI, Automation, and industry innovation that would benefit our company’s brand authority.\nReturn them in strict JSON with fields: title, description, keywords.\nno exta text, details etc. give me direct json output without pre and post text.\n"
            }
          ]
        }
      },
      "credentials": {
        "googlePalmApi": {
          "id": "ry9hnf20jfXpHAes",
          "name": "Google Gemini(PaLM) Api account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5da2d4ee-d7b0-441a-8523-067a17182c6a",
      "name": "모델에 메시지 보내기1",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        800,
        -240
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-2.5-flash",
          "cachedResultName": "models/gemini-2.5-flash"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "=You are an expert SEO content strategist. Write a 1200–1500 word blog in Markdown on the topic:\n\"{{ $json.content.parts[0].text }}\"\n\nRequirements:\n- Use high-ranking keywords naturally.\n- Include an SEO title, meta description, and excerpt.\n- Use markdown headings, bullet points, and bold keywords.\n- Structure: Introduction → Insight → Case Studies → Conclusion → CTA.\nOutput JSON:\n{\n  \"title\": \"...\",\n  \"slug\": \"...\",\n  \"excerpt\": \"...\",\n  \"content\": \"...\",\n  \"keywords\": \"...\",\n  \"image_prompt\": \"...\"\n}\n"
            }
          ]
        }
      },
      "credentials": {
        "googlePalmApi": {
          "id": "ry9hnf20jfXpHAes",
          "name": "Google Gemini(PaLM) Api account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "1369e40f-2008-4fb7-9123-d17b02a7d42d",
      "name": "JavaScript 코드",
      "type": "n8n-nodes-base.code",
      "position": [
        1152,
        -240
      ],
      "parameters": {
        "jsCode": "// --- Ultra-Resilient Gemini Blog Cleaner ---\n// Works with Markdown fences, nested JSON, or plain text\n\nconst raw = $json.content?.parts?.[0]?.text || '';\nif (!raw) throw new Error('Gemini returned empty response.');\n\nlet text = raw.trim();\n\n// 1️⃣ Strip Markdown fences and language hints\ntext = text\n  .replace(/```json/gi, '')\n  .replace(/```/g, '')\n  .replace(/^#+\\s+/gm, '')\n  .trim();\n\n// 2️⃣ Find the innermost JSON block\nlet matches = text.match(/\\{[\\s\\S]*\\}/g);\nlet parsed = {};\n\nif (matches && matches.length) {\n  // pick the deepest block (most nested)\n  let jsonText = matches[matches.length - 1]\n    .replace(/“|”/g, '\"')\n    .replace(/‘|’/g, \"'\")\n    .replace(/,\\s*([}\\]])/g, '$1')\n    .replace(/'/g, '\"')\n    .trim();\n\n  try {\n    parsed = JSON.parse(jsonText);\n  } catch (err) {\n    // attempt repair if invalid JSON\n    let repaired = jsonText.replace(/([{,]\\s*)([A-Za-z0-9_]+)\\s*:/g, '$1\"$2\":');\n    try {\n      parsed = JSON.parse(repaired);\n    } catch (err2) {\n      parsed = {};\n    }\n  }\n}\n\n// 3️⃣ Regex fallback if still not parsed\nif (!parsed.title) {\n  parsed.title = text.match(/\"title\"\\s*:\\s*\"([^\"]+)\"/i)?.[1]\n    || text.match(/title\\s*[:\\-]\\s*(.+)/i)?.[1]?.trim()\n    || '';\n}\nif (!parsed.slug) {\n  parsed.slug = text.match(/\"slug\"\\s*:\\s*\"([^\"]+)\"/i)?.[1]\n    || text.match(/slug\\s*[:\\-]\\s*(.+)/i)?.[1]?.trim()\n    || '';\n}\nif (!parsed.excerpt) {\n  parsed.excerpt = text.match(/\"excerpt\"\\s*:\\s*\"([^\"]+)\"/i)?.[1]\n    || text.match(/excerpt\\s*[:\\-]\\s*(.+)/i)?.[1]?.trim()\n    || '';\n}\nif (!parsed.content) {\n  const contentMatch = text.match(/\"content\"\\s*:\\s*\"([\\s\\S]+)\"/i);\n  parsed.content = contentMatch\n    ? contentMatch[1]\n    : text.match(/content\\s*[:\\-]\\s*([\\s\\S]+)/i)?.[1]?.trim()\n    || '';\n}\nif (!parsed.keywords) {\n  parsed.keywords = text.match(/\"keywords\"\\s*:\\s*\"([^\"]+)\"/i)?.[1]\n    || text.match(/keywords?\\s*[:\\-]\\s*(.+)/i)?.[1]?.trim()\n    || '';\n}\nif (!parsed.image_prompt) {\n  parsed.image_prompt = text.match(/\"image_prompt\"\\s*:\\s*\"([^\"]+)\"/i)?.[1]\n    || text.match(/image[_\\s]?prompt\\s*[:\\-]\\s*(.+)/i)?.[1]?.trim()\n    || '';\n}\n\n// 4️⃣ Normalize and sanitize output\nparsed.title = parsed.title?.replace(/^[\"']|[\"']$/g, '') || 'Untitled Blog';\nparsed.slug =\n  parsed.slug ||\n  parsed.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');\nparsed.excerpt = parsed.excerpt?.replace(/^[\"']|[\"']$/g, '') || parsed.content.slice(0, 160);\nparsed.content = parsed.content?.replace(/^[\"']|[\"']$/g, '') || '';\nparsed.keywords = parsed.keywords?.replace(/^[\"']|[\"']$/g, '') || '';\nparsed.image_prompt =\n  parsed.image_prompt?.replace(/^[\"']|[\"']$/g, '') || parsed.title;\n\n// 5️⃣ Output ready-to-use normalized data\nreturn [parsed];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "02a8a518-fb7d-4f13-b72d-25dcbacfb033",
      "name": "대기",
      "type": "n8n-nodes-base.wait",
      "position": [
        1824,
        -240
      ],
      "webhookId": "c8b9eb51-2818-4db7-9c66-3a17afb79adc",
      "parameters": {
        "amount": 20
      },
      "typeVersion": 1.1
    },
    {
      "id": "e2f813a3-1808-44f7-9bae-842d8d6cecbc",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        2048,
        -240
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "31dea76b-5ba5-464c-a85f-cac7facabdfb",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.status }}",
              "rightValue": "=succeeded"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "b300ab84-eeea-42ea-a609-6bff06da4846",
      "name": "필드 수정",
      "type": "n8n-nodes-base.set",
      "position": [
        2272,
        -240
      ],
      "parameters": {
        "mode": "raw",
        "options": {},
        "jsonOutput": "={\n  \"title\": \"{{ $('Code in JavaScript').item.json.title }}\",\n  \"slug\": \"{{ $('Code in JavaScript').item.json.slug }}\",\n  \"excerpt\": \"{{ $('Code in JavaScript').item.json.excerpt }}\",\n  \"content\": \"{{ $('Code in JavaScript').item.json.content }}\",\n  \"image_url\": \"{{ $json.output }}\",\n  \"published\": true\n}"
      },
      "typeVersion": 3.4
    },
    {
      "id": "df01fb3f-d7dd-4d2b-9581-24df4472b3ea",
      "name": "예약 트리거",
      "type": "n8n-nodes-base.cron",
      "position": [
        0,
        -240
      ],
      "parameters": {
        "triggerTimes": {
          "item": [
            {
              "hour": 10
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "03a19edc-7128-40d1-a936-7fa3bce230a2",
      "name": "스티커 노트",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -48,
        -48
      ],
      "parameters": {
        "color": 4,
        "width": 384,
        "height": 512,
        "content": "### 🌐 **Fetch Industry Trends (HTTP Request – NewsAPI)**\n\n**Purpose:**\nFetches the latest 10 articles related to “AI automation SaaS” from NewsAPI.\nThese articles are used as context for generating trending blog topics.\n\n**Credentials Required:**\n\n* `NewsAPI` (Generic Query Auth) — Use your API key from [https://newsapi.org](https://newsapi.org).\n\n**Notes:**\n\n* You can modify the `q` parameter to match your industry (e.g., “finance AI,” “healthcare automation,” etc.).\n* You can also adjust `pageSize` to fetch more or fewer results.\n* NewsAPI free tier allows 100 requests/day — plan accordingly if running multiple times.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "dc40791a-0f73-45dd-8856-30d3ea8b88fe",
      "name": "스티커 노트1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        304,
        -672
      ],
      "parameters": {
        "color": 5,
        "width": 352,
        "height": 416,
        "content": "### 🤖 **Message a model (Google Gemini)**\n\n**Purpose:**\nAsks Gemini to analyze current news trends and generate **1 trending blog topic** idea in JSON format (title, description, keywords).\n\n**Credentials Required:**\n\n* `Google Gemini (PaLM) API Key`\n\n**Notes:**\n\n* Returns strict JSON to make downstream parsing easier.\n* You can modify the prompt for your own industry context (e.g., “Based on fintech trends…”).\n* Recommended model: `gemini-2.5-flash` for faster responses."
      },
      "typeVersion": 1
    },
    {
      "id": "b2863fad-0e3e-4f6d-a5e9-c083a37c7962",
      "name": "스티커 노트2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        624,
        -48
      ],
      "parameters": {
        "color": 5,
        "width": 432,
        "height": 416,
        "content": "### ✍️ **Message a model1 (Google Gemini)**\n\n**Purpose:**\nGenerates a full-length blog (1200–1500 words) on the selected topic, optimized for SEO and structured in Markdown.\n\n**Credentials Required:**\n\n* Same `Google Gemini (PaLM)` credential as above.\n\n**Notes:**\n\n* The prompt includes explicit instructions for SEO title, meta description, excerpt, and structured JSON output.\n* You can tune word length or format (e.g., shorter LinkedIn post version) by editing the prompt text.\n* Output is JSON, but sometimes Gemini may include Markdown or text noise — the next node handles cleanup."
      },
      "typeVersion": 1
    },
    {
      "id": "c024e432-6579-4846-bd85-3d1d6cc8c047",
      "name": "스티커 노트3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        864,
        -672
      ],
      "parameters": {
        "color": 3,
        "width": 400,
        "height": 416,
        "content": "### 🧹 **Code in JavaScript**\n\n**Purpose:**\nCleans, parses, and repairs any messy AI output to ensure consistent JSON fields (title, slug, excerpt, content, keywords, image_prompt).\n\n**Notes:**\n\n* This code is **resilient** against broken Markdown, mixed quotes, and malformed JSON.\n* It automatically normalizes the slug, removes extra quotation marks, and trims long text.\n* If Gemini output fails to parse, it still produces fallback fields like `Untitled Blog`.\n* No credentials required.\n\n💡 *You can safely modify this node if you add or remove output fields from the AI prompt.*"
      },
      "typeVersion": 1
    },
    {
      "id": "1792857d-0095-4aaf-93d3-3137a6f7c59d",
      "name": "스티커 노트4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1136,
        -16
      ],
      "parameters": {
        "color": 4,
        "width": 384,
        "height": 432,
        "content": "### 🖼️ **HTTP Request (Replicate – Generate Image)**\n\n**Purpose:**\nSends the `image_prompt` field to Replicate’s **Ideogram v3 Turbo** model to generate a 1024×1024 image.\n\n**Credentials Required:**\n\n* `Replicate Bearer Token` from [https://replicate.com/account](https://replicate.com/account)\n\n**Notes:**\n\n* Modify `width`/`height` for other image sizes.\n* You can swap model endpoint with any text-to-image API you prefer.\n* Returns a `prediction ID` and temporary URL for polling."
      },
      "typeVersion": 1
    },
    {
      "id": "35e16700-c40d-4e8b-abda-a55b193b7e1f",
      "name": "HTTP 요청1 (Replicate 폴링)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1600,
        -240
      ],
      "parameters": {
        "url": "={{ $json.urls.get }}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "IaV5B30kamGSSZgF",
          "name": "Bearer Auth account"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "6c7dfb6f-4f83-4d65-bea0-56c12a7b5393",
      "name": "HTTP 요청 (Replicate - 이미지 생성)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1376,
        -240
      ],
      "parameters": {
        "url": "https://api.replicate.com/v1/models/ideogram-ai/ideogram-v3-turbo/predictions",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"input\": {\n    \"prompt\": \"{{ $json.image_prompt }}\",\n    \"width\": 1024,\n    \"height\": 1024\n  }\n}\n",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "IaV5B30kamGSSZgF",
          "name": "Bearer Auth account"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "9a54a8e9-938b-4e24-8f50-6681b64e53d7",
      "name": "스티커 노트5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1744,
        -32
      ],
      "parameters": {
        "width": 256,
        "height": 368,
        "content": "### ⏱️ **Wait**\n\n**Purpose:**\nAdds a 20-second delay before rechecking Replicate’s image status.\n\n**Notes:**\n\n* Replicate image generation takes ~10–20 seconds usually.\n* You can increase or decrease the wait time depending on your model speed.\n* Prevents rate-limit errors by spacing out API calls.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "e4691aa3-b13b-447a-9a13-86787ecacac6",
      "name": "스티커 노트6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1456,
        -656
      ],
      "parameters": {
        "color": 4,
        "width": 352,
        "height": 400,
        "content": "### ⏳ **HTTP Request1 (Replicate Polling)**\n\n**Purpose:**\nFetches the status of the image generation request from Replicate using the returned `prediction ID`.\n\n**Credentials Required:**\n\n* Same Replicate Bearer Token as above.\n\n**Notes:**\n\n* The polling is used in combination with the **Wait** and **If** nodes.\n* Returns `status` = `succeeded` once image is ready.\n* You can also extract error messages if the job fails."
      },
      "typeVersion": 1
    },
    {
      "id": "a363eaf7-f137-4977-aec6-e714d761f3ff",
      "name": "스티커 노트7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1888,
        -592
      ],
      "parameters": {
        "width": 304,
        "height": 336,
        "content": "### ✅ **If**\n\n**Purpose:**\nChecks if the Replicate image generation has **succeeded**.\n\n**Notes:**\n\n* If the status = “succeeded,” workflow proceeds to the next step.\n* If not, it loops back to **HTTP Request1** to poll again.\n* This ensures the workflow doesn’t break while waiting for long image generations.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "bdec9233-16ac-4054-b953-69e6351b9c50",
      "name": "스티커 노트8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2128,
        -80
      ],
      "parameters": {
        "width": 304,
        "height": 352,
        "content": "### 🧩 **Edit Fields (Set Node)**\n\n**Purpose:**\nCombines cleaned text and generated image URL into a final JSON payload for publishing.\n\n**Notes:**\n\n* Merges `title`, `slug`, `excerpt`, `content`, and `image_url` fields into one structured object.\n* Adds `\"published\": true` flag for Supabase insert.\n* You can add extra custom fields like `category` or `author` here easily.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "f00d7334-5237-4b3c-ac73-d07164ad5ab7",
      "name": "스티커 노트9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2272,
        -720
      ],
      "parameters": {
        "color": 4,
        "width": 432,
        "height": 480,
        "content": "### 🚀 **Publish to Supabase (HTTP Request)**\n\n**Purpose:**\nPublishes the final blog post to Supabase via your custom function endpoint.\n\n**Credentials Required:**\n\n* `Supabase Header Auth` (e.g., `Authorization: Bearer YOUR_KEY`)\n\n**Notes:**\n\n* The example endpoint is:\n\n  ```\n  https://your-project.supabase.co/functions/v1/blog-api\n  ```\n* Make sure your Supabase Edge Function expects JSON with the fields provided.\n* You can replace this with your own CMS (WordPress, Ghost, Webflow, etc.) API endpoint."
      },
      "typeVersion": 1
    },
    {
      "id": "5fe82ef4-24c2-46ae-b0de-e6986bcb3668",
      "name": "스티커 노트10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2704,
        -80
      ],
      "parameters": {
        "color": 2,
        "width": 336,
        "height": 480,
        "content": "### 💬 **Slack Notification**\n\n**Purpose:**\nNotifies your Slack channel with the published blog details.\n\n**Credentials Required:**\n\n* Slack API token (with `chat:write` permission).\n\n**Notes:**\n\n* Message includes blog title, slug, and URL (`https://utsltech.com/blog/{{slug}}`).\n* You can customize channel name and message formatting (supports Block Kit).\n* Great for instant visibility of published content.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "b1208c9f-d79c-405a-8d1c-96d0a5ec7389",
      "name": "스티커 노트11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -240,
        -816
      ],
      "parameters": {
        "width": 480,
        "height": 336,
        "content": "## 🧩 General Notes for Template\n\n* **All credentials** should be created before importing the workflow.\n* **Error handling:** This workflow includes a fallback for Gemini output; you can add a global error workflow for API failures.\n* **Customization:** You can easily extend the flow to auto-share to LinkedIn, Twitter, or email subscribers.\n* **Runtime:** Average runtime ~1–2 minutes depending on image generation time.\n* **Timezone:** Set to `Asia/Kolkata` by default — adjust if needed in workflow settings.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "13f542b7-566c-429d-ba5d-45a63b7fd801",
      "name": "스티커 노트12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1040,
        -816
      ],
      "parameters": {
        "width": 784,
        "height": 1696,
        "content": "The **AI Blog Creator with Gemini, Replicate Image, Supabase Publishing & Slack** is a fully automated content generation and publishing workflow designed for modern marketing and SaaS teams.\nIt automatically fetches the latest industry trends, generates SEO-optimized blogs using AI, creates a relevant featured image, publishes the post to your CMS (e.g., Supabase or custom API), and notifies your team via Slack all on a daily schedule.\n\nThis workflow connects multiple services NewsAPI, Google Gemini, Replicate, Supabase, and Slack into one intelligent content pipeline that runs hands-free once set up.\n\n---\n\n### **✨ Features**\n\n* 📰 **Fetch Trending Topics** — pulls the latest news or updates from your selected industry (via NewsAPI).\n* 🤖 **AI Topic Generation** — Gemini suggests trending blog topics relevant to AI, SaaS, and Automation.\n* 📝 **AI Blog Authoring** — Gemini then writes a full 1200-1500 word SEO-optimized article in Markdown.\n* 🧹 **Smart JSON Cleaner** — A resilient code node parses Gemini’s output and ensures clean, structured data.\n* 🖼️ **Auto-Generated Image** — Replicate’s Ideogram model creates a blog cover image based on the content prompt.\n* 🌐 **Automatic Publishing** — Posts are automatically published to your Supabase or custom backend.\n* 💬 **Slack Notification** — Notifies your team with blog details and live URL.\n* ⏰ **Fully Scheduled** — Runs automatically every day at your preferred time (default 10 AM IST).\n\n---\n\n### **⚙️ Workflow Structure**\n\n| Step | Node                                | Purpose                                         |\n| ---- | ----------------------------------- | ----------------------------------------------- |\n| 1    | **Schedule Trigger**                | Runs daily at 10 AM                             |\n| 2    | **Fetch Industry Trends (NewsAPI)** | Retrieves trending articles                     |\n| 3    | **Message a model (Gemini)**        | Generates trending topic ideas                  |\n| 4    | **Message a model1 (Gemini)**       | Writes full SEO blog content                    |\n| 5    | **Code in JavaScript**              | Cleans, validates, and normalizes Gemini output |\n| 6    | **HTTP Request (Replicate)**        | Generates an image using Ideogram               |\n| 7    | **HTTP Request1**                   | Retrieves generated image URL                   |\n| 8    | **Wait + If**                       | Polls until image generation succeeds           |\n| 9    | **Edit Fields**                     | Assembles blog fields into final JSON           |\n| 10   | **Publish to Supabase**             | Posts to your CMS                               |\n| 11   | **Slack Notification**              | Sends message to your Slack channel             |\n\n---\n\n### **🔧 Setup Instructions**\n\n1. **Import the Workflow** in n8n and enable it.\n2. Create the following credentials:\n\n   * **NewsAPI (Query Auth)** — from [https://newsapi.org](https://newsapi.org)\n   * **Google Gemini (PaLM API)** — use your Gemini API key\n   * **Replicate (Bearer Auth)** — API key from [https://replicate.com/account](https://replicate.com/account)\n   * **Supabase (Header Auth)** — endpoint to your `/functions/v1/blog-api` (set your key in header)\n   * **Slack API** — create a Slack App token with `chat:write` permission\n3. Edit the **NewsAPI URL** query parameter to match your industry (e.g., `q=AI automation SaaS`).\n4. Update the **Supabase publish URL** to your project endpoint if needed.\n5. Adjust the **Slack Channel** name under “Slack Notification”.\n6. (Optional) Change the **Schedule Trigger** time as per your timezone.\n\n---\n\n### **💡 Notes & Tips**\n\n* The **Code in JavaScript** node is robust against malformed or extra text in Gemini output — it sanitizes Markdown and reconstructs clean JSON safely.\n* You can replace Supabase with any CMS or Webhook endpoint by editing the “Publish to Supabase” node.\n* The Replicate model used is `ideogram-ai/ideogram-v3-turbo` — you can swap it with Stable Diffusion or another model for different aesthetics.\n* Use the `slug` field in your blog URLs for SEO-friendly links.\n* Test with one manual execution before activating scheduled runs.\n* If Slack notification fails, verify the token scopes and channel permissions.\n\n"
      },
      "typeVersion": 1
    }
  ],
  "active": true,
  "pinData": {},
  "settings": {
    "timezone": "Asia/Kolkata",
    "callerPolicy": "workflowsFromSameOwner",
    "errorWorkflow": "EmPnnzwJEHxMuJaw",
    "executionOrder": "v1",
    "saveExecutionProgress": true,
    "saveDataErrorExecution": "all"
  },
  "versionId": "bc157604-a8a8-4745-a98d-d8b10da1b1ab",
  "connections": {
    "e2f813a3-1808-44f7-9bae-842d8d6cecbc": {
      "main": [
        [
          {
            "node": "b300ab84-eeea-42ea-a609-6bff06da4846",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "35e16700-c40d-4e8b-abda-a55b193b7e1f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "02a8a518-fb7d-4f13-b72d-25dcbacfb033": {
      "main": [
        [
          {
            "node": "e2f813a3-1808-44f7-9bae-842d8d6cecbc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "b300ab84-eeea-42ea-a609-6bff06da4846": {
      "main": [
        [
          {
            "node": "2c641b4b-9ce0-472d-a970-714d6a630f0c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5ecb7538-6358-4d89-ac55-8e4539f8d42a": {
      "main": [
        [
          {
            "node": "5da2d4ee-d7b0-441a-8523-067a17182c6a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5da2d4ee-d7b0-441a-8523-067a17182c6a": {
      "main": [
        [
          {
            "node": "1369e40f-2008-4fb7-9123-d17b02a7d42d",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "df01fb3f-d7dd-4d2b-9581-24df4472b3ea": {
      "main": [
        [
          {
            "node": "e45d33d9-2fc2-476c-b0ff-63d16b30111a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "1369e40f-2008-4fb7-9123-d17b02a7d42d": {
      "main": [
        [
          {
            "node": "6c7dfb6f-4f83-4d65-bea0-56c12a7b5393",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "17fcce85-bdf1-4c21-848a-3ce667e3aab5": {
      "main": [
        []
      ]
    },
    "2c641b4b-9ce0-472d-a970-714d6a630f0c": {
      "main": [
        [
          {
            "node": "17fcce85-bdf1-4c21-848a-3ce667e3aab5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "e45d33d9-2fc2-476c-b0ff-63d16b30111a": {
      "main": [
        [
          {
            "node": "5ecb7538-6358-4d89-ac55-8e4539f8d42a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "35e16700-c40d-4e8b-abda-a55b193b7e1f": {
      "main": [
        [
          {
            "node": "02a8a518-fb7d-4f13-b72d-25dcbacfb033",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6c7dfb6f-4f83-4d65-bea0-56c12a7b5393": {
      "main": [
        [
          {
            "node": "35e16700-c40d-4e8b-abda-a55b193b7e1f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
자주 묻는 질문

이 워크플로우를 어떻게 사용하나요?

위의 JSON 구성 코드를 복사하여 n8n 인스턴스에서 새 워크플로우를 생성하고 "JSON에서 가져오기"를 선택한 후, 구성을 붙여넣고 필요에 따라 인증 설정을 수정하세요.

이 워크플로우는 어떤 시나리오에 적합한가요?

고급

유료인가요?

이 워크플로우는 완전히 무료이며 직접 가져와 사용할 수 있습니다. 다만, 워크플로우에서 사용하는 타사 서비스(예: OpenAI API)는 사용자 직접 비용을 지불해야 할 수 있습니다.

워크플로우 정보
난이도
고급
노드 수25
카테고리-
노드 유형9
난이도 설명

고급 사용자를 위한 16+개 노드의 복잡한 워크플로우

저자
Parag Javale

Parag Javale

@pollar-beer

Tech driven creative who turns ideas into impact. I blend storytelling, product strategy, and automation whether it’s hooky audio promos, smart LMS platforms, or AI driven workflows. I help businesses grab attention, streamline ops, and scale fast. Big on data, experiments, and building digital solutions that actually work.

외부 링크
n8n.io에서 보기

이 워크플로우 공유

카테고리

카테고리: 34