AutomationFlowsAI & RAG › Generate Seo-optimized Blog Content with Google Gemini, RSS Feeds and Telegram

Generate Seo-optimized Blog Content with Google Gemini, RSS Feeds and Telegram

ByBaris Cem Ant @baris on n8n.io

This n8n workflow automates the entire content creation process by monitoring specified RSS feeds for new articles. It then leverages Google Gemini AI to generate comprehensive, SEO-optimized blog posts inspired by these articles, creates unique cover images, and distributes the…

Event trigger★★★★☆ complexityAI-powered27 nodesGoogle GeminiS3AWS DynamoDBTelegramRss Feed Read Trigger
AI & RAG Trigger: Event Nodes: 27 Complexity: ★★★★☆ AI nodes: yes Added:
Generate Seo-optimized Blog Content with Google Gemini, RSS Feeds and Telegram — n8n workflow card showing Google Gemini, S3, AWS DynamoDB integration

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

This workflow follows the Googlegemini → Telegram 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
{
  "id": "8e45QHRb4UraY7xY",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Blog",
  "tags": [],
  "nodes": [
    {
      "id": "1c5be898-3898-4725-b9f1-210f88fa80b5",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        -1744,
        240
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineAll"
      },
      "typeVersion": 3.2
    },
    {
      "id": "50fae4b8-17d4-4b4b-95f9-937d1d646b80",
      "name": "Merge1",
      "type": "n8n-nodes-base.merge",
      "position": [
        -848,
        96
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineAll"
      },
      "typeVersion": 3.2
    },
    {
      "id": "d50e6152-e2df-4e84-833e-25d736197b95",
      "name": "Gemini Content Generation",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        -2544,
        176
      ],
      "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 writer. Your task is to generate high-quality, SEO-focused blog posts in English only. Ensure that your output is well-structured, includes relevant keywords, and follows best practices for search engine optimization. Do not provide content in any language other than English."
            },
            {
              "content": "=Follow the instructions below to generate a high-quality, SEO-focused blog post. You must return **ONLY** the JSON specified in the `Mandatory JSON format` section.\n\n## 0. Blog Content Information\n- **Shared News:** `[{{ $json.link }}]`\n\n## 1. Core Information\n- **Title:** [Insert a compelling, keyword-rich title here]\n- **Category:** [Specify the blog category]\n\n## 2. SEO Metadata\n- **Meta Title / Slug:** [Craft an SEO-friendly title under 60 characters. The slug should be a URL-friendly version, e.g., `how-to-write-seo-blog-post`]\n- **Meta Description:** [Write a compelling summary, under 160 characters, that includes the primary keyword and encourages clicks.]\n\n3. Visuals\n\n    Image Generation Prompt: Instead of providing advice, you will generate a direct, detailed prompt for an AI image generator (like an Imagen model). This prompt will be used to create the cover image for the blog post.\n    \n\n    Prompt Style: The prompt must be a series of descriptive keywords and phrases separated by commas. It must NOT be a sentence or a request (e.g., do not use \"Generate a picture of...\"). The prompt should be based on the core theme or a key metaphor from the generated blog content.\n\n    Examples:\n\n        Good Prompt: Photorealistic image, a futuristic courtroom with glowing digital gavels, data streams in the background, cinematic lighting, 4k resolution.\n\n        Good Prompt: Vector illustration, a magnifying glass examining lines of code on a computer screen, vibrant colors, minimalist style.\n\n        Bad Prompt: Please create a picture about Google's antitrust case.\n\n## 4. Body Content (Markdown)\n\n# [Main Title - Should match the 'Title' field above]\n\n## Introduction\n[Hook the reader in the first sentence. Clearly state the problem you're solving or the question you're answering. Promise a valuable takeaway. Ensure the primary keyword appears naturally within the first 100 words.]\n\n## [Subheading 1 - Use a Secondary Keyword]\n[Dive into the first main point. Use short paragraphs, bullet points, and **bold text** to make the content scannable and easy to read.]\n\n## [Subheading 2 - Use Another Secondary Keyword]\n[Elaborate on the next point. Consider adding a data point, a quote from an expert, or an embedded image to add credibility and break up the text.]\n\n## Conclusion\n[Summarize the key takeaways from the article. Avoid introducing new information. Provide a final, impactful thought or recommendation.]\n\n## Call to Action (CTA)\n[What is the single most important action the reader should take next? e.g., \"Leave a comment below with your favorite tip,\" \"Sign up for our free newsletter for more insights,\" or \"Check out our related product.\"]\n\n---\n\n## 5. Additional Sections\n\n### FAQ Section\n- **Question 1:** [A relevant question using a keyword]\n- **Answer 1:** [A concise and helpful answer]\n- **Question 2:** [Another relevant question]\n- **Answer 2:** [Another concise answer]\n\n### References\n- [Authoritative Source Name](URL)\n- [Data/Statistic Source](URL)\n\n### Related Content (Internal Links)\n- [Title of an Existing Article on Your Site](URL)\n- [Another Relevant Article on Your Site](URL)\n\n---\n\n## 6. SEO & Quality Checklist\n- [ ] **Keyword Placement:** Primary keyword is in the Title, Meta Title, Introduction, and at least one Subheading.\n- [ ] **Keyword Usage:** Secondary keywords are used naturally throughout the body and subheadings.\n- [ ] **Content Value:** The content is original, comprehensive, and provides more value than existing top-ranking articles.\n- [ ] **Readability:** Sentences and paragraphs are short. The language is clear and easy to understand for the target audience.\n- [ ] **Internal Links:** At least 2-3 relevant internal links are included.\n- [ ] **External Links:** At least 1-2 external links to high-authority, non-competing websites are included.\n- [ ] **Visuals:** All images have descriptive alt text that includes keywords where appropriate.\n- [ ] **Structured Data:** Consider if `Article` or `FAQPage` schema is appropriate to help search engines understand the content.\n\n---\n### **Mandatory JSON format:**\nYou must provide your response using only the following JSON structure. Do not include any text, explanations, or markdown formatting before or after the JSON object.\n\n```json\n{\n  \"title\": \"[Enter a Compelling, Unique, and Keyword-Rich Title Here]\",\n  \"description\": \"[Write a brief and effective description summarizing the blog post's topic, maximum 80 characters.]\",\n  \"slug\": \"[seo-friendly-url-structure-based-on-title]\",\n  \"image_generation_prompt\": \"[A comma-separated, descriptive prompt for an AI image generator, reflecting the blog's core theme. E.g., 'vector illustration of a rocket ship launching from a laptop screen, vibrant colors, minimalist style']\",\n  \"author\": \"[Author's Name or ID]\",\n  \"category\": \"[Relevant Blog Category (e.g., SEO, Artificial Intelligence)]\",\n  \"body\": \"<!-- BLOG CONTENT (MARKDOWN) -->\\n\\n# [Enter a Compelling, Unique, and Keyword-Rich Title Here]\\n\\n## Introduction\\n[Hook the reader in the first sentence. Clearly state the problem you're solving or the question you're answering. Ensure the primary keyword appears naturally within the first 100 words. Promise a valuable takeaway for the reader.]\\n\\n## [Subheading 1 Using a Secondary Keyword]\\n[Elaborate on the first main point here. Use short paragraphs, bullet points, and **bold text** to improve readability. Make the content easy to scan.]\\n\\n## [Subheading 2 Using a Different Secondary Keyword]\\n[Explain the next key point. Consider adding a data point, a quote from an expert, or an embedded image to add credibility and enrich the text.]\\n\\n---\\n\\n## Conclusion\\n[Briefly summarize the main takeaways from the article. Avoid introducing new information. Provide a final, impactful thought or recommendation.]\\n\\n## Call to Action (CTA)\\n[What is the next step you want the reader to take? E.g., 'Leave a comment below,' 'Sign up for our free newsletter,' or 'Check out our related product.']\\n\\n---\\n\\n### Frequently Asked Questions (FAQ)\\n\\n**Question 1: [A frequently asked question that includes a keyword]**\\n\\n*Answer 1: [Answer the question clearly and concisely.]*\\n\\n**Question 2: [Another relevant, popular question]**\\n\\n*Answer 2: [Provide a brief and helpful answer.]*\\n\\n---\\n\\n### References\\n\\n- [Authoritative Source Name](URL)\\n- [Data/Statistic Source](URL)\\n\\n### Related Content (Internal Links)\\n\\n- [Title of an Existing Article on Your Site](URL)\\n- [Another Relevant Article on Your Site](URL)\",\n  \"seo\": {\n    \"metaTitle\": \"[SEO-Friendly Meta Title, Under 60 Characters]\",\n    \"metaDescription\": \"[Write a Meta Description Under 160 Characters That Includes the Keyword and Encourages Clicks.]\"\n  }\n}\n```"
            }
          ]
        }
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "d80f845d-3c6f-4570-a42c-78976d237e4c",
      "name": "Json Parser",
      "type": "n8n-nodes-base.code",
      "position": [
        -2192,
        176
      ],
      "parameters": {
        "jsCode": "/**\n * N8N'den gelen Gemini response'unu parse eder ve JSON'a \u00e7evirir.\n * Birden fazla strateji kullanarak g\u00fcvenilir parsing sa\u011flar.\n *\n * @param {string} geminiResponse - N8N'den gelen ham Gemini yan\u0131t\u0131\n * @returns {object|null} Parse edilmi\u015f JSON objesi veya null\n */\nfunction parseGeminiResponse(geminiResponse) {\n    // Giri\u015f kontrol\u00fc\n    if (!geminiResponse || typeof geminiResponse !== 'string') {\n        console.error(\"Bo\u015f veya ge\u00e7ersiz Gemini response'u\");\n        return null;\n    }\n    \n    console.log(`Parsing Gemini response, length: ${geminiResponse.length} characters`);\n    \n    // Response'u temizle\n    const cleanedResponse = cleanGeminiResponse(geminiResponse);\n    \n    if (!cleanedResponse.trim()) {\n        console.error(\"Temizlendikten sonra bo\u015f response\");\n        return null;\n    }\n\n    // JSON parse etme stratejileri\n    const parseStrategies = [\n        directJsonParse,           // Direkt parse\n        extractFirstJsonObject,   // \u0130lk JSON nesnesini bul\n        fixAndParseJson,         // Yayg\u0131n sorunlar\u0131 d\u00fczelt\n        regexExtractJson         // Regex ile JSON bul\n    ];\n    \n    for (let i = 0; i < parseStrategies.length; i++) {\n        try {\n            const result = parseStrategies[i](cleanedResponse);\n            if (result && typeof result === 'object') {\n                console.log(`JSON ba\u015far\u0131yla parse edildi (strateji ${i + 1})`);\n                \n                // Blog yap\u0131s\u0131n\u0131 validate et\n                if (validateBlogStructure(result)) {\n                    console.log(\"Ge\u00e7erli blog JSON yap\u0131s\u0131 bulundu\");\n                } else {\n                    console.warn(\"Blog JSON yap\u0131s\u0131 eksik alanlar i\u00e7eriyor\");\n                }\n                \n                return result;\n            }\n        } catch (error) {\n            console.log(`Parse stratejisi ${i + 1} ba\u015far\u0131s\u0131z: ${error.message}`);\n            continue;\n        }\n    }\n    \n    // T\u00fcm stratejiler ba\u015far\u0131s\u0131z\n    const responsePreview = cleanedResponse.length > 500 \n        ? cleanedResponse.substring(0, 500) + \"...\" \n        : cleanedResponse;\n    \n    console.error(\n        `Gemini response hi\u00e7bir strateji ile parse edilemedi. ` +\n        `Response uzunlu\u011fu: ${cleanedResponse.length} karakter. ` +\n        `Response \u00f6nizlemesi: ${responsePreview}`\n    );\n    \n    return null;\n}\n\n/**\n * Gemini response'unu temizler - markdown, extra whitespace vs.\n */\nfunction cleanGeminiResponse(response) {\n    // Markdown code block'lar\u0131n\u0131 kald\u0131r\n    response = response.replace(/```json\\s*/gi, '');\n    response = response.replace(/```\\s*/g, '');\n    \n    // Ba\u015flang\u0131\u00e7 ve son whitespace'leri temizle\n    response = response.trim();\n    \n    // E\u011fer multiple JSON objesi varsa sadece ilkini al\n    if ((response.match(/\\{/g) || []).length > 1) {\n        response = extractFirstCompleteJson(response);\n    }\n    \n    return response;\n}\n\n/**\n * \u0130lk tam JSON nesnesini \u00e7\u0131kar\u0131r\n */\nfunction extractFirstCompleteJson(text) {\n    const firstBrace = text.indexOf('{');\n    if (firstBrace === -1) {\n        return text;\n    }\n    \n    let braceCount = 0;\n    for (let i = firstBrace; i < text.length; i++) {\n        if (text[i] === '{') {\n            braceCount++;\n        } else if (text[i] === '}') {\n            braceCount--;\n            if (braceCount === 0) {\n                return text.substring(firstBrace, i + 1);\n            }\n        }\n    }\n    \n    return text; // Tam JSON bulunamazsa orijinali d\u00f6nd\u00fcr\n}\n\n/**\n * Direkt JSON parse\n */\nfunction directJsonParse(text) {\n    return JSON.parse(text);\n}\n\n/**\n * \u0130lk ge\u00e7erli JSON nesnesini bulur\n */\nfunction extractFirstJsonObject(text) {\n    const firstBrace = text.indexOf('{');\n    if (firstBrace === -1) {\n        throw new Error(\"JSON objesi bulunamad\u0131\");\n    }\n    \n    let braceCount = 0;\n    for (let i = firstBrace; i < text.length; i++) {\n        if (text[i] === '{') {\n            braceCount++;\n        } else if (text[i] === '}') {\n            braceCount--;\n            if (braceCount === 0) {\n                const jsonText = text.substring(firstBrace, i + 1);\n                return JSON.parse(jsonText);\n            }\n        }\n    }\n    \n    throw new Error(\"Tamamlanmam\u0131\u015f JSON objesi\");\n}\n\n/**\n * Yayg\u0131n JSON sorunlar\u0131n\u0131 d\u00fczeltir\n */\nfunction fixAndParseJson(text) {\n    // Eksik kapan\u0131\u015f parantezlerini tamamla\n    const openBraces = (text.match(/\\{/g) || []).length;\n    const closeBraces = (text.match(/\\}/g) || []).length;\n    \n    if (openBraces > closeBraces) {\n        text += '}'.repeat(openBraces - closeBraces);\n    }\n    \n    // Trailing comma'lar\u0131 kald\u0131r\n    text = text.replace(/,\\s*}/g, '}');\n    text = text.replace(/,\\s*]/g, ']');\n    \n    return JSON.parse(text);\n}\n\n/**\n * Regex ile JSON bulur\n */\nfunction regexExtractJson(text) {\n    // Nested JSON pattern\n    const jsonPattern = /\\{(?:[^{}]|(?:\\{(?:[^{}]|(?:\\{[^{}]*\\})*)*\\})*)*\\}/g;\n    const matches = text.match(jsonPattern);\n    \n    if (!matches || matches.length === 0) {\n        throw new Error(\"Regex ile JSON pattern bulunamad\u0131\");\n    }\n    \n    // En uzun match'i al\n    const longestMatch = matches.reduce((a, b) => a.length > b.length ? a : b);\n    return JSON.parse(longestMatch);\n}\n\n/**\n * Blog JSON yap\u0131s\u0131n\u0131n gerekli alanlar\u0131 i\u00e7erip i\u00e7ermedi\u011fini kontrol eder\n */\nfunction validateBlogStructure(data) {\n    if (!data || typeof data !== 'object') {\n        return false;\n    }\n    \n    // Temel gerekli alanlar\n    const requiredFields = ['title', 'description', 'slug', 'body'];\n    \n    const missingFields = [];\n    for (const field of requiredFields) {\n        if (!data[field]) {\n            missingFields.push(field);\n        }\n    }\n    \n    if (missingFields.length > 0) {\n        console.warn(`Eksik gerekli alanlar: ${missingFields.join(', ')}`);\n        return false;\n    }\n    \n    // SEO alanlar\u0131n\u0131 kontrol et (opsiyonel ama \u00f6nemli)\n    if (data.seo && typeof data.seo === 'object') {\n        const seoFields = ['metaTitle', 'metaDescription'];\n        const missingSeo = seoFields.filter(field => !data.seo[field]);\n        if (missingSeo.length > 0) {\n            console.warn(`Eksik SEO alanlar\u0131: ${missingSeo.join(', ')}`);\n        }\n    }\n    \n    return true;\n}\n\n/**\n * Parse edilmi\u015f JSON'dan blog i\u00e7eri\u011fini \u00e7\u0131kar\u0131r ve d\u00fczenler\n */\nfunction extractBlogContent(data) {\n    if (!data || typeof data !== 'object') {\n        throw new Error(\"Ge\u00e7ersiz data format\u0131\");\n    }\n    \n    // Blog i\u00e7eri\u011fini \u00e7\u0131kar\n    const blogContent = {\n        title: data.title || '',\n        description: data.description || '',\n        slug: data.slug || '',\n        body: data.body || '',\n        author: data.author || 'AI Content Generator',\n        category: data.category || 'Genel',\n        image_generation_prompt: data.image_generation_prompt || '',\n        seo: data.seo || {},\n        created_at: '2025-09-03 07:48:33', // Current timestamp\n        created_by: '0Baris', // Current user\n        status: 'draft'\n    };\n    \n    // SEO alanlar\u0131n\u0131 d\u00fczenle\n    if (!blogContent.seo || Object.keys(blogContent.seo).length === 0) {\n        blogContent.seo = {\n            metaTitle: blogContent.title.length > 60 \n                ? blogContent.title.substring(0, 60) + '...' \n                : blogContent.title,\n            metaDescription: blogContent.description.length > 160 \n                ? blogContent.description.substring(0, 160) + '...' \n                : blogContent.description\n        };\n    }\n    \n    // Body'den blog content comment'ini temizle\n    if (blogContent.body) {\n        blogContent.body = blogContent.body\n            .replace(/<!-- BLOG CONTENT \\(MARKDOWN\\) -->\\s*/g, '')\n            .trim();\n    }\n    \n    return blogContent;\n}\n\n/**\n * N8N'den gelen Gemini response'unu i\u015fler ve blog i\u00e7in haz\u0131r hale getirir\n */\nfunction processN8nGeminiResponse(geminiResponse) {\n    try {\n        // Response'u parse et\n        const parsedData = parseGeminiResponse(geminiResponse);\n        \n        if (!parsedData) {\n            throw new Error(\"Gemini response parse edilemedi\");\n        }\n        \n        // Blog i\u00e7eri\u011fini \u00e7\u0131kar ve d\u00fczenle\n        const blogContent = extractBlogContent(parsedData);\n        \n        console.log(`Blog i\u00e7eri\u011fi ba\u015far\u0131yla i\u015flendi: ${blogContent.title}`);\n        return blogContent;\n        \n    } catch (error) {\n        console.error(`Gemini response i\u015flenirken hata: ${error.message}`);\n        return null;\n    }\n}\n\n// --- N8N KULLANIMI ---\n\n// Gemini'den gelen yan\u0131t\u0131n n8n'deki yolu\n// Mevcut kodunuzdaki gibi\nconst geminiResponseText = $input.first().json.content.parts[0].text;\n\n// Geli\u015ftirilmi\u015f fonksiyonu \u00e7a\u011f\u0131r\nconst cleanedData = processN8nGeminiResponse(geminiResponseText);\n\n// E\u011fer i\u015flem ba\u015far\u0131s\u0131z olursa, i\u015f ak\u0131\u015f\u0131n\u0131n bu kolunun devam etmesini engelle\nif (cleanedData === null) {\n    console.error(\"JSON temizleme ve ayr\u0131\u015ft\u0131rma i\u015flemi ba\u015far\u0131s\u0131z oldu. \u0130\u015f ak\u0131\u015f\u0131 bu koldan devam etmeyecek.\");\n    return []; // Bo\u015f dizi, n8n'in bu yolu sonland\u0131rmas\u0131n\u0131 sa\u011flar\n}\n\n// Ba\u015far\u0131l\u0131 olursa, temizlenmi\u015f veriyi bir sonraki d\u00fc\u011f\u00fcme g\u00f6nder\nreturn {\n    json: cleanedData\n};"
      },
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "83ec7e8a-a3de-4a43-b88a-c8950359b58d",
      "name": "Slug Selector",
      "type": "n8n-nodes-base.set",
      "position": [
        -1968,
        176
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "ad97cbd6-6489-4ef7-a597-3e9428b83d54",
              "name": "slug",
              "type": "string",
              "value": "={{ $json.slug }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "5ac3ee91-030b-4d8a-baa1-17d822063eb0",
      "name": "Generate Image",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        -1968,
        432
      ],
      "parameters": {
        "prompt": "=**Image Size: 1200x630 aspect Ratio 1.91:1**\n{{ $json.image_generation_prompt }}",
        "modelId": {
          "__rl": true,
          "mode": "id",
          "value": "models/gemini-2.5-flash-image-preview"
        },
        "options": {},
        "resource": "image"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "1cd97703-acb9-4423-9845-e2bd92c1f106",
      "name": "Image Renamer",
      "type": "n8n-nodes-base.set",
      "position": [
        -1520,
        240
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "89f151ed-4b34-4a02-b3b6-f658cb931a5b",
              "name": "fileName",
              "type": "string",
              "value": "={{ $json.slug }}.{{ $json.fileExtension }}"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "4b1f8445-6124-488d-9bae-07c57341695d",
      "name": "Upload Image to Cloudflare R2 Storage",
      "type": "n8n-nodes-base.s3",
      "position": [
        -1296,
        240
      ],
      "parameters": {
        "fileName": "={{ $json.fileName }}",
        "operation": "upload",
        "bucketName": "saywize-media",
        "additionalFields": {}
      },
      "credentials": {
        "s3": {
          "name": "<your credential>"
        }
      },
      "executeOnce": true,
      "typeVersion": 1
    },
    {
      "id": "2e9d5e0f-b7ff-483e-8eb6-ce6f2b950134",
      "name": "If Statement",
      "type": "n8n-nodes-base.if",
      "position": [
        -1072,
        240
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "9dbfe1dc-732d-4bd1-a539-fad98a10bd61",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.success }}",
              "rightValue": "tr"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "8d4d08f4-7efb-40bd-b940-d30a2de418cf",
      "name": "If Statement2",
      "type": "n8n-nodes-base.if",
      "position": [
        -624,
        96
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "ed82746b-e6e9-46d0-a65a-be5df2787261",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": true,
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "56ad3868-2136-4303-926c-e18873ab35a5",
      "name": "Get an item",
      "type": "n8n-nodes-base.awsDynamoDb",
      "position": [
        -3216,
        32
      ],
      "parameters": {
        "keysUi": {
          "keyValues": [
            {
              "key": "article_url",
              "value": "={{ $json.link }}"
            }
          ]
        },
        "operation": "get",
        "tableName": "processed_rss_links",
        "additionalFields": {}
      },
      "credentials": {
        "aws": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "215b6a36-f2c8-4aca-8a4a-5e0ea5f58bcd",
      "name": "Loop Over Items1",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -3440,
        512
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "e8046541-4995-439b-9b2f-7c1398a7e6a6",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -3440,
        320
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "b3e57766-3f8d-436c-8854-fb99d23f9bb0",
      "name": "Loop Over Items2",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -3440,
        128
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "ec5853c0-6c18-497c-a086-71927d81e702",
      "name": "Create or update an item",
      "type": "n8n-nodes-base.awsDynamoDb",
      "position": [
        -2480,
        368
      ],
      "parameters": {
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "article_url",
              "fieldValue": "={{ $json.link }}"
            }
          ]
        },
        "tableName": "processed_rss_links",
        "additionalFields": {}
      },
      "credentials": {
        "aws": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "0860adb2-b3a4-4dc8-bf99-ab6745c41b72",
      "name": "Merge3",
      "type": "n8n-nodes-base.merge",
      "position": [
        -2992,
        368
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineAll"
      },
      "typeVersion": 3.2
    },
    {
      "id": "7ed70f9a-44c3-4b0a-aae0-2bb9b1f7225a",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        -2768,
        368
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "4bf9f505-0f7f-4174-832f-f384d955a364",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{ $json.article_url }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "0b961b43-8452-411e-9729-e91e01c86cab",
      "name": "Last Content Detection",
      "type": "n8n-nodes-base.set",
      "position": [
        -400,
        96
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "e5b17521-2fdb-44c4-8e78-5d3b42298faa",
              "name": "title",
              "type": "string",
              "value": "={{ $json.title }}"
            },
            {
              "id": "bfb86d94-85d0-4ec8-a91b-063e44f2845d",
              "name": "description",
              "type": "string",
              "value": "={{ $json.description }}"
            },
            {
              "id": "84cf076d-adcd-4f85-a2b3-9b348c38160c",
              "name": "slug",
              "type": "string",
              "value": "={{ $json.slug }}"
            },
            {
              "id": "cbdbf7c6-bdeb-4f66-9eb5-76d23372af74",
              "name": "body",
              "type": "string",
              "value": "={{ $json.body }}"
            },
            {
              "id": "eb4859eb-9dcf-4c97-ad30-d300fa3d3510",
              "name": "author",
              "type": "string",
              "value": "Baris's Agent"
            },
            {
              "id": "7036ec5a-f77a-45d9-bdfd-0caa6fb17524",
              "name": "category",
              "type": "string",
              "value": "={{ $json.category }}"
            },
            {
              "id": "779d8231-527b-4aa0-9c32-de3905c315a7",
              "name": "seo.metaTitle",
              "type": "string",
              "value": "={{ $json.seo.metaTitle }}"
            },
            {
              "id": "f759dc75-88cc-465f-ac1d-d67802336fd8",
              "name": "seo.metaDescription",
              "type": "string",
              "value": "={{ $json.seo.metaDescription }}"
            },
            {
              "id": "e2575609-5e15-485b-9208-d223d7840b49",
              "name": "image_url",
              "type": "string",
              "value": "=https://cdn.saywize.com/{{ $json.slug }}.png"
            },
            {
              "id": "0de6b56d-ed3c-49d1-b4f0-f3e71b344146",
              "name": "article_url",
              "type": "string",
              "value": "={{ $('Merge3').item.json.link }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "3fbdd541-d0b3-4320-badb-ba20310864cc",
      "name": "Telegram Debugger",
      "type": "n8n-nodes-base.telegram",
      "position": [
        -2480,
        560
      ],
      "parameters": {
        "text": "=Since the article already exists, the blog post could not be created: {{ $json.article_url }}",
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "2c0d3019-3c4e-4115-b766-ae132b7ecff6",
      "name": "Telegram Debugger1",
      "type": "n8n-nodes-base.telegram",
      "position": [
        -848,
        336
      ],
      "parameters": {
        "text": "An error occurred during image creation.",
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "cabf5681-ddf1-4d56-b91a-f89b131c60dc",
      "name": "Telegram Debugger2",
      "type": "n8n-nodes-base.telegram",
      "position": [
        -400,
        288
      ],
      "parameters": {
        "text": "I encountered a problem while creating a blog.",
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "641358e2-fe79-42d7-bbae-39ba9e5ae8ae",
      "name": "Convert to File",
      "type": "n8n-nodes-base.convertToFile",
      "position": [
        -176,
        96
      ],
      "parameters": {
        "options": {
          "fileName": "={{ $json.slug }}.json"
        },
        "operation": "toJson"
      },
      "typeVersion": 1.1
    },
    {
      "id": "94a89dc2-71ec-4382-a9a6-cb957ae9dfed",
      "name": "RSS 1",
      "type": "n8n-nodes-base.rssFeedReadTrigger",
      "position": [
        -3664,
        128
      ],
      "parameters": {
        "feedUrl": "",
        "pollTimes": {
          "item": [
            {
              "mode": "everyHour"
            },
            {
              "mode": "everyWeek"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "1ff8b300-dbff-430d-8d33-0af8effd845d",
      "name": "RSS 2",
      "type": "n8n-nodes-base.rssFeedReadTrigger",
      "position": [
        -3664,
        320
      ],
      "parameters": {
        "feedUrl": "",
        "pollTimes": {
          "item": [
            {
              "mode": "everyWeek"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "86898f62-1f0d-4c57-a6d0-895bc1235190",
      "name": "RSS 3",
      "type": "n8n-nodes-base.rssFeedReadTrigger",
      "position": [
        -3664,
        512
      ],
      "parameters": {
        "feedUrl": "",
        "pollTimes": {
          "item": [
            {
              "hour": 12,
              "mode": "everyWeek",
              "weekday": "5"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "b08b2b93-864a-4e05-8b02-d47a7ba3c19f",
      "name": "Edit Chat ID",
      "type": "n8n-nodes-base.telegram",
      "position": [
        32,
        96
      ],
      "parameters": {
        "operation": "sendDocument",
        "binaryData": true,
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "6efc0a3d-d27e-40be-9f58-79f76883f3a0",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2880,
        -1040
      ],
      "parameters": {
        "width": 1136,
        "height": 1008,
        "content": "## Telegram ChatID and Bot Creation\n**Telegram** [Docs](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.telegram/message-operations/#send-sticker)\n\n### A Guide to BotFather and Userinfobot\n\nTelegram bots can automate tasks, provide information, and integrate with other services, offering a rich, interactive experience within the messaging app. Creating and managing these bots is handled by a primary bot called BotFather, while understanding user information can be done with the help of Userinfobot.\n\n### Creating a Bot with BotFather\n\nBotFather is the official Telegram bot that allows you to create and manage your own bots. The process is straightforward and doesn't require any coding knowledge to get started.\n\nHere is a step-by-step guide to creating a new bot:\n\n1.  **Start a chat with BotFather:** Open your Telegram app and search for the username `@BotFather` \u2013 be sure to look for the one with a blue verification checkmark. Start a chat with it.\n\n2.  **Initiate the creation process:** Type the command `/newbot` and send it.\n\n3.  **Name your bot:** BotFather will ask you to choose a name for your bot. This is the display name that users will see in their contact list.\n\n4.  **Choose a username:** Next, you will need to provide a unique username for your bot. This username must end with the word \"bot\" (e.g., `MyTestBot` or `my_test_bot`).\n\n5.  **Receive your token:** Once you have successfully chosen a name and a unique username, BotFather will generate a unique authentication token. This token is essential as it is used to control your bot and connect it to various platforms and APIs, so it is crucial to store it securely.\n\nAfter creating your bot, you can further customize it using various commands within BotFather. You can set a description, an about text, and a profile picture for your bot. The `/mybots` command will show you a list of your bots and allow you to edit their settings.\n\n### Understanding Userinfobot\n\nUserinfobot is a helpful utility bot that provides you with a Telegram user's information, most importantly their unique User ID. This ID is a numerical identifier that Telegram uses for accounts.\n\nThere are two primary ways to use Userinfobot:\n\n1.  **To get your own information:**\n    *   Search for `@userinfobot` in Telegram and start a chat.\n    *   Simply click the \"Start\" button or send the `/start` command.\n    *   The bot will immediately reply with your User ID, first name, last name (if you have one set), and your language code.\n\n2.  **To get another user's information:**\n    *   Forward a message from the desired user to your chat with Userinfobot.\n    *   The bot will then provide you with the User ID and name of the original sender of that message."
      },
      "typeVersion": 1
    }
  ],
  "active": true,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "fde55ab3-f3a5-4bf7-aac6-aa4d8b5c7954",
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "Gemini Content Generation",
            "type": "main",
            "index": 0
          },
          {
            "node": "Create or update an item",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Telegram Debugger",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "Image Renamer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "RSS 1": {
      "main": [
        [
          {
            "node": "Loop Over Items2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "RSS 2": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "RSS 3": {
      "main": [
        [
          {
            "node": "Loop Over Items1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge1": {
      "main": [
        [
          {
            "node": "If Statement2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge3": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get an item": {
      "main": [
        [
          {
            "node": "Merge3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Json Parser": {
      "main": [
        [
          {
            "node": "Generate Image",
            "type": "main",
            "index": 0
          },
          {
            "node": "Slug Selector",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Statement": {
      "main": [
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 1
          }
        ],
        [
          {
            "node": "Telegram Debugger1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Statement2": {
      "main": [
        [
          {
            "node": "Last Content Detection",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Telegram Debugger2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Image Renamer": {
      "main": [
        [
          {
            "node": "Upload Image to Cloudflare R2 Storage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slug Selector": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Image": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Convert to File": {
      "main": [
        [
          {
            "node": "Edit Chat ID",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "Get an item",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge3",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Loop Over Items1": {
      "main": [
        [],
        [
          {
            "node": "Get an item",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge3",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Loop Over Items2": {
      "main": [
        [],
        [
          {
            "node": "Get an item",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge3",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Last Content Detection": {
      "main": [
        [
          {
            "node": "Convert to File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gemini Content Generation": {
      "main": [
        [
          {
            "node": "Json Parser",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload Image to Cloudflare R2 Storage": {
      "main": [
        [
          {
            "node": "If Statement",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

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

About this workflow

This n8n workflow automates the entire content creation process by monitoring specified RSS feeds for new articles. It then leverages Google Gemini AI to generate comprehensive, SEO-optimized blog posts inspired by these articles, creates unique cover images, and distributes the…

Source: https://n8n.io/workflows/8363/ — 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

Most expense tracker apps (like Money Lover, Spendee, or Wallet) have a common friction point: Data Entry. You have to unlock your phone, find the app, wait for it to load, navigate menus, and manuall

Google Sheets, Google Gemini, Telegram +2
AI & RAG

Sales Lead Qualifier. Uses telegramTrigger, googleSheets, telegram, googleGemini. Event-driven trigger; 41 nodes.

Telegram Trigger, Google Sheets, Telegram +3
AI & RAG

This n8n workflow enables automated transcription of voice messages in Telegram groups with built-in access control and intelligent fallback mechanisms. It's designed for teams that need to convert au

Telegram Trigger, Telegram, OpenAI +1
AI & RAG

Perfect for marketing teams, agencies, solopreneurs, and e-commerce brands who need fast, professional-quality ad creatives — without hiring designers or using Canva. This workflow automates image gen

Form Trigger, Google Gemini, Telegram
AI & RAG

This workflow serves as a complete "AI Receptionist" for mortgage brokers or high-ticket service providers. It automates the messy process of qualifying leads, getting internal approval, and collectin

Google Gemini, Gmail, Google Drive +3