This workflow follows the Agent → 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 →
{
"nodes": [
{
"id": "55beb635-9328-435c-ad2c-7ec7a021dcc6",
"name": "\ud83d\udccb Workflow Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2688,
-752
],
"parameters": {
"width": 672,
"height": 860,
"content": "@[youtube](urteFD1Q-74)\n\n## LinkedIn Viral Post Creator\n**Telegram Bot \u2192 AI Rewrite \u2192 Auto-Post**\n\n### How It Works\n1. Send a LinkedIn post URL to your Telegram bot\n2. AI rewrites it in YOUR style + generates an image\n3. Preview in Telegram, approve or reject\n4. Approved posts go live on LinkedIn\n\n### Setup Required\n1. **Telegram Bot** - Create via @BotFather\n2. **Google Gemini API** - For AI writing & images\n3. **ConnectSafely.ai** - For LinkedIn scraping\n4. **LinkedIn OAuth** - For posting\n5. **Your Telegram ID** - Update Security Check node\n6. **Your Persona** - Customize the Load Persona node"
},
"typeVersion": 1
},
{
"id": "6fb82c82-7c47-4650-ba65-7ecf38d907de",
"name": "\ud83d\udce5 Input & Validation",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1988,
-424
],
"parameters": {
"width": 520,
"height": 280,
"content": "## \ud83d\udce5 Input & Validation\nReceives Telegram messages, validates sender, and extracts LinkedIn URLs."
},
"typeVersion": 1
},
{
"id": "430dcb7e-6be5-4ac7-be69-a31d6e71cf32",
"name": "\ud83d\udd04 Scrape & Persona",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1030,
-520
],
"parameters": {
"width": 620,
"height": 280,
"content": "## \ud83d\udd04 Scrape & Persona\nScrapes original post content and loads your personal writing style."
},
"typeVersion": 1
},
{
"id": "6a483c5d-89db-4a28-b65e-37378152e5a9",
"name": "\ud83e\udd16 AI Generation",
"type": "n8n-nodes-base.stickyNote",
"position": [
-388,
-532
],
"parameters": {
"width": 584,
"height": 500,
"content": "## \ud83e\udd16 AI Generation\nRewrites post in your voice using Gemini, then creates an image prompt."
},
"typeVersion": 1
},
{
"id": "fd2c731f-51c4-4476-b1f5-72fc25d4d92e",
"name": "\ud83c\udfa8 Image & Preview",
"type": "n8n-nodes-base.stickyNote",
"position": [
224,
-512
],
"parameters": {
"width": 320,
"height": 280,
"content": "## \ud83c\udfa8 Image & Preview\nGenerates image with Gemini Imagen and sends preview to Telegram."
},
"typeVersion": 1
},
{
"id": "82d496d1-088a-464f-9d5b-0f9bd3313437",
"name": "\u2705 Approval Flow",
"type": "n8n-nodes-base.stickyNote",
"position": [
736,
-560
],
"parameters": {
"width": 320,
"height": 320,
"content": "## \u2705 Approval Flow\nWaits for your yes/no response in Telegram before proceeding."
},
"typeVersion": 1
},
{
"id": "f22be8e9-ac83-409b-af30-81eb8c940084",
"name": "\ud83d\ude80 Publish",
"type": "n8n-nodes-base.stickyNote",
"position": [
1082,
-604
],
"parameters": {
"width": 684,
"height": 268,
"content": "## \ud83d\ude80 Publish\nPosts to LinkedIn with image and sends confirmation to Telegram."
},
"typeVersion": 1
},
{
"id": "a0b83b77-34f8-4569-8be0-c462e50d071c",
"name": "Send Success Message",
"type": "n8n-nodes-base.telegram",
"position": [
1600,
-496
],
"parameters": {
"text": "=\ud83d\ude80 Your LinkedIn post is live!\n\nCheck it out here \ud83d\udc47\nhttps://www.linkedin.com/feed/update/{{ $json.urn }}\n",
"chatId": "={{ $('Telegram Trigger').item.json.message.from.id }}",
"additionalFields": {}
},
"notesInFlow": false,
"typeVersion": 1.2
},
{
"id": "202429d7-cce1-4d28-bd26-6884390f9679",
"name": "Send Decline Message",
"type": "n8n-nodes-base.telegram",
"position": [
1152,
-304
],
"parameters": {
"text": "=Your post was not published. You decided to decline.",
"chatId": "={{ $('Telegram Trigger').item.json.message.from.id }}",
"additionalFields": {
"appendAttribution": false
}
},
"notesInFlow": false,
"typeVersion": 1.2
},
{
"id": "8a026bfa-bca7-45a3-ba78-4c64d3338546",
"name": "Check Approval",
"type": "n8n-nodes-base.if",
"position": [
928,
-400
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "b471d7f2-5e45-431b-89ad-690e3209b4e4",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.data.approved }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "263d48dd-65cf-4d41-983d-62462726fb2e",
"name": "Create LinkedIn Post",
"type": "n8n-nodes-base.linkedIn",
"position": [
1376,
-496
],
"parameters": {
"text": "={{ $json.post }}",
"person": "YOUR_LINKEDIN_PERSON_ID",
"additionalFields": {},
"binaryPropertyName": "=data",
"shareMediaCategory": "IMAGE"
},
"typeVersion": 1,
"alwaysOutputData": false
},
{
"id": "42f9f7b2-6610-4a2f-8806-c8b9f27c843f",
"name": "Send Message and Wait for Approval",
"type": "n8n-nodes-base.telegram",
"position": [
704,
-400
],
"parameters": {
"chatId": "={{ $('Telegram Trigger').item.json.message.from.id }}",
"message": "=Please review the post text above and the image sent previously.\n\nText:\n{{ $('AI Agent1').first().json.output.post }}",
"options": {
"appendAttribution": false
},
"operation": "sendAndWait",
"approvalOptions": {
"values": {
"approvalType": "double"
}
}
},
"typeVersion": 1.2
},
{
"id": "cf5d9dc8-bccc-4806-a63a-47ec56594f25",
"name": "\ud83d\udcdd Create Image Prompt",
"type": "n8n-nodes-base.code",
"position": [
32,
-400
],
"parameters": {
"jsCode": "const post = $input.first().json.output.post;\nconst prompt = `Create a professional, high-quality, vibrant digital illustration suitable for a viral LinkedIn post. \n\nContext/Topic: ${post.substring(0, 300)}...\n\nStyle: Modern, clean, corporate but creative, vector art style, vibrant colors. No text in the image.`;\n\nreturn { imagePrompt: prompt, post: post };"
},
"typeVersion": 2
},
{
"id": "cde57698-847d-4ed9-a95c-2423854d8e87",
"name": "\ud83d\udce8 Send Preview Image",
"type": "n8n-nodes-base.telegram",
"position": [
480,
-400
],
"parameters": {
"chatId": "={{ $('Telegram Trigger').item.json.message.from.id }}",
"operation": "sendPhoto",
"binaryData": true,
"additionalFields": {
"caption": "\ud83c\udfa8 Generated Image for your post (Gemini)"
}
},
"typeVersion": 1.2
},
{
"id": "0b2aead5-b96c-4c86-90d6-b9b82e0b8b65",
"name": "Structured Output Parser",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
-184,
-176
],
"parameters": {
"schemaType": "manual",
"inputSchema": "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"title\": \"LinkedIn Post - Ready to Publish\",\n \"description\": \"Complete LinkedIn post with hook, content, and hashtags - ready to copy and paste\",\n \"type\": \"object\",\n \"properties\": {\n \"post\": {\n \"type\": \"string\",\n \"description\": \"The complete LinkedIn post including hook, body, CTA, and hashtags - ready to copy and paste directly to LinkedIn\",\n \"minLength\": 100,\n \"maxLength\": 3000\n }\n },\n \"required\": [\n \"post\"\n ],\n \"additionalProperties\": false\n}"
},
"typeVersion": 1.3
},
{
"id": "10e502d8-09db-49af-9bae-3037b635235d",
"name": "Google Gemini Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
-312,
-176
],
"parameters": {
"options": {
"temperature": 1
},
"modelName": "models/gemini-2.5-pro"
},
"typeVersion": 1
},
{
"id": "04034342-b8ef-400b-b80c-3160ee081cd3",
"name": "AI Agent1",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
-320,
-400
],
"parameters": {
"text": "=Rewrite the post now.",
"options": {
"systemMessage": "=# LinkedIn Post Rewriter - Match Writing Style\n\nRewrite this LinkedIn post to match the target persona's style exactly.\n\n## Original Post\nAuthor: {{ $json.originalAuthor }}\nEngagement: {{ $json.originalEngagement }} likes\n\n{{ $json.originalPostText }}\n\n## Target Persona\nName: {{ $json.persona.name }}\nTone: {{ $json.persona.style.tone }}\nVoice: {{ $json.persona.style.voice }}\nFormatting: {{ $json.persona.style.formatting }}\nHooks: {{ $json.persona.style.hooks }}\nCTA Style: {{ $json.persona.style.callToAction }}\nLength: {{ $json.persona.postLength }}\nExpertise: {{ $json.persona.expertiseAreas.join(', ') }}\nCommon Phrases: {{ $json.persona.commonPhrases.join(', ') }}\nEmojis: {{ $json.persona.preferredEmojis.join(' ') }}\n\n## Requirements\n\n**Content to Preserve:**\n- All URLs/links from original (keep exact URLs)\n- Key statistics and data points\n- Company/product names mentioned\n- Core message and insights\n\n**Style Matching:**\n- Match their typical hooks and opening style\n- Use their common phrases naturally\n- Follow their tone, voice, and formatting\n- Include 2-5 of their preferred emojis\n- Match their CTA style\n- Add 3-5 hashtags at end\n\n**LinkedIn Native Formatting (SUPPORTED):**\n\u2705 **Bold text** - Use for titles/emphasis (surround with *asterisks*)\n\u2705 *Italic text* - Use for subtle emphasis (surround with _underscores_)\n\u2705 Line breaks and spacing for structure\n\u2705 Emojis for visual hierarchy (\u26a1\ud83d\udca1\ud83c\udfaf\u2192\u2728)\n\u2705 CAPS for strong emphasis\n\u2705 Preserve any URLs exactly as they appear\n\u2705 Hashtags on last line only\n\n\u274c NOT supported: # headers, - markdown bullets, > quotes, [link](url) syntax\n\n**How to format for LinkedIn:**\n- Bold titles: *Title Text Here* (LinkedIn converts to bold)\n- Italic: _subtle emphasis_ (LinkedIn converts to italic)\n- Bullets: Use emojis or \u2192 symbol\n- Spacing: Line breaks for readability\n\n**Structure:**\n1. Hook (their style, can use *bold* for impact)\n2. Body (their voice & formatting)\n3. Key points (emoji bullets or structured)\n4. CTA (their typical style)\n5. Hashtags (3-5 at end)\n\n## Output Format\n\nReturn ONLY valid JSON:\n```json\n{\n \"post\": \"Complete post here\\n\\nWith line breaks\\n\\n*Bold Title If Needed*\\n\\nPreserved URLs: https://example.com\\n\\n#Hashtag1 #Hashtag2\"\n}\n```\n\nRules:\n- Entire post in single \"post\" field\n- Use \\n for line breaks, \\n\\n for paragraphs\n- Use *text* for bold, _text_ for italic\n- Include ALL original URLs unchanged\n- Ready to paste into LinkedIn\n\nReturn ONLY the JSON. No explanations. No code fences. Just the JSON object."
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 2.2
},
{
"id": "2be03393-36ac-4dad-b161-57e0544b5c6c",
"name": "Send Error Message",
"type": "n8n-nodes-base.telegram",
"position": [
-992,
-208
],
"parameters": {
"text": "={{ $('\ud83d\udd0d Extract Post URL').item.json.message }}",
"chatId": "={{ $('Telegram Trigger').item.json.message.from.id }}",
"additionalFields": {
"appendAttribution": false
}
},
"notesInFlow": false,
"typeVersion": 1.2
},
{
"id": "e57a2fef-e917-44c2-9d03-76ee00f914ba",
"name": "\ud83d\udc64 Load Your Persona",
"type": "n8n-nodes-base.code",
"notes": "\ud83d\udcdd CUSTOMIZE THIS - Edit the PERSONA object to match YOUR writing style",
"position": [
-544,
-400
],
"parameters": {
"jsCode": "// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// CUSTOMIZE THIS PERSONA TO MATCH YOUR LINKEDIN WRITING STYLE\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nconst PERSONA = {\n name: \"YourName\", // <-- Change to your name\n style: {\n tone: \"Professional yet conversational, engaging and authentic\",\n voice: \"First-person, direct, relatable\",\n formatting: \"Short paragraphs, bullet points, emojis for emphasis\",\n hooks: \"Start with bold statements, questions, or surprising facts\",\n callToAction: \"Encourage discussion, ask questions, invite engagement\"\n },\n expertiseAreas: [\n \"Your niche topic 1\", // <-- Change to your expertise\n \"Your niche topic 2\",\n \"Your niche topic 3\",\n \"Your niche topic 4\",\n \"Your niche topic 5\"\n ],\n postStructure: {\n opening: \"Hook with a question, stat, or bold statement\",\n body: \"3-5 short paragraphs with actionable insights\",\n bullets: \"Use bullet points for key takeaways\",\n closing: \"Strong CTA or thought-provoking question\",\n hashtags: \"3-5 relevant hashtags\"\n },\n commonPhrases: [ // <-- Add phrases YOU actually use\n \"Here's the thing:\",\n \"Let me break this down:\",\n \"The reality is:\",\n \"Here's what I learned:\",\n \"This changed everything:\",\n \"Quick story:\"\n ],\n preferredEmojis: [\"\ud83d\ude80\", \"\ud83d\udca1\", \"\ud83c\udfaf\", \"\u26a1\", \"\ud83d\udd25\", \"\u2728\", \"\ud83d\udcc8\", \"\ud83d\udcaa\"], // <-- Your favorite emojis\n postLength: \"medium\", // short, medium, or long\n styleNotes: [\n \"Always provide actionable value\",\n \"Share personal experiences and lessons\",\n \"Use concrete examples, not vague advice\",\n \"Keep it authentic and genuine\",\n \"Balance education with entertainment\",\n \"Never overly salesy or promotional\"\n ]\n};\n\nconst postText = $input.first().json.postText;\nconst authorName = $input.first().json.authorName;\nconst engagement = $input.first().json.engagement;\n\nreturn [{\n json: {\n ...($input.first().json),\n persona: PERSONA,\n originalPostText: postText,\n originalAuthor: authorName,\n originalEngagement: engagement,\n personaLoaded: true\n }\n}];"
},
"typeVersion": 2
},
{
"id": "ba4c1065-ce73-4a66-a678-464e725e1eea",
"name": "\ud83d\udd0d Scrape LinkedIn Post",
"type": "n8n-nodes-connectsafely-ai.connectSafelyLinkedIn",
"notes": "Uses ConnectSafely.ai to scrape LinkedIn post content",
"position": [
-992,
-400
],
"parameters": {
"postUrl": "={{ $json.postUrl }}",
"operation": "scrapePost"
},
"typeVersion": 1
},
{
"id": "a54f766c-343c-47ad-a8d4-4ce79b6cb1c7",
"name": "\u2753 Valid URL?",
"type": "n8n-nodes-base.if",
"notes": "Checks if LinkedIn URL was found",
"position": [
-1216,
-304
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "url-check",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.valid }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "2a479155-5b1d-464e-8cf2-69d784e580c3",
"name": "\ud83d\udd0d Extract Post URL",
"type": "n8n-nodes-base.code",
"notes": "Extracts LinkedIn URL from Telegram message",
"position": [
-1440,
-304
],
"parameters": {
"jsCode": "// Extract LinkedIn post URL from chat input\nconst userMessage = $input.first().json.message.text;\n\n// Extract URL from message\nconst urlRegex = /(https?:\\/\\/(?:www\\.)?linkedin\\.com\\/posts\\/[^\\s]+)/gi;\nconst urls = userMessage.match(urlRegex);\n\nif (!urls || urls.length === 0) {\n return [{\n json: {\n valid: false,\n message: \"\u274c No LinkedIn post URL found.\\n\\nPlease send a valid LinkedIn post URL.\\n\\nExample: https://www.linkedin.com/posts/username_activity-1234567890\",\n originalInput: userMessage\n }\n }];\n}\n\nconst postUrl = urls[0];\n\nreturn [{\n json: {\n postUrl: postUrl,\n originalInput: userMessage,\n extractedAt: new Date().toISOString(),\n workflowId: $execution.id,\n valid: true,\n }\n}];"
},
"typeVersion": 2
},
{
"id": "4aa18185-7b76-4392-8249-c093b6449c74",
"name": "Telegram Trigger",
"type": "n8n-nodes-base.telegramTrigger",
"position": [
-1888,
-304
],
"parameters": {
"updates": [
"message"
],
"additionalFields": {}
},
"typeVersion": 1.2
},
{
"id": "a651f09d-f52a-4303-9152-8c9266171fc1",
"name": "\ud83d\udd12 Security Check",
"type": "n8n-nodes-base.if",
"notes": "IMPORTANT: Replace YOUR_TELEGRAM_USER_ID with your actual Telegram user ID (get it from @userinfobot)",
"position": [
-1664,
-304
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "77f6ce79-5d55-46bc-848c-a8f7200e78fb",
"operator": {
"type": "number",
"operation": "equals"
},
"leftValue": "={{ $json.message.from.id }}",
"rightValue": "YOUR_TELEGRAM_USER_ID"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "57ec5621-761a-4127-be12-3913a71acb94",
"name": "Generate an image",
"type": "@n8n/n8n-nodes-langchain.googleGemini",
"position": [
256,
-400
],
"parameters": {
"prompt": "={{ $json.imagePrompt }}",
"modelId": {
"__rl": true,
"mode": "list",
"value": "models/gemini-2.0-flash-exp-image-generation",
"cachedResultName": "models/gemini-2.0-flash-exp-image-generation"
},
"options": {
"binaryPropertyOutput": "data"
},
"resource": "image"
},
"typeVersion": 1
},
{
"id": "d735a688-72d9-49c5-9530-96f8410f554c",
"name": "Prepare Content for LinkedIn",
"type": "n8n-nodes-base.code",
"position": [
1152,
-496
],
"parameters": {
"jsCode": "// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// LINKEDIN POST CLEANER WITH BINARY DATA\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nlet postText = $('AI Agent1').first().json.output.post\n\nfunction cleanPost(text) {\n let cleaned = text.replace(/\\\\n/g, '\\n');\n cleaned = cleaned.replace(/\\*\\*([^*]+)\\*\\*/g, '$1');\n cleaned = cleaned.replace(/\\*([^*]+)\\*/g, '$1');\n cleaned = cleaned.replace(/^#{1,6}\\s+/gm, '');\n cleaned = cleaned.replace(/\\n{4,}/g, '\\n\\n\\n');\n cleaned = cleaned.trim();\n \n const hashtagMatch = cleaned.match(/(#\\w+(?:\\s+#\\w+)*)\\s*$/);\n if (hashtagMatch) {\n cleaned = cleaned.replace(/(#\\w+(?:\\s+#\\w+)*)\\s*$/, '').trim();\n cleaned = cleaned + '\\n\\n' + hashtagMatch[1];\n }\n \n return cleaned;\n}\n\ntry {\n const cleanedPost = cleanPost(postText);\n \n // Get the binary data from the image generation node\n const imageBinary = $('Generate an image').first().binary.data;\n \n const output = {\n json: {\n post: cleanedPost,\n _original: postText.substring(0, 500)\n },\n binary: {\n data: imageBinary\n }\n };\n \n return [output];\n \n} catch (error) {\n return [{\n json: {\n post: postText,\n validation: {\n isValid: false,\n issues: ['Cleaning failed: ' + error.message]\n },\n },\n }];\n}"
},
"typeVersion": 2
},
{
"id": "d7d30d9e-d17d-41c3-81e6-3d4f0e9ec899",
"name": "\ud83d\udccb Extract Post Data",
"type": "n8n-nodes-base.set",
"notes": "Extracts key data from scraped post",
"position": [
-768,
-400
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "post-text",
"name": "postText",
"type": "string",
"value": "={{ $json.data.content }}"
},
{
"id": "author-name",
"name": "authorName",
"type": "string",
"value": "={{ $json.data.author.name }}"
},
{
"id": "engagement",
"name": "engagement",
"type": "number",
"value": "={{ $json.data.engagement.likes }}"
},
{
"id": "has-images",
"name": "hasImages",
"type": "boolean",
"value": "={{ $json.data.media.hasImages }}"
}
]
}
},
"typeVersion": 3.4
}
],
"connections": {
"AI Agent1": {
"main": [
[
{
"node": "\ud83d\udcdd Create Image Prompt",
"type": "main",
"index": 0
}
]
]
},
"Check Approval": {
"main": [
[
{
"node": "Prepare Content for LinkedIn",
"type": "main",
"index": 0
}
],
[
{
"node": "Send Decline Message",
"type": "main",
"index": 0
}
]
]
},
"\u2753 Valid URL?": {
"main": [
[
{
"node": "\ud83d\udd0d Scrape LinkedIn Post",
"type": "main",
"index": 0
}
],
[
{
"node": "Send Error Message",
"type": "main",
"index": 0
}
]
]
},
"Telegram Trigger": {
"main": [
[
{
"node": "\ud83d\udd12 Security Check",
"type": "main",
"index": 0
}
]
]
},
"Generate an image": {
"main": [
[
{
"node": "\ud83d\udce8 Send Preview Image",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udd12 Security Check": {
"main": [
[
{
"node": "\ud83d\udd0d Extract Post URL",
"type": "main",
"index": 0
}
]
]
},
"Create LinkedIn Post": {
"main": [
[
{
"node": "Send Success Message",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udd0d Extract Post URL": {
"main": [
[
{
"node": "\u2753 Valid URL?",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udc64 Load Your Persona": {
"main": [
[
{
"node": "AI Agent1",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udccb Extract Post Data": {
"main": [
[
{
"node": "\ud83d\udc64 Load Your Persona",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udce8 Send Preview Image": {
"main": [
[
{
"node": "Send Message and Wait for Approval",
"type": "main",
"index": 0
}
]
]
},
"Google Gemini Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent1",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Structured Output Parser": {
"ai_outputParser": [
[
{
"node": "AI Agent1",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"\ud83d\udcdd Create Image Prompt": {
"main": [
[
{
"node": "Generate an image",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udd0d Scrape LinkedIn Post": {
"main": [
[
{
"node": "\ud83d\udccb Extract Post Data",
"type": "main",
"index": 0
}
]
]
},
"Prepare Content for LinkedIn": {
"main": [
[
{
"node": "Create LinkedIn Post",
"type": "main",
"index": 0
}
]
]
},
"Send Message and Wait for Approval": {
"main": [
[
{
"node": "Check Approval",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
How this works
Transform viral social media posts into personalised content that resonates with your professional network, saving hours of manual rewriting while boosting engagement on LinkedIn. This workflow is ideal for content creators, marketers, and social media managers who spot trending ideas on Telegram and want to adapt them authentically for business audiences. It starts with an event trigger on Telegram, where you share a viral post, then leverages Google Gemini AI to rephrase it in your unique voice, incorporating structured output parsing for polished results before scheduling the post on LinkedIn.
Use this workflow when you need quick, tailored adaptations of timely trends without starting from scratch, especially for daily social media routines. Avoid it for highly regulated industries requiring legal reviews, or when posts demand extensive original research beyond rewriting. Common variations include swapping Gemini for another AI model or adding email notifications for approvals.
About this workflow
Viral-Post-Rewriter-Gemini. Uses telegram, linkedIn, outputParserStructured, lmChatGoogleGemini. Event-driven trigger; 27 nodes.
Source: https://github.com/ConnectSafelyAI/connectsafely-cookbook/blob/main/n8n/viral-post-rewriter-gemini.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow transforms your Telegram bot into an intelligent creative assistant. It can chat conversationally, fetch trending image prompts from PromptHero for inspiration, or perform a deep "remix"
This workflow acts as an AI-powered "Viral Architect" for YouTube creators. Simply send a video topic (e.g., "Kling 2.6") to your Telegram bot, and it will scrape top-performing competitor thumbnails,
This workflow acts as an intelligent content engine. Simply send a link to your Telegram bot (e.g., a product page or news article), and it will automatically scrape the content, rewrite it into a hig
> Optimize your AI workflows, cut costs, and get faster, more accurate answers.
This workflow automates Facebook posting and appointment booking directly from a Telegram bot, making it especially useful for pet grooming businesses that want to keep their social media active while