블로그 및 LinkedIn 콘텐츠 제작 자동화
고급
이것은Content Creation, Multimodal AI분야의자동화 워크플로우로, 28개의 노드를 포함합니다.주로 If, Set, Code, Cron, Gmail 등의 노드를 사용하며. OpenAI 및 Replicate AI 이미지를 사용한 블로그 및 LinkedIn 콘텐츠 제작 자동화
사전 요구사항
- •Google 계정 및 Gmail API 인증 정보
- •Notion API Key
- •LinkedIn API 인증 정보
- •대상 API의 인증 정보가 필요할 수 있음
- •OpenAI API Key
워크플로우 미리보기
노드 연결 관계를 시각적으로 표시하며, 확대/축소 및 이동을 지원합니다
워크플로우 내보내기
다음 JSON 구성을 복사하여 n8n에 가져오면 이 워크플로우를 사용할 수 있습니다
{
"meta": {
"instanceId": "f930580f475173640cf75bd5e1dc94fd2a589d21917d2c231c8fd90eb205f9b82",
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "45e081e9-db15-4808-9c26-6f1089f23a0e",
"name": "Cron (일정)",
"type": "n8n-nodes-base.cron",
"position": [
-1648,
-304
],
"parameters": {
"triggerTimes": {
"item": [
{
"hour": 19
}
]
}
},
"typeVersion": 1
},
{
"id": "7e72fddb-7c81-4bf3-bd96-b02c3ebb53efa",
"name": "Set (설정)",
"type": "n8n-nodes-base.set",
"position": [
-1424,
-304
],
"parameters": {
"values": {
"string": [
{
"name": "NOTION_DB_ID",
"value": "25496301-7675-81fa-9d31-cedcc7f452c6a"
},
{
"name": "NOTION_PAGE_PARENT",
"value": "XXXXXXXXXXXXXXXXXXXXXXXXXXX"
},
{
"name": "LINKEDIN_PERSON_URN",
"value": "urn:li:person:XXXXXXXX"
},
{
"name": "OPENAI_MODEL",
"value": "gpt-4.1-mini"
},
{
"name": "EMAIL_TO",
"value": "test@mail.com"
}
],
"boolean": [
{
"name": "LINKEDIN_PUBLISH",
"value": true
}
]
},
"options": {},
"keepOnlySet": true
},
"typeVersion": 2
},
{
"id": "648ff7d2-a55e-4e0c-8b12-d3634d1f1b958",
"name": "Notion → 아이디어 DB 쿼리 (전체)",
"type": "n8n-nodes-base.notion",
"position": [
-1200,
-304
],
"parameters": {
"simple": false,
"options": {
"sort": {
"sortValue": [
{
"key": "created_time",
"direction": "ascending",
"timestamp": true
}
]
}
},
"resource": "databasePage",
"operation": "getAll",
"returnAll": true,
"databaseId": {
"__rl": true,
"mode": "id",
"value": "={{ $json.NOTION_DB_ID }}"
},
"filterJson": "={\n \"property\": \"published\",\n \"checkbox\": { \"equals\": false }\n}",
"filterType": "json"
},
"credentials": {
"notionApi": {
"id": "AU61TARrYLYMxTj9",
"name": "Notion account"
}
},
"typeVersion": 2
},
{
"id": "c964ef88-6dea-4ea1-ad6c-2eef99b483646",
"name": "IF (자격 있는 항목 존재?)",
"type": "n8n-nodes-base.if",
"position": [
-1200,
0
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "d6c0245f-b296-4a04-861d-84c42736aa997",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.eligible_count > 0 }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2
},
{
"id": "e3a428a0-c52e-47f6-9281-1063f84e587c3",
"name": "Split In Batches (1)",
"type": "n8n-nodes-base.splitInBatches",
"position": [
-656,
-304
],
"parameters": {
"options": {},
"batchSize": 1
},
"typeVersion": 2
},
{
"id": "017d6b4c-52f8-4238-abf1-95f44d08b182b",
"name": "Error Trigger (노드 실패 시)",
"type": "n8n-nodes-base.errorTrigger",
"position": [
-1520,
2272
],
"parameters": {},
"typeVersion": 1
},
{
"id": "219ddd0a-9ad8-4555-acf1-b002406738346",
"name": "자격 있는 항목 수 세기",
"type": "n8n-nodes-base.code",
"position": [
-1424,
0
],
"parameters": {
"jsCode": "// Emit a single item with the eligible count for IF routing\nreturn [{ json: { eligible_count: items.length } }];"
},
"typeVersion": 2
},
{
"id": "7d00232e-be9d-4cdc-b072-eedc64dd79e3c",
"name": "미발행 항목 필터링 + 매핑",
"type": "n8n-nodes-base.code",
"position": [
-976,
-304
],
"parameters": {
"jsCode": "/* Filter unpublished + map fields safely */\nconst out = [];\nfor (const item of items) {\n const page = item.json;\n const id = page.id;\n const p = page.properties || {};\n const g = (prop) => {\n if (!prop) return '';\n if (prop.type === 'title' && prop.title?.length) return prop.title.map(t=>t.plain_text).join('');\n if (prop.type === 'rich_text' && prop.rich_text?.length) return prop.rich_text.map(t=>t.plain_text).join('');\n if (prop.type === 'url') return prop.url || '';\n if (prop.type === 'checkbox') return !!prop.checkbox;\n if (prop.type === 'multi_select') return prop.multi_select.map(o=>o.name);\n if (prop.type === 'select') return prop.select?.name || '';\n if (prop.type === 'date') return prop.date?.start || '';\n return '';\n };\n const isPublished = p.published ? !!p.published.checkbox : false;\n if (isPublished) continue;\n\n const title = g(p.title) || page.properties?.Name?.title?.[0]?.plain_text || '';\n const angle = g(p.angle);\n const tags = p.tags ? (p.tags.type === 'multi_select' ? p.tags.multi_select.map(o=>o.name) : g(p.tags)) : '';\n const primary_link = g(p.primary_link);\n const reference_links = g(p.reference_links);\n const images = g(p.images);\n const notes = g(p.notes);\n const target_audience = g(p.target_audience);\n const canonical_url = g(p.canonical_url);\n const language = g(p.language);\n const slug = g(p.slug);\n\n out.push({ json: {\n notion_page_id: id,\n title,\n angle,\n tags,\n primary_link,\n reference_links,\n images,\n notes,\n target_audience,\n canonical_url,\n language,\n slug\n }});\n}\nreturn out;\n"
},
"typeVersion": 2
},
{
"id": "40b826f5-b1ef-490b-b208-f1754c1972d81",
"name": "메시지 보내기",
"type": "n8n-nodes-base.gmail",
"position": [
-976,
0
],
"webhookId": "60e2a23b-9c59-485b-a5d3-9c61b2f39a45",
"parameters": {
"sendTo": "={{ $('Set (Configs)').item.json.EMAIL_TO }}",
"message": "=No rows found in {{ $('Set (Configs)').item.json.NOTION_DB_ID }} with published != true at {{$now}}.",
"options": {},
"subject": "Blog Pipeline: No Eligible Notion Rows!",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"id": "g6m2gV1BtMtEggjm",
"name": "Gmail account"
}
},
"typeVersion": 2.1
},
{
"id": "87a55a66-d609-47d2-a177-eddb4a7d9d560",
"name": "JSON 구문 분석 및 검증",
"type": "n8n-nodes-base.code",
"position": [
144,
-304
],
"parameters": {
"jsCode": "/**\n * Node 11 — Function (Parse & Validate JSON from OpenAI)\n * Soft-handles safety_flags (warnings) instead of throwing.\n */\n\n// ---------- 1) Extract message.content ----------\nconst input = items[0].json;\n\nfunction extractContent(nodeOut) {\n // n8n OpenAI nodes vary; support a few shapes:\n\n // A) Array of { message: { content } }\n if (Array.isArray(nodeOut) && nodeOut[0]?.message?.content !== undefined) {\n return nodeOut[0].message.content;\n }\n // B) Chat Completions\n if (nodeOut?.data?.choices?.[0]?.message?.content !== undefined) {\n return nodeOut.data.choices[0].message.content;\n }\n // C) OpenAI node returning raw string JSON at top level\n if (typeof nodeOut === \"string\") {\n return nodeOut;\n }\n // D) Flattened shape\n if (nodeOut?.message?.content !== undefined) {\n return nodeOut.message.content;\n }\n // E) Sometimes models already return parsed object\n if (nodeOut?.content !== undefined) {\n return nodeOut.content;\n }\n throw new Error(\"Node11: could not locate message.content from OpenAI output\");\n}\n\nlet content = extractContent(input);\n\n// ---------- 2) Parse to object ----------\nlet parsed;\nif (content && typeof content === \"object\") {\n parsed = content;\n} else if (typeof content === \"string\") {\n let txt = content.trim();\n if (txt.startsWith(\"```\")) {\n txt = txt.replace(/^```(?:json)?\\s*/i, \"\").replace(/\\s*```$/i, \"\");\n }\n txt = txt\n .replace(/[\\u2018\\u2019]/g, \"'\")\n .replace(/[\\u201C\\u201D]/g, '\"')\n .replace(/[\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F]/g, \" \")\n .replace(/,\\s*([}\\]])/g, \"$1\");\n\n // escape raw newlines inside strings\n (function escapeNewlinesInStrings() {\n let out = \"\", inStr = false, esc = false;\n for (let i = 0; i < txt.length; i++) {\n const ch = txt[i];\n if (!inStr) { if (ch === '\"') inStr = true; out += ch; continue; }\n if (esc) { out += ch; esc = false; continue; }\n if (ch === \"\\\\\") { out += ch; esc = true; continue; }\n if (ch === '\"') { inStr = false; out += ch; continue; }\n if (ch === \"\\n\" || ch === \"\\r\") { out += \"\\\\n\"; continue; }\n out += ch;\n }\n txt = out;\n })();\n\n try {\n parsed = JSON.parse(txt);\n } catch (e) {\n throw new Error(\"Node11: JSON.parse failed after repair: \" + e.message);\n }\n} else {\n throw new Error(\"Node11: message.content is neither object nor string\");\n}\n\n// ---------- 3) Validate + normalize ----------\nconst errs = [];\nconst warn = [];\nconst isNonEmpty = (s) => typeof s === \"string\" && s.trim().length > 0;\nconst arrOfStr = (a) => Array.isArray(a) ? a.map(x => String(x)).filter(Boolean) : [];\n\nif (!parsed.blog) errs.push(\"blog missing\");\nelse {\n if (!isNonEmpty(parsed.blog.title)) errs.push(\"blog.title missing\");\n if (!isNonEmpty(parsed.blog.slug)) errs.push(\"blog.slug missing\");\n if (!isNonEmpty(parsed.blog.markdown)) errs.push(\"blog.markdown missing\");\n if (parsed.blog.slug && parsed.blog.slug.length > 100) errs.push(\"blog.slug > 100 chars\");\n parsed.blog.keywords = arrOfStr(parsed.blog.keywords);\n parsed.blog.image_alt_texts = arrOfStr(parsed.blog.image_alt_texts);\n if (\n parsed.blog.canonical_url !== null &&\n parsed.blog.canonical_url !== undefined &&\n typeof parsed.blog.canonical_url !== \"string\"\n ) errs.push(\"blog.canonical_url must be string or null\");\n}\n\nif (!parsed.linkedin) errs.push(\"linkedin missing\");\nelse {\n if (!isNonEmpty(parsed.linkedin.final_text)) errs.push(\"linkedin.final_text missing\");\n // hashtags soft window\n parsed.linkedin.hashtags = arrOfStr(parsed.linkedin.hashtags);\n if (parsed.linkedin.hashtags.length > 8) {\n parsed.linkedin.hashtags = parsed.linkedin.hashtags.slice(0, 8);\n }\n // char guard\n let ft = String(parsed.linkedin.final_text || \"\");\n if (ft.length > 1200) {\n let cut = ft.slice(0, 1180);\n const lastBreak = Math.max(cut.lastIndexOf(\"\\n\"), cut.lastIndexOf(\".\"));\n if (lastBreak > 800) cut = cut.slice(0, lastBreak + 1);\n parsed.linkedin.final_text = cut;\n warn.push(\"linkedin.final_text truncated to 1200 chars\");\n }\n}\n\n// Safety flags: treat as warnings (expose downstream)\nif (!Array.isArray(parsed.safety_flags)) parsed.safety_flags = [];\nif (parsed.safety_flags.length) {\n warn.push(\"safety_flags present: \" + parsed.safety_flags.join(\", \"));\n}\n\n// Hard errors?\nif (errs.length) {\n throw new Error(\"Node11 validation failed: \" + errs.join(\"; \"));\n}\n\n// ---------- 4) Merge with Normalize Arrays (Node 9), return ----------\nlet norm = {};\ntry {\n const n = $items(\"Function (Normalize Arrays)\", 0, $runIndex);\n if (Array.isArray(n) && n[0] && n[0].json) norm = n[0].json;\n} catch (_) {}\n\nreturn [{\n json: {\n ...norm,\n openai: parsed,\n warnings: warn\n }\n}];\n"
},
"typeVersion": 2
},
{
"id": "3ab2103a-a358-415c-a4d1-1df7c3cb14f5",
"name": "배열 정규화",
"type": "n8n-nodes-base.code",
"position": [
-432,
-304
],
"parameters": {
"jsCode": "// Normalize arrays + carry configs\nfunction toArray(v){\n if (Array.isArray(v)) return v;\n if (typeof v === 'string'){\n const s = v.trim();\n if (!s) return [];\n try { const parsed = JSON.parse(s); if (Array.isArray(parsed)) return parsed; } catch(e) {}\n return s.split(',').map(x=>x.trim()).filter(Boolean);\n }\n return [];\n}\n\n// Pull config from the Set (Configs) node\n// Simple form:\nconst cfg = $node[\"Set (Configs)\"].json;\n// Robust form (if you prefer):\n// const cfg = $items(\"Set (Configs)\", 0, $runIndex)[0].json;\n\nconst i = items[0].json;\n\nreturn [{\n json: {\n NOTION_DB_ID: cfg.NOTION_DB_ID,\n NOTION_PAGE_PARENT: cfg.NOTION_PAGE_PARENT,\n LINKEDIN_PERSON_URN: cfg.LINKEDIN_PERSON_URN,\n OPENAI_MODEL: cfg.OPENAI_MODEL,\n EMAIL_TO: cfg.EMAIL_TO,\n\n notion_page_id: i.notion_page_id,\n title: i.title || '',\n angle: i.angle || '',\n tags: toArray(i.tags),\n primary_link: i.primary_link || '',\n reference_links: toArray(i.reference_links),\n images: toArray(i.images),\n notes: i.notes || '',\n target_audience: i.target_audience || '',\n canonical_url: i.canonical_url || '',\n language: i.language || '',\n slug: i.slug || ''\n }\n}];\n"
},
"typeVersion": 2
},
{
"id": "52a1ad9c-cc6a-49a1-ab7f-9b3a8a2e8c2b",
"name": "게시물 생성",
"type": "n8n-nodes-base.linkedIn",
"position": [
1872,
-432
],
"parameters": {
"text": "={{ $('Content Creator').item.json.message.content.linkedin.final_text }}",
"person": "k47kCb899q",
"additionalFields": {
"title": "={{ $('Content Creator').item.json.message.content.blog.title }}",
"visibility": "PUBLIC"
},
"binaryPropertyName": "=data",
"shareMediaCategory": "IMAGE"
},
"credentials": {
"linkedInOAuth2Api": {
"id": "DzG9q9KGhJCP5FSt",
"name": "LinkedIn account"
}
},
"typeVersion": 1
},
{
"id": "128ee066-dca2-4c19-830b-621e3eafbbc0",
"name": "아티클 데이터베이스 페이지 생성",
"type": "n8n-nodes-base.notion",
"position": [
432,
-304
],
"parameters": {
"title": "={{ $json.openai.blog.title }}",
"simple": false,
"options": {},
"resource": "databasePage",
"databaseId": {
"__rl": true,
"mode": "list",
"value": "25496301-7675-81bc-b023-c7e012094120",
"cachedResultUrl": "https://www.notion.so/25496301767581bcb023c7e012094120",
"cachedResultName": "Articles"
},
"propertiesUi": {
"propertyValues": [
{
"key": "title|title",
"title": "={{ $json.openai.blog.title }}"
},
{
"key": "slug|rich_text",
"text": {
"text": [
{
"text": "={{ $json.openai.blog.slug }}",
"annotationUi": {}
}
]
},
"richText": true
},
{
"key": "excerpt|rich_text",
"text": {
"text": [
{
"text": "={{ $json.openai.blog.excerpt }}",
"annotationUi": {}
}
]
},
"richText": true
},
{
"key": "keywords|multi_select",
"multiSelectValue": "={{ $json.openai.blog.keywords }}"
},
{
"key": "canonical_url|url",
"urlValue": "={{ $json.openai.blog.canonical_url || '' }}",
"ignoreIfEmpty": true
},
{
"key": "suggested_cover_caption|rich_text",
"text": {
"text": [
{
"text": "={{ $json.openai.blog.suggested_cover_caption }}",
"annotationUi": {}
}
]
},
"richText": true
},
{
"key": "image_alt_texts|rich_text",
"text": {
"text": [
{
"text": "={{ $json.openai.blog.image_alt_texts.join(', ') }}",
"annotationUi": {}
}
]
},
"richText": true
},
{
"key": "language|select",
"selectValue": "={{ $('Split In Batches (1)').item.json.language || 'en' }}"
},
{
"key": "tags|multi_select",
"multiSelectValue": "={{ $json.openai.linkedin.hashtags }}"
},
{
"key": "status|select",
"selectValue": "Published"
},
{
"key": "published_at|date",
"date": "={{ $now }}",
"timezone": "Asia/Kathmandu"
},
{
"key": "source_idea|relation",
"relationValue": [
"={{ $('Split In Batches (1)').item.json.notion_page_id }}"
]
},
{
"key": "linkedin_draft|rich_text",
"text": {
"text": [
{
"text": "={{ $json.openai.linkedin.final_text }}",
"annotationUi": {}
}
]
},
"richText": true
}
]
}
},
"credentials": {
"notionApi": {
"id": "AU61TARrYLYMxTj9",
"name": "Notion account"
}
},
"typeVersion": 2.2
},
{
"id": "6160be76-97f5-4f4c-bfa6-5e480080d854",
"name": "이메일 초안 작성",
"type": "n8n-nodes-base.gmail",
"position": [
1120,
-80
],
"webhookId": "4a91eae9-a78f-4246-bdf2-faaf10f3afdd",
"parameters": {
"sendTo": "={{ $('Set (Configs)').item.json.EMAIL_TO }}",
"message": "=Title: {{ $json.properties.title.title[0].text.content }}\nDraft: {{ $json.properties.linkedin_draft.rich_text[0].text.content }}",
"options": {},
"subject": "LinkedIn Draft Ready",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"id": "g6m2gV1BtMtEggjm",
"name": "Gmail account"
}
},
"typeVersion": 2.1
},
{
"id": "a1a7482f-3868-402c-a05b-2535b8443ad7",
"name": "발행 이메일",
"type": "n8n-nodes-base.gmail",
"position": [
2096,
-432
],
"webhookId": "f2d6603d-058d-43dd-8d67-aaed9476c825",
"parameters": {
"sendTo": "mail@budhathokisagar.com.np",
"message": "=Published: {{ $('Create a Article Database Page').item.json.properties.title.title[0].text.content }}\nSlug: {{ $('Create a Article Database Page').item.json.properties.slug.rich_text[0].text.content }}\nLinkedIn: posted as person.\nIdea Page: {{ $('Create a Article Database Page').item.json.id }}",
"options": {},
"subject": "LinkedIn Post Published!",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"id": "g6m2gV1BtMtEggjm",
"name": "Gmail account"
}
},
"typeVersion": 2.1
},
{
"id": "a7b80170-9832-46fb-85ba-8b87c5bd9da4",
"name": "데이터베이스 업데이트 초안",
"type": "n8n-nodes-base.notion",
"position": [
1344,
-80
],
"parameters": {
"pageId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Create a Article Database Page').item.json.id }}"
},
"simple": false,
"options": {},
"resource": "databasePage",
"operation": "update",
"propertiesUi": {
"propertyValues": [
{
"key": "status|select",
"selectValue": "Draft"
}
]
}
},
"credentials": {
"notionApi": {
"id": "AU61TARrYLYMxTj9",
"name": "Notion account"
}
},
"typeVersion": 2.2
},
{
"id": "4e43c32b-407c-4a62-8a0d-2b5eea10c615",
"name": "데이터베이스 페이지 업데이트",
"type": "n8n-nodes-base.notion",
"position": [
2320,
-432
],
"parameters": {
"pageId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Create a Article Database Page').item.json.id }}"
},
"simple": false,
"options": {},
"resource": "databasePage",
"operation": "update",
"propertiesUi": {
"propertyValues": [
{
"key": "status|select",
"selectValue": "Published"
}
]
}
},
"credentials": {
"notionApi": {
"id": "AU61TARrYLYMxTj9",
"name": "Notion account"
}
},
"typeVersion": 2.2
},
{
"id": "c3dfe348-0a68-45ee-b538-2f72fdbffaa9",
"name": "이미지 다운로드",
"type": "n8n-nodes-base.httpRequest",
"position": [
1648,
-432
],
"parameters": {
"url": "={{ $json.output[0] }}",
"options": {}
},
"typeVersion": 4.2
},
{
"id": "4b21b649-4087-4ef2-aa8d-9ee53c5db581",
"name": "Replicate 이미지 예측",
"type": "n8n-nodes-base.httpRequest",
"position": [
1424,
-432
],
"parameters": {
"url": "https://api.replicate.com/v1/models/black-forest-labs/flux-schnell/predictions",
"method": "POST",
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
},
"jsonBody": "={\n \"input\": {\n \"prompt\": \"{{ $json.message.content }}\",\n \"aspect_ratio\": \"16:9\"\n }\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpBearerAuth",
"headerParameters": {
"parameters": [
{
"name": "Prefer",
"value": "wait"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"credentials": {
"httpBearerAuth": {
"id": "UMvkuuToRy2C4VYfo",
"name": "Bearer Auth Replicate"
}
},
"typeVersion": 4.2
},
{
"id": "2dd65c1f-d859-4809-857b-7f8b6e535306",
"name": "콘텐츠 크리에이터",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
-208,
-304
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-5-mini",
"cachedResultName": "GPT-5-MINI"
},
"options": {},
"messages": {
"values": [
{
"content": "=You are a senior technical writer and LinkedIn ghostwriter for a Nepal-based DevOps/CloudOps/SysOps/Python developer who also loves AI/ML. \nYour job is to take one Notion row and turn it into:\n\n1) A polished, human-readable blog article for Hashnode (Markdown only).\n2) A LinkedIn post that feels authentic, insightful, and share-worthy, and most-importantly simpler english.\n\nYour voice should feel like a real engineer sharing something useful:\n- Informative but conversational\n- Confident but humble\n- Sometimes witty, but never forced\n- Includes actionable value (tips, insights, commands, lessons)\n- Occasionally adds light Nepali flavor naturally if language=\"ne\"\n\n---\n### INPUT\n- title: {{ $json.title }}\n- angle: {{ $json.angle }}\n- tags: {{ $json.tags }}\n- primary_link: {{ $json.primary_link }}\n- reference_links: {{ $json.reference_links }}\n- images: {{ $json.images }}\n- notes: {{ $json.notes }}\n- target_audience: {{ $json.target_audience }}\n- canonical_url: {{ $json.canonical_url }}\n- language: {{ $json.language }}\n- slug: {{ $json.slug }}\n\n---\n### PREFERENCES\n- LinkedIn posts ≤ 1200 characters\n- Blog word count:\n - Rich notes/tags: 900–1400 words\n - Sparse notes/tags: 600–900 words\n- Include at least one specific example, command, or actionable tip\n- Only one link allowed in LinkedIn text (if primary_link exists)\n\n---\n### STYLE TARGETS\nFor LinkedIn, pick the most natural style automatically:\n- **Story:** Small anecdote or lesson\n- **Industry Take:** Commentary with reflection\n- **Tech Breakdown:** Clear step-by-step with code/tips\n- **Basics:** Foundational guidance in checklist format\n- **Humor List:** Funny but relatable \"few techs\" overwhelm joke\n- **Optimization/Win:** Real-world result or improvement shared\n\n---\n### BLOG REQUIREMENTS\n- Markdown only, no frontmatter\n- Structure:\n - Hook intro (2–4 lines)\n - Clear sections with H2/H3\n - Include steps, code snippets, or bullet lists\n - Add “Sharp edges & gotchas” with realistic pitfalls\n - Include a mini case/example\n - End with actionable “Key Takeaways” (3–6 bullets)\n- Include:\n - SEO: slug, excerpt, keywords (5–10)\n - Suggested cover caption\n - Alt text suggestions for images\n - Canonical URL if provided\n\n---\n### LINKEDIN REQUIREMENTS\n- Start with a strong HOOK (1–2 lines), do not mention word itself like 'hook' or similar\n- Use short, human paragraphs\n- Include at least one actionable tip or fact\n- Invite engagement with a closing question or CTA\n- Add 5–10 hashtags, a mix of broad (#DevOps #Cloud) and niche (#AWS #Kubernetes #Observability)\n\n---\n### RULES\n- Never invent unknown facts\n- Prioritize clear, human language\n- Favor real-world examples over generic advice\n- Use emojis sparingly and purposefully (max 3)\n\n---\n### OUTPUT SCHEMA\n{\n \"blog\": {\n \"title\": \"string\",\n \"slug\": \"string\",\n \"excerpt\": \"string\",\n \"keywords\": [\"string\", \"...\"],\n \"canonical_url\": \"string|null\",\n \"suggested_cover_caption\": \"string\",\n \"image_alt_texts\": [\"string\", \"...\"],\n \"markdown\": \"string\"\n },\n \"linkedin\": {\n \"style_used\": \"story|industry_take|tech_breakdown|basics|humor_list|optimization\",\n \"final_text\": \"string\",\n \"alt_titles\": [\"string\",\"string\",\"string\"]\n },\n \"safety_flags\": []\n}"
}
]
},
"simplify": "={{ true }}",
"jsonOutput": true
},
"credentials": {
"openAiApi": {
"id": "1JMlq9LFlvNZ4n7z",
"name": "OpenAi account"
}
},
"typeVersion": 1.8
},
{
"id": "17809fd9-84d8-458b-a904-b497549c10dd",
"name": "이미지 프롬프트 생성기",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
1072,
-432
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini",
"cachedResultName": "GPT-4.1-MINI"
},
"options": {},
"messages": {
"values": [
{
"content": "={\n \"title\": \"{{$json.properties?.title?.title?.[0]?.plain_text || ''}}\",\n \"excerpt\": \"{{$json.properties?.excerpt?.rich_text?.[0]?.plain_text || ''}}\",\n \"linkedin_draft\": \"{{$json.properties?.linkedin_draft?.rich_text?.[0]?.plain_text || ''}}\",\n \"alt\": \"{{$json.properties?.image_alt_texts?.rich_text?.[0]?.plain_text || ''}}\",\n \"keywords\": \"{{$json.properties?.keywords?.multi_select?.map(k => k.name).join(', ') || ''}}\"\n}\n"
},
{
"role": "system",
"content": "You generate a single, realistic text-to-image prompt for the Replicate model black-forest-labs/flux-schnell, based on details from a LinkedIn post.\n\nRULES:\n- Output only the prompt as plain text, no JSON, no commentary.\n- Make the scene look photorealistic but clean and professional — perfect for LinkedIn.\n- Focus on key objects, actions, and environment described in the post (title, excerpt, alt, keywords).\n- Include subtle realistic elements (lighting, depth, perspective, color) but keep the layout minimal and balanced.\n- Never include any legible text, logos, watermarks, brand names, or faces.\n- Use soft professional lighting, shallow depth of field, and natural tones.\n- Keep it under ~900 characters.\n- Default to a 16:9 aspect ratio.\n"
}
]
}
},
"credentials": {
"openAiApi": {
"id": "1JMlq9LFlvNZ4n7z",
"name": "OpenAi account"
}
},
"typeVersion": 1.8
},
{
"id": "20246ca2-9171-4ba8-8009-f43a43296c59",
"name": "실패 메시지",
"type": "n8n-nodes-base.gmail",
"position": [
-1232,
2272
],
"webhookId": "3fd774cb-ed1a-4d99-9680-46fed3bdeb82",
"parameters": {
"sendTo": "={{$json.execution?.error?.workflow?.data?.startData?.runData?.['Set (Configs)']?.[0]?.json?.EMAIL_TO || 'test@mail.com'}}",
"message": "=Node: {{$json.execution?.error?.node?.name}}\\nMessage: {{$json.execution?.error?.message}}\\nStack: {{$json.execution?.error?.stack}}\\nLast Payload: {{JSON.stringify($json.execution?.error?.node?.data, null, 2).slice(0,5000)}}",
"options": {},
"subject": "=Blog Pipeline ERROR: {{$json.execution?.error?.message || 'Unknown error'}}",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"id": "g6m2gV1BtMtEggjm",
"name": "Gmail account"
}
},
"typeVersion": 2.1
},
{
"id": "efd5db98-aa5e-46e4-9d6c-4708b8db08a4",
"name": "스티커 노트",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1712,
-624
],
"parameters": {
"color": 4,
"width": 960,
"height": 832,
"content": "# INITIALIZATION & DATA COLLECTION\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n- Cron triggers daily at 7 PM\n- Set configs (DB IDs, email, LinkedIn settings)\n- Query Notion for unpublished ideas\n- Filter & clean the data\n- Count eligible posts\n\nIf no posts found → Send \"nothing to do\" email"
},
"typeVersion": 1
},
{
"id": "0c0f92c8-d1b4-4e11-86cf-dc32022e984b",
"name": "스티커 노트1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-720,
-624
],
"parameters": {
"color": 4,
"width": 1024,
"height": 832,
"content": "# CONTENT PROCESSING & AI GENERATION\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n- Process ideas one by one (batch size: 1)\n- Normalize data for AI prompt\n- OpenAI creates:\n - Full blog post (Markdown)\n - LinkedIn post with hashtags\n - SEO keywords & metadata\n- Validate & parse AI output\n\nQuality control ensures perfect formatting"
},
"typeVersion": 1
},
{
"id": "69e0c3a8-1239-4283-8c64-7c8aa8c3ec4e",
"name": "LinkedIn 발행 확인 조건문",
"type": "n8n-nodes-base.if",
"position": [
640,
-304
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "58a827f7-5153-4641-afbd-9bdf3d62ee2c",
"operator": {
"type": "boolean",
"operation": "equals"
},
"leftValue": "={{ $('Set (Configs)').item.json.LINKEDIN_PUBLISH || false }}",
"rightValue": true
}
]
}
},
"typeVersion": 2.2,
"alwaysOutputData": false
},
{
"id": "b3f96e1b-73d8-4153-84ef-952fd9785888",
"name": "스티커 노트2",
"type": "n8n-nodes-base.stickyNote",
"position": [
336,
-624
],
"parameters": {
"color": 5,
"width": 608,
"height": 832,
"content": "# CONTENT STORAGE & PUBLISH DECISION\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n- Save AI content to Articles database\n- Check LINKEDIN_PUBLISH setting\n\nTwo paths:\nPUBLISH = TRUE → Auto-publish flow\nPUBLISH = FALSE → Draft review flow\n\nAll content safely stored in Notion first"
},
"typeVersion": 1
},
{
"id": "c663ee05-545d-4c1e-995d-26ed92ecba6d",
"name": "스티커 노트3",
"type": "n8n-nodes-base.stickyNote",
"position": [
976,
-624
],
"parameters": {
"color": 5,
"width": 1536,
"height": 832,
"content": ""
},
"typeVersion": 1
},
{
"id": "995fee04-6be5-4b7b-ad46-6a0965696e5c",
"name": "스티커 노트4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1920,
-144
],
"parameters": {
"color": 5,
"width": 592,
"height": 352,
"content": "# PUBLISHING & COMPLETION\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\nAUTO-PUBLISH PATH:\n- Generate image prompt → Create image\n- Post to LinkedIn with image\n- Send success email\n- Mark as \"Published\"\n\nDRAFT PATH:\n- Email draft for review\n- Mark as \"Draft\"\n\nBoth paths ensure proper status tracking"
},
"typeVersion": 1
}
],
"pinData": {},
"connections": {
"6160be76-97f5-4f4c-bfa6-5e480080d854": {
"main": [
[
{
"node": "a7b80170-9832-46fb-85ba-8b87c5bd9da4",
"type": "main",
"index": 0
}
]
]
},
"52a1ad9c-cc6a-49a1-ab7f-9b3a8a2e8c2b": {
"main": [
[
{
"node": "a1a7482f-3868-402c-a05b-2535b8443ad7",
"type": "main",
"index": 0
}
]
]
},
"7e72fddb-7c81-4bf3-bd96-b02c3ebb53efa": {
"main": [
[
{
"node": "648ff7d2-a55e-4e0c-8b12-d3634d1f1b958",
"type": "main",
"index": 0
}
]
]
},
"219ddd0a-9ad8-4555-acf1-b002406738346": {
"main": [
[
{
"node": "c964ef88-6dea-4ea1-ad6c-2eef99b483646",
"type": "main",
"index": 0
}
]
]
},
"c3dfe348-0a68-45ee-b538-2f72fdbffaa9": {
"main": [
[
{
"node": "52a1ad9c-cc6a-49a1-ab7f-9b3a8a2e8c2b",
"type": "main",
"index": 0
}
]
]
},
"40b826f5-b1ef-490b-b208-f1754c1972d81": {
"main": [
[]
]
},
"2dd65c1f-d859-4809-857b-7f8b6e535306": {
"main": [
[
{
"node": "87a55a66-d609-47d2-a177-eddb4a7d9d560",
"type": "main",
"index": 0
}
]
]
},
"45e081e9-db15-4808-9c26-6f1089f23a0e": {
"main": [
[
{
"node": "7e72fddb-7c81-4bf3-bd96-b02c3ebb53efa",
"type": "main",
"index": 0
}
]
]
},
"a1a7482f-3868-402c-a05b-2535b8443ad7": {
"main": [
[
{
"node": "4e43c32b-407c-4a62-8a0d-2b5eea10c615",
"type": "main",
"index": 0
}
]
]
},
"3ab2103a-a358-415c-a4d1-1df7c3cb14f5": {
"main": [
[
{
"node": "2dd65c1f-d859-4809-857b-7f8b6e535306",
"type": "main",
"index": 0
}
]
]
},
"c964ef88-6dea-4ea1-ad6c-2eef99b483646": {
"main": [
[],
[
{
"node": "40b826f5-b1ef-490b-b208-f1754c1972d81",
"type": "main",
"index": 0
}
]
]
},
"e3a428a0-c52e-47f6-9281-1063f84e587c3": {
"main": [
[
{
"node": "3ab2103a-a358-415c-a4d1-1df7c3cb14f5",
"type": "main",
"index": 0
}
]
]
},
"87a55a66-d609-47d2-a177-eddb4a7d9d560": {
"main": [
[
{
"node": "128ee066-dca2-4c19-830b-621e3eafbbc0",
"type": "main",
"index": 0
}
]
]
},
"17809fd9-84d8-458b-a904-b497549c10dd": {
"main": [
[
{
"node": "4b21b649-4087-4ef2-aa8d-9ee53c5db581",
"type": "main",
"index": 0
}
]
]
},
"4e43c32b-407c-4a62-8a0d-2b5eea10c615": {
"main": [
[]
]
},
"7d00232e-be9d-4cdc-b072-eedc64dd79e3c": {
"main": [
[
{
"node": "e3a428a0-c52e-47f6-9281-1063f84e587c3",
"type": "main",
"index": 0
},
{
"node": "219ddd0a-9ad8-4555-acf1-b002406738346",
"type": "main",
"index": 0
}
]
]
},
"4b21b649-4087-4ef2-aa8d-9ee53c5db581": {
"main": [
[
{
"node": "c3dfe348-0a68-45ee-b538-2f72fdbffaa9",
"type": "main",
"index": 0
}
]
]
},
"69e0c3a8-1239-4283-8c64-7c8aa8c3ec4e": {
"main": [
[
{
"node": "17809fd9-84d8-458b-a904-b497549c10dd",
"type": "main",
"index": 0
}
],
[
{
"node": "6160be76-97f5-4f4c-bfa6-5e480080d854",
"type": "main",
"index": 0
}
]
]
},
"128ee066-dca2-4c19-830b-621e3eafbbc0": {
"main": [
[
{
"node": "69e0c3a8-1239-4283-8c64-7c8aa8c3ec4e",
"type": "main",
"index": 0
}
]
]
},
"017d6b4c-52f8-4238-abf1-95f44d08b182b": {
"main": [
[
{
"node": "20246ca2-9171-4ba8-8009-f43a43296c59",
"type": "main",
"index": 0
}
]
]
},
"648ff7d2-a55e-4e0c-8b12-d3634d1f1b958": {
"main": [
[
{
"node": "7d00232e-be9d-4cdc-b072-eedc64dd79e3c",
"type": "main",
"index": 0
}
]
]
}
}
}자주 묻는 질문
이 워크플로우를 어떻게 사용하나요?
위의 JSON 구성 코드를 복사하여 n8n 인스턴스에서 새 워크플로우를 생성하고 "JSON에서 가져오기"를 선택한 후, 구성을 붙여넣고 필요에 따라 인증 설정을 수정하세요.
이 워크플로우는 어떤 시나리오에 적합한가요?
고급 - 콘텐츠 제작, 멀티모달 AI
유료인가요?
이 워크플로우는 완전히 무료이며 직접 가져와 사용할 수 있습니다. 다만, 워크플로우에서 사용하는 타사 서비스(예: OpenAI API)는 사용자 직접 비용을 지불해야 할 수 있습니다.
관련 워크플로우 추천
YouTube 비디오 기반 자율 블로그 게시
ChatGPT, Sheets, Apify, Pexels, WordPress를 사용하여 YouTube 비디오를 자동으로 블로그에 게시합니다.
If
Set
Code
+
If
Set
Code
80 노드Oriol Seguí
콘텐츠 제작
GPT-4o Vision과 Claude 3.5 + 판매 분석을 사용하여 Shopify 제품 설명 생성
사용GPT-4o Vision과Claude 3.5 + 판매 분석으로 Shopify 제품 설명 생성
If
Set
Code
+
If
Set
Code
43 노드Kumar Shivam
콘텐츠 제작
AI驱动의이메일分诊与자동回复系统,통합OpenAI에이전트및Gmail
AI驱动의이메일分诊与자동回复系统,통합OpenAI에이전트및Gmail
If
Set
Gmail
+
If
Set
Gmail
68 노드Abdullahi Ahmed
콘텐츠 제작
회의록 및 액션 아이템 트래커
AI 기반 회의록: GPT-4, 작업 할당 및 다중 채널 배포 활용
If
Set
Code
+
If
Set
Code
38 노드Jitesh Dugar
콘텐츠 제작
✨🩷자동화소셜 미디어콘텐츠게시工厂 + 系统提示组合
基于动态系统提示및GPT-4o의AI驱动多平台소셜 미디어콘텐츠工厂
If
Set
Code
+
If
Set
Code
100 노드Amit Mehta
콘텐츠 제작
Printify 자동화 - 제목 및 설명 업데이트 - AlexK1919
GPT-4o-mini를 사용하여 Printify용 SEO 제품 제목 및 설명 자동 생성
If
Set
Code
+
If
Set
Code
26 노드Amit Mehta
콘텐츠 제작
워크플로우 정보
난이도
고급
노드 수28
카테고리2
노드 유형12
저자
Sagar Budhathoki
@sbmagar13A DevOps and AI Engineer with a passion for automation, infrastructure as code, building resilient systems, and exploring AI agents & MCP technologies.
외부 링크
n8n.io에서 보기 →
이 워크플로우 공유