{"slug": "turn-one-devlog-into-posts-for-every-channel-with-n8n-ai", "title": "Turn one devlog into posts for every channel with n8n + AI", "summary": "A solo game developer automated social media posting by building an n8n workflow that uses Google Gemini to rewrite a single devlog into drafts for Twitter, Reddit, Discord, and a newsletter, saving them to Notion for manual review. The workflow runs locally via Docker and outputs structured JSON drafts, keeping the process authentic and compliant with each platform's rules.", "body_md": "If you're a solo game developer, you know the drill: you ship an update, write a devlog… and then you have to rewrite it four times. A punchy tweet. A longer Reddit post that doesn't sound like an ad. A casual Discord ping. A newsletter blurb. By the third rewrite you've lost the will to post at all.\n\nI automated the rewriting with **n8n**, **Google Gemini**, and **Notion**. I write the devlog once, hit run, and get channel-ready drafts waiting in Notion. It **doesn't auto-post**, it makes drafts I review and send myself, which keeps everything authentic and inside each platform's rules.\n\nHere's a short demo of the finished workflow:\n\n👉 [https://www.loom.com/share/f108f0a003b448b2bc414a8be742d772](https://www.loom.com/share/f108f0a003b448b2bc414a8be742d772)\n\nFor one devlog you paste in, it:\n\nThe flow looks like this:\n\n```\nManual Trigger\n  → Devlog Input\n  → AI Reformat (Gemini)\n  → Parse Drafts\n  → Save Drafts to Notion\ndocker volume create n8n_data\n\ndocker run -d --name n8n \\\n  -p 5678:5678 \\\n  -v n8n_data:/home/node/.n8n \\\n  docker.n8n.io/n8nio/n8n\n```\n\nOpen [http://localhost:5678](http://localhost:5678) and create your account.\n\nAdd a **Code** node where you write your update once. Keeping it in a Code node means you just edit two variables each time:\n\n``` js\nconst devlog_title = \"Update 0.3 — Online Co-op\";\nconst devlog_body = `We just shipped online co-op for up to 4 players,\nfixed the save-corruption bug, and added 2 new levels.\nNext up: controller support and a Steam demo.`;\n\nreturn [{ json: { devlog_title, devlog_body } }];\n```\n\n(Later you can swap this for a **Form Trigger** so you get a little web form, or a **Notion Trigger** that fires when you add a devlog page.)\n\nAdd the **Google Gemini** node. The trick is to make it return **strict JSON** so the next node can split it cleanly:\n\n```\nYou are a social media manager for a solo indie game developer.\n\nHere is a devlog update:\nTitle: {{ $json.devlog_title }}\nBody: {{ $json.devlog_body }}\n\nRewrite it for each channel. Return ONLY valid JSON (no markdown,\nno code fences, no text outside the JSON) with these exact keys:\n{\n  \"twitter\": \"280 characters max, punchy, 1-2 relevant hashtags\",\n  \"reddit\": \"friendly longer post for r/IndieDev, first person, no hashtags, no hard selling\",\n  \"discord\": \"casual short announcement for a community server, 1-2 emojis ok\",\n  \"newsletter\": \"2-3 sentence email blurb\"\n}\n```\n\nLLMs sometimes wrap JSON in code fences, so a small **Code** node cleans and parses it, with a fallback so you never lose output:\n\n``` js\nconst raw = ($json.content?.parts?.[0]?.text) || \"\";\n\n// \\x60 is a backtick (char code 96). This strips a code fence\n// if the model wraps its JSON output in one.\nlet clean = raw.trim()\n  .replace(/^\\x60{3}json\\s*/i, \"\")\n  .replace(/^\\x60{3}\\s*/, \"\")\n  .replace(/\\x60{3}$/, \"\")\n  .trim();\n\nlet parsed;\ntry {\n  parsed = JSON.parse(clean);\n} catch (e) {\n  parsed = { twitter: \"\", reddit: raw, discord: \"\", newsletter: \"\" };\n}\n\nconst input = $('Devlog Input').item.json;\n\nreturn [{\n  json: {\n    devlog_title: input.devlog_title,\n    twitter: parsed.twitter || \"\",\n    reddit: parsed.reddit || \"\",\n    discord: parsed.discord || \"\",\n    newsletter: parsed.newsletter || \"\",\n  }\n}];\n```\n\nCreate a Notion database called **Devlog Drafts** with these properties: **Name** (title), **Twitter** (text), **Reddit** (text), **Discord** (text), **Newsletter** (text), **Status** (text), **Created** (date).\n\nCreate an internal integration at notion.so/my-integrations, connect it to the database, then map the fields in n8n's **Notion** node. Set the title to `{{ $json.devlog_title }}`\n\nand each channel field to its matching value (`{{ $json.twitter }}`\n\n, etc.).\n\nRun the workflow and you'll get a new row with four drafts - review, tweak, and post whenever you like.\n\nI packaged this, plus a Steam competitor-tracking workflow - into an importable pack with setup guides, the AI prompts, troubleshooting, and example screenshots:\n\n👉 [https://shrisab.gumroad.com/l/indie-launch-ops/LAUNCH](https://shrisab.gumroad.com/l/indie-launch-ops/LAUNCH)\n\nEither way, write the devlog once, and stop dreading the four rewrites. Questions welcome in the comments.", "url": "https://wpnews.pro/news/turn-one-devlog-into-posts-for-every-channel-with-n8n-ai", "canonical_source": "https://dev.to/shrisab_shrestha_ba84e9a3/turn-one-devlog-into-posts-for-every-channel-with-n8n-ai-35dp", "published_at": "2026-07-14 07:33:43+00:00", "updated_at": "2026-07-14 08:00:39.286151+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence", "large-language-models", "ai-tools"], "entities": ["n8n", "Google Gemini", "Notion", "Docker"], "alternates": {"html": "https://wpnews.pro/news/turn-one-devlog-into-posts-for-every-channel-with-n8n-ai", "markdown": "https://wpnews.pro/news/turn-one-devlog-into-posts-for-every-channel-with-n8n-ai.md", "text": "https://wpnews.pro/news/turn-one-devlog-into-posts-for-every-channel-with-n8n-ai.txt", "jsonld": "https://wpnews.pro/news/turn-one-devlog-into-posts-for-every-channel-with-n8n-ai.jsonld"}}