8
n8n 한국어amn8n.com

블로그 및 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)는 사용자 직접 비용을 지불해야 할 수 있습니다.

워크플로우 정보
난이도
고급
노드 수28
카테고리2
노드 유형12
난이도 설명

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

저자
Sagar Budhathoki

Sagar Budhathoki

@sbmagar13

A DevOps and AI Engineer with a passion for automation, infrastructure as code, building resilient systems, and exploring AI agents & MCP technologies.

외부 링크
n8n.io에서 보기

이 워크플로우 공유

카테고리

카테고리: 34