AutomationFlowsAI & RAG › Tindi Article

Tindi Article

Tindi article. Uses httpRequest, lmChatOpenAi, chainLlm, outputParserStructured. Webhook trigger; 44 nodes.

Webhook trigger★★★★★ complexityAI-powered44 nodesHTTP RequestOpenAI ChatChain LlmOutput Parser StructuredAgentMemory Buffer Window
AI & RAG Trigger: Webhook Nodes: 44 Complexity: ★★★★★ AI nodes: yes Added:
Tindi Article — n8n workflow card showing HTTP Request, OpenAI Chat, Chain Llm integration

This workflow follows the Agent → Chainllm recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "Tindi article",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "fa5206f1-7a31-4cd3-92c9-90ce888093d4",
        "authentication": "basicAuth",
        "options": {
          "rawBody": true
        }
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -1680,
        592
      ],
      "id": "c9b24c59-73a8-4995-b408-a4c014ee3664",
      "name": "Webhook",
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.freepik.com/v1/ai/text-to-image",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "x-freepik-api-key",
              "value": "FPSX50946d27d1ed4dc4bb74b9e8102b0cb0"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"prompt\": \"{{ $json.text }}\",\n    \"negative_prompt\": \"b&w, person, aerial-view, cartoon, fantasy\",\n    \"guidance_scale\": \"\",\n    \"seed\": \"\",\n    \"num_images\": 2,\n    \"image\": {\n      \"size\": \"widescreen_16_9\"\n    },\n    \"styling\": {\n    \"style\": \"photo\",\n    \"effects\": {\n        \"color\": \"pastel\",\n        \"lightning\": \"warm\",\n        \"framing\": \"portrait\"\n    }\n}\n} ",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -304,
        16
      ],
      "id": "cd54cbfa-42f2-430e-8905-17c9bf70ff34",
      "name": "Create Freepik Image",
      "retryOnFail": true
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://tindimedia.vn/wp-json/wp/v2/media",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "wordpressApi",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "content.type",
              "value": "image/png"
            },
            {
              "name": "content-disposition",
              "value": "=attachment;filename=\"{{$('Webhook').item.json.body.post_title.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '').toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '')}}-1.png\""
            }
          ]
        },
        "sendBody": true,
        "contentType": "binaryData",
        "inputDataFieldName": "data",
        "options": {}
      },
      "id": "1740772e-e298-4ae6-9adc-ae0be9c94aa6",
      "name": "Upload Image 1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        144,
        -32
      ],
      "typeVersion": 4.2,
      "retryOnFail": true,
      "credentials": {
        "wordpressApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "toBinary",
        "sourceProperty": "data[0].base64",
        "options": {}
      },
      "type": "n8n-nodes-base.convertToFile",
      "typeVersion": 1.1,
      "position": [
        -80,
        -32
      ],
      "id": "f6149305-b80c-46ce-9626-cf49334eecbd",
      "name": "Convert to File 1"
    },
    {
      "parameters": {
        "operation": "toBinary",
        "sourceProperty": "data[0].base64",
        "options": {}
      },
      "type": "n8n-nodes-base.convertToFile",
      "typeVersion": 1.1,
      "position": [
        -80,
        352
      ],
      "id": "55eb8b66-779c-426d-b06a-9f2825616db8",
      "name": "Convert to File 2"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://tindimedia.vn/wp-json/wp/v2/media",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "wordpressApi",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "content.type",
              "value": "image/png"
            },
            {
              "name": "content-disposition",
              "value": "=attachment;filename=\"{{$('Webhook').item.json.body.post_title.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '').toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '')}}-2.png\""
            }
          ]
        },
        "sendBody": true,
        "contentType": "binaryData",
        "inputDataFieldName": "data",
        "options": {}
      },
      "id": "90487c63-fd68-4d4f-84df-72aa06b484b4",
      "name": "Upload Image 2",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        144,
        352
      ],
      "typeVersion": 4.2,
      "retryOnFail": true,
      "credentials": {
        "wordpressApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "value": "gpt-4o",
          "mode": "list",
          "cachedResultName": "gpt-4o"
        },
        "options": {
          "maxTokens": 3600
        }
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.2,
      "position": [
        1040,
        1120
      ],
      "id": "4586c3bb-4c78-4e6c-a339-05ca7533599b",
      "name": "OpenAI Chat Model",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Create a prompt to generate a realistic image for the article as follows in English, write only the command, do not use line breaks, write in one continuous line. {{ $json.output.outline }}",
        "messages": {
          "messageValues": [
            {
              "message": "=Notes:\n- Do not include any quotation marks or special characters."
            }
          ]
        }
      },
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "typeVersion": 1.6,
      "position": [
        -656,
        0
      ],
      "id": "0cd91078-97a7-40d8-beb0-ca4da66eb6cf",
      "name": "Create Image Generation Prompt"
    },
    {
      "parameters": {
        "mode": "markdownToHtml",
        "markdown": "={{ $json.output.content }}",
        "destinationKey": "content",
        "options": {
          "noHeaderId": true
        }
      },
      "type": "n8n-nodes-base.markdown",
      "typeVersion": 1,
      "position": [
        144,
        560
      ],
      "id": "13f254f7-6c06-4273-a54c-91f177b79f67",
      "name": "Markdown",
      "alwaysOutputData": false
    },
    {
      "parameters": {
        "numberInputs": 4
      },
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3.1,
      "position": [
        720,
        128
      ],
      "id": "28de36f0-9d51-4232-931b-1c66fa8546fd",
      "name": "Merge",
      "alwaysOutputData": true,
      "executeOnce": true
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose",
            "version": 2
          },
          "conditions": [
            {
              "id": "c1be27e0-9b50-4dce-a278-42154acd6a18",
              "leftValue": "={{ $('Webhook').item.json.body.post_settings.gen_image }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "looseTypeValidation": true,
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        -880,
        112
      ],
      "id": "117dd70a-b137-4e20-bba8-4a1f35968f9f",
      "name": "If Generate Image Needed"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose",
            "version": 2
          },
          "conditions": [
            {
              "id": "e7f38703-371f-449f-9112-95818d3707d8",
              "leftValue": "={{ $items('Webhook')[0].json.body.post_settings.gen_image }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "looseTypeValidation": true,
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        432,
        560
      ],
      "id": "d7c0be40-e088-4a27-89a8-fce3489133fa",
      "name": "If Generate Image"
    },
    {
      "parameters": {
        "jsCode": "// H\u00e0m chuy\u1ec3n \u0111\u1ed5i chu\u1ed7i th\u00e0nh slug\nfunction toSlug(str) {\n  if (typeof str !== 'string') return '';\n  str = str.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '');\n  str = str.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '');\n  return str;\n}\n// X\u1eed l\u00fd input\nconst items = $input.all();\n\n// L\u1ea5y title v\u00e0 t\u1ea1o base slug cho alt text\n// const title = items[3].json.output.title;\n// const baseAlt = toSlug(title); // \"quang-cao-trong-nha-tai-ha-noi\"\n\n// T\u1ea1o danh s\u00e1ch \u1ea3nh v\u1edbi alt text t\u1eeb description.rendered\nconst images = items.slice(0, 3).map((item, index) => {\n  const rendered = item.json.description.rendered;\n  // Regex \u0111\u1ec3 l\u1ea5y th\u1ebb <img>\n  const imgRegex = /<img[^>]+>/i;\n  const imgMatch = rendered.match(imgRegex);\n  if (!imgMatch) return '';\n\n  let imgTag = imgMatch[0];\n  // Th\u00eam ho\u1eb7c c\u1eadp nh\u1eadt alt attribute\n  // const altText = `${baseAlt}-image-${index + 1}`;\n  // if (imgTag.includes('alt=')) {\n  //   imgTag = imgTag.replace(/alt=\"[^\"]*\"/i, `alt=\"${altText}\"`);\n  // } else {\n  //   imgTag = imgTag.replace(/>$/, ` alt=\"${altText}\">`);\n  // }\n\n  // C\u1eadp nh\u1eadt width v\u00e0 height\n  const newWidth = item.json.media_details.sizes.medium_large.width;\n  const newHeight = item.json.media_details.sizes.medium_large.height;\n\n  imgTag = imgTag.replace(/\\s*width=\"[^\"]*\"/i, `width=\"${newWidth}\"`);\n  imgTag = imgTag.replace(/\\s*height=\"[^\"]*\"/i, `height=\"${newHeight}\"`);\n\n  // Th\u00eam ho\u1eb7c c\u1eadp nh\u1eadt title attribute\n  // if (imgTag.includes('title=')) {\n  //   imgTag = imgTag.replace(/title=\"[^\"]*\"/i, `title=\"${title}\"`);\n  // } else {\n  //   imgTag = imgTag.replace(/>$/, ` title=\"${title}\">`);\n  // }\n\n  // Thay th\u1ebf src attribute b\u1eb1ng medium_large source_url\n  const newSrc = item.json.media_details.sizes.medium_large.source_url;\n  imgTag = imgTag.replace(/src=\"[^\"]*\"/i, `src=\"${newSrc}\"`);\n\n  return rendered.replace(imgRegex, imgTag); // Return full rendered HTML with updated img tag\n});\n\n// L\u1ea5y HTML t\u1eeb content c\u1ee7a item[3]\nlet contentHtml = items[3].json.content;\n\n// Thay th\u1ebf <image-location> l\u1ea7n l\u01b0\u1ee3t b\u1eb1ng HTML c\u1ee7a \u1ea3nh\nlet imageIndex = 0;\ncontentHtml = contentHtml.replace(/<(img|image)-[^>]+>/g, () => {\n  if (imageIndex < images.length && images[imageIndex]) {\n    return images[imageIndex++];\n  }\n  return ''; // X\u00f3a c\u00e1c placeholder c\u00f2n l\u1ea1i\n});\n\n// C\u1eadp nh\u1eadt content trong items[2].json\nitems[3].json.content = contentHtml;\n\n// Tr\u1ea3 v\u1ec1 content\nreturn items[3];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        944,
        160
      ],
      "id": "e4589ac1-339b-44e1-a785-df4ca721d59c",
      "name": "Code"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=T\u1ea1o meta title, meta description, permalink v\u00e0 3-4 t\u1eeb kh\u00f3a ph\u1ee5 (m\u1edf r\u1ed9ng t\u1eeb t\u1eeb kh\u00f3a ch\u00ednh) cho b\u00e0i vi\u1ebft sau:\n- Ti\u00eau \u0111\u1ec1: {{ $json.title.raw }}\n- N\u1ed9i dung: {{ $json.content.raw }}\n- \u0110o\u1ea1n tr\u00edch: {{ $json.excerpt.rendered }}\n- T\u1eeb kh\u00f3a ch\u00ednh: {{ $items('Create Outline + Choose Keyword')[0].json.output.focus_keyword }}\n\nY\u00caU C\u1ea6U META TAG:\n\n1. Meta Title:\n- Ch\u1ee9a t\u1eeb kh\u00f3a ch\u00ednh ch\u00ednh x\u00e1c (nguy\u00ean v\u0103n, \u0111\u00fang th\u1ee9 t\u1ef1).\n- \u0110\u1eb7t t\u1eeb kh\u00f3a g\u1ea7n \u0111\u1ea7u ti\u00eau \u0111\u1ec1.\n- N\u00ean d\u00f9ng con s\u1ed1 n\u1ebfu ph\u00f9 h\u1ee3p.\n- \u0110\u1ed9 d\u00e0i \u2264 70 k\u00fd t\u1ef1.\n- N\u00eau r\u00f5 gi\u00e1 tr\u1ecb ch\u00ednh, c\u00f3 th\u1ec3 th\u00eam t\u00ean th\u01b0\u01a1ng hi\u1ec7u.\n\n2. Meta Description:\n- Ch\u1ee9a t\u1eeb kh\u00f3a ch\u00ednh (kh\u1edbp 100%).\n- \u0110\u1ed9 d\u00e0i \u2264 200 k\u00fd t\u1ef1.\n- C\u00f3 CTA r\u00f5 r\u00e0ng.\n- N\u00eau l\u1ee3i \u00edch n\u1ed5i b\u1eadt, t\u00f3m t\u1eaft n\u1ed9i dung ch\u00ednh.\n- V\u0103n phong l\u00f4i cu\u1ed1n, th\u1ec3 hi\u1ec7n chuy\u00ean m\u00f4n, h\u1ee9a h\u1eb9n gi\u00e1 tr\u1ecb gi\u1ea3i ph\u00e1p.\n\n3. Permalink:\n- Ch\u1ee9a t\u1eeb kh\u00f3a ch\u00ednh (ch\u00ednh x\u00e1c).\n- Ch\u1ec9 d\u00f9ng ch\u1eef th\u01b0\u1eddng, s\u1ed1, d\u1ea5u g\u1ea1ch ngang.\n- \u0110\u1ed9 d\u00e0i 55\u201375 k\u00fd t\u1ef1.\n- Ng\u1eafn g\u1ecdn, m\u00f4 t\u1ea3 \u0111\u00fang n\u1ed9i dung; b\u1ecf t\u1eeb th\u1eeba; kh\u00f4ng k\u00fd t\u1ef1 \u0111\u1eb7c bi\u1ec7t; d\u1ec5 nh\u1edb.\n\nCHECKLIST KI\u1ec2M TRA:\n\n- \u0110\u00fang m\u1ee5c \u0111\u00edch t\u00ecm ki\u1ebfm.\n- Ph\u00f9 h\u1ee3p lo\u1ea1i n\u1ed9i dung.\n- Gi\u00e1 tr\u1ecb r\u00f5 r\u00e0ng, CTA h\u1ea5p d\u1eabn.\n- Ch\u00ednh t\u1ea3 chu\u1ea9n, t\u1ed1i \u01b0u mobile.\n- Kh\u00f4ng d\u00f9ng placeholder.\n\nH\u01af\u1edaNG D\u1eaaN K\u1ef8 THU\u1eacT:\n- Kh\u00f4ng d\u00f9ng d\u1ea5u ngo\u1eb7c k\u00e9p trong m\u00f4 t\u1ea3.\n- Tr\u00e1nh k\u00fd t\u1ef1 \u0111\u1eb7c bi\u1ec7t.\n- D\u00f9ng UTF-8, vi\u1ebft hoa \u0111\u00fang chu\u1ea9n.",
        "hasOutputParser": true,
        "messages": {
          "messageValues": [
            {
              "message": "=You are an expert SEO content optimizer specialized in creating meta tags for marketing and advertising articles."
            }
          ]
        }
      },
      "id": "6367bc0a-7bfc-4d49-99b9-77e932a9ba4a",
      "name": "Agent SEO Expert",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1392,
        656
      ],
      "typeVersion": 1.5,
      "retryOnFail": false
    },
    {
      "parameters": {
        "jsonSchemaExample": "{\n  \"meta_title\": \"<ti\u00eau \u0111\u1ec1 meta>\",\n  \"meta_description\": \"<m\u00f4 t\u1ea3 meta>\",\n  \"permalink\": \"duong-dan-toi-uu\",\n  \"secondary_keywords\": \"c\u00e1c t\u1eeb kh\u00f3a ph\u1ee5\"\n}"
      },
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.2,
      "position": [
        1472,
        880
      ],
      "id": "10fc6dc3-9a34-433f-862d-8dac3501510b",
      "name": "Structured Output Parser2"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://tindimedia.vn/wp-json/rankmath/v1/updateMetaBulk",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "wordpressApi",
        "sendBody": true,
        "contentType": "multipart-form-data",
        "bodyParameters": {
          "parameters": [
            {
              "name": "=rows[{{$('Publish Post').item.json.id}}][focus_keyword]",
              "value": "={{ $items('Create Outline + Choose Keyword')[0].json.output.focus_keyword }},{{ $json.output.secondary_keywords }}"
            },
            {
              "name": "=rows[{{$('Publish Post').item.json.id}}][permalink]",
              "value": "={{ $json.output.permalink }}"
            },
            {
              "name": "=rows[{{$('Publish Post').item.json.id}}][title]",
              "value": "={{ $json.output.meta_title }}"
            },
            {
              "name": "=rows[{{$('Publish Post').item.json.id}}][description]",
              "value": "={{ $json.output.meta_description }}"
            }
          ]
        },
        "options": {}
      },
      "id": "c156c5dc-ba9a-4f2e-b14e-7c135e0d1a4b",
      "name": "Set SEO Tags",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1744,
        656
      ],
      "typeVersion": 4.2,
      "retryOnFail": true,
      "credentials": {
        "wordpressApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.freepik.com/v1/ai/text-to-image",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "x-freepik-api-key",
              "value": "FPSX50946d27d1ed4dc4bb74b9e8102b0cb0"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"prompt\": \"{{ $json.text }}\",\n    \"negative_prompt\": \"b&w, person, aerial-view, cartoon, fantasy\",\n    \"guidance_scale\": \"\",\n    \"seed\": \"\",\n    \"num_images\": 1,\n    \"image\": {\n      \"size\": \"widescreen_16_9\"\n    },\n    \"styling\": {\n    \"style\": \"photo\",\n    \"effects\": {\n        \"color\": \"pastel\",\n        \"lightning\": \"warm\",\n        \"framing\": \"portrait\"\n    }\n}\n} ",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -304,
        352
      ],
      "id": "eda57b16-d6c5-4fa8-a210-9fdc3f8522c2",
      "name": "Create Freepik Image 1",
      "retryOnFail": true
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.freepik.com/v1/ai/text-to-image",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "x-freepik-api-key",
              "value": "FPSX50946d27d1ed4dc4bb74b9e8102b0cb0"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"prompt\": \"{{ $json.text }}\",\n    \"negative_prompt\": \"b&w, person, aerial-view, cartoon, fantasy\",\n    \"guidance_scale\": \"\",\n    \"seed\": \"\",\n    \"num_images\": 1,\n    \"image\": {\n      \"size\": \"widescreen_16_9\"\n    },\n    \"styling\": {\n    \"style\": \"photo\",\n    \"effects\": {\n        \"color\": \"pastel\",\n        \"lightning\": \"warm\",\n        \"framing\": \"portrait\"\n    }\n}\n} ",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        720,
        -176
      ],
      "id": "97ce0bc3-bb18-4d3f-ad64-e6662fafe48e",
      "name": "Create Freepik Image 2",
      "retryOnFail": true
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://tindimedia.vn/wp-json/wp/v2/{{ $('Webhook').item.json.body.post_settings.post_type === \"post\" ? \"posts\" : $('Webhook').item.json.body.post_settings.post_type }}/{{ $input.all()[1].json.id }}",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "wordpressApi",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {}
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "featured_media",
              "value": "={{ $input.all()[0].json.id }}"
            }
          ]
        },
        "options": {}
      },
      "id": "18791b82-d59e-4051-9087-534c157cf456",
      "name": "Set Featured Image",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1968,
        -176
      ],
      "typeVersion": 4.2,
      "retryOnFail": true,
      "credentials": {
        "wordpressApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "toBinary",
        "sourceProperty": "data[0].base64",
        "options": {}
      },
      "type": "n8n-nodes-base.convertToFile",
      "typeVersion": 1.1,
      "position": [
        944,
        -176
      ],
      "id": "ba4ae279-9f2a-4d14-9587-28e14d888b56",
      "name": "Convert to File "
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://tindimedia.vn/wp-json/wp/v2/media",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "wordpressApi",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "content.type",
              "value": "image/png"
            },
            {
              "name": "content-disposition",
              "value": "=attachment;filename=\"{{$('Webhook').item.json.body.post_title.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '').toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '')}}-0.png\""
            }
          ]
        },
        "sendBody": true,
        "contentType": "binaryData",
        "inputDataFieldName": "data",
        "options": {}
      },
      "id": "d085f4bd-77e0-4826-8fa5-bdc59a138448",
      "name": "Upload Image",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1168,
        -176
      ],
      "typeVersion": 4.2,
      "retryOnFail": true,
      "credentials": {
        "wordpressApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose",
            "version": 2
          },
          "conditions": [
            {
              "id": "c253a615-c48b-41a3-9684-c07fd3259db2",
              "leftValue": "={{ $items('Webhook')[0].json.body.post_settings.gen_image }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "looseTypeValidation": true,
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1456,
        32
      ],
      "id": "30e31bf8-0b21-458b-ac1e-43d3cf4bef15",
      "name": "If Generate Image 1"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3.1,
      "position": [
        1744,
        -176
      ],
      "id": "bb4e1a05-e193-4b38-909c-b4ba920c1fea",
      "name": "Merge1"
    },
    {
      "parameters": {
        "operation": "toBinary",
        "sourceProperty": "data[1].base64",
        "options": {}
      },
      "type": "n8n-nodes-base.convertToFile",
      "typeVersion": 1.1,
      "position": [
        -80,
        160
      ],
      "id": "84f267f6-6b48-4041-a2d9-10f14fc927a6",
      "name": "Convert to File 3"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://tindimedia.vn/wp-json/wp/v2/media",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "wordpressApi",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "content.type",
              "value": "image/png"
            },
            {
              "name": "content-disposition",
              "value": "=attachment;filename=\"{{$('Webhook').item.json.body.post_title.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '').toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '')}}-3.png\""
            }
          ]
        },
        "sendBody": true,
        "contentType": "binaryData",
        "inputDataFieldName": "data",
        "options": {}
      },
      "id": "332b5f8e-c45d-45db-b982-fbcfbc5beb96",
      "name": "Upload Image 3",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        144,
        160
      ],
      "typeVersion": 4.2,
      "retryOnFail": true,
      "credentials": {
        "wordpressApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://tindimedia.vn/wp-json/wp/v2/media/{{ $json.id }}",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "wordpressApi",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "alt_text",
              "value": "={{ $json.title.raw }}"
            },
            {
              "name": "title",
              "value": "={{ $('Create Outline + Choose Keyword').item.json.output.title }}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        432,
        -32
      ],
      "id": "166dbdb2-8098-4c5e-ac66-1f03af149feb",
      "name": "Update Image 1",
      "retryOnFail": true,
      "credentials": {
        "wordpressApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://tindimedia.vn/wp-json/wp/v2/media/{{ $json.id }}",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "wordpressApi",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "alt_text",
              "value": "={{ $json.title.raw }}"
            },
            {
              "name": "title",
              "value": "={{ $('Create Outline + Choose Keyword').item.json.output.title }}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        432,
        160
      ],
      "id": "fd27f732-4a63-4f3d-883c-0baf5fc14abf",
      "name": "Update Image 3",
      "retryOnFail": true,
      "credentials": {
        "wordpressApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://tindimedia.vn/wp-json/wp/v2/media/{{ $json.id }}",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "wordpressApi",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "alt_text",
              "value": "={{ $json.title.raw }}"
            },
            {
              "name": "title",
              "value": "={{ $('Create Outline + Choose Keyword').item.json.output.title }}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        432,
        352
      ],
      "id": "b39e7a30-0283-4274-a605-ec5bcde0a17f",
      "name": "Update Image 2",
      "retryOnFail": true,
      "credentials": {
        "wordpressApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://tindimedia.vn/wp-json/wp/v2/media/{{ $json.id }}",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "wordpressApi",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "alt_text",
              "value": "={{ $json.title.raw }}"
            },
            {
              "name": "title",
              "value": "={{ $('Create Outline + Choose Keyword').item.json.output.title }}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1456,
        -176
      ],
      "id": "de281f5d-39f2-4e65-a581-12989d2801cf",
      "name": "Update Image",
      "credentials": {
        "wordpressApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://tindimedia.vn/wp-json/wp/v2/{{ $items('Webhook')[0].json.body.post_settings.post_type === \"post\" ? \"posts\" : $items('Webhook')[0].json.body.post_settings.post_type }}",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "wordpressApi",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "title",
              "value": "={{ $items('Webhook')[0].json.body.post_title }}"
            },
            {
              "name": "content",
              "value": "={{ $json.content }}"
            },
            {
              "name": "author",
              "value": "={{ $items('Webhook')[0].json.body.post_settings.author }}"
            },
            {
              "name": "status",
              "value": "={{ $items('Webhook')[0].json.body.post_settings.status }}"
            },
            {
              "name": "categories",
              "value": "={{ $items('Webhook')[0].json.body.post_settings.categories }}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1168,
        512
      ],
      "id": "f4b7d0f2-a4de-427d-9615-ba1261314f29",
      "name": "Publish Post",
      "credentials": {
        "wordpressApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://tindimedia.vn/wp-json/n8n-webhook/v1/callback",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "wordpressApi",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "message",
              "value": "=Execution successfully!"
            },
            {
              "name": "status",
              "value": "success"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1968,
        656
      ],
      "id": "64defe99-edd7-4828-bef7-dd26a49b2233",
      "name": "HTTP Request",
      "credentials": {
        "wordpressApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// L\u1ea5y n\u1ed9i dung outline t\u1eeb output\nconst outline = $json[\"output\"][\"outline\"];\n\n// T\u00e1ch t\u1eebng d\u00f2ng\nconst lines = outline\n  .split(\"\\n\")\n  .map(line => line.trim())\n  .filter(line => /^#+\\s+/.test(line)); // ch\u1ec9 gi\u1eef d\u00f2ng c\u00f3 d\u1ea5u #\n\n/**\n * Bi\u1ebfn th\u00e0nh list item c\u00f3 2 field:\n * - raw: gi\u1eef nguy\u00ean c\u1ea3 d\u1ea5u #\n * - section: ph\u1ea7n ti\u00eau \u0111\u1ec1 \u0111\u00e3 b\u1ecf d\u1ea5u #\n * - level: c\u1ea5p \u0111\u1ed9 ti\u00eau \u0111\u1ec1 (1=h1, 2=h2, ...)\n */\nconst items = lines.map(line => {\n  const match = line.match(/^(#+)\\s*(.*)$/);\n  const level = match[1].length; // s\u1ed1 l\u01b0\u1ee3ng d\u1ea5u #\n  const section = match[2];\n  return { json: { raw: line, section, level } };\n});\n\nreturn items;"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1104,
        560
      ],
      "id": "cc09a282-558e-48d4-9a31-773aa08b95d2",
      "name": "Code in JavaScript1"
    },
    {
      "parameters": {
        "jsCode": "// Nh\u1eadn to\u00e0n b\u1ed9 input items (\u0111\u00e3 c\u00f3 level, section)\nconst items = $input.all().map(i => i.json);\n\n// M\u1ea3ng k\u1ebft qu\u1ea3\nconst grouped = [];\n\nlet currentParent = null;\n\nfor (const item of items) {\n  if (item.level === 2) {\n    // N\u1ebfu l\u00e0 H2 \u2192 t\u1ea1o 1 nh\u00f3m m\u1edbi\n    currentParent = {\n      title: item.section,\n      raw: item.raw,\n      subsections: []\n    };\n    grouped.push(currentParent);\n  } else if (item.level > 2 && currentParent) {\n    // N\u1ebfu l\u00e0 H3, H4 \u2192 th\u00eam v\u00e0o nh\u00f3m hi\u1ec7n t\u1ea1i\n    currentParent.subsections.push(item.section);\n  }\n}\n\n// Tr\u1ea3 v\u1ec1 m\u1ed7i nh\u00f3m l\u00e0 1 item n8n\nreturn grouped.map(g => ({ json: g }));"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -880,
        560
      ],
      "id": "60903f94-22b3-4516-ba1c-2d2bb63f6b51",
      "name": "Code in JavaScript2"
    },
    {
      "parameters": {
        "jsCode": "const items = $input.all();\nlet merged = \"\";\n\nfor (const item of items) {\n  if (item.json.error) continue;\n\n  const rawTitle = item.json.output.title || \"\";\n  const content = item.json.output.content || \"\";\n\n  // Chu\u1ea9n h\u00f3a title (b\u1ecf \"5. \" ho\u1eb7c \"12. \")\n  const normalizedTitle = rawTitle.replace(/^\\d+\\.\\s*/, \"\").trim().toLowerCase();\n\n  // L\u1ea5y d\u00f2ng \u0111\u1ea7u ti\u00ean c\u1ee7a content\n  const firstLine = content.split(\"\\n\")[0].toLowerCase().trim();\n\n  // Ki\u1ec3m tra xem d\u00f2ng \u0111\u1ea7u ti\u00ean c\u00f3 ch\u1ee9a title hay kh\u00f4ng\n  const hasTitleInFirstLine = firstLine.includes(normalizedTitle);\n\n  // Ki\u1ec3m tra content c\u00f3 b\u1eaft \u0111\u1ea7u b\u1eb1ng \"##\"\n  const startsWithMarkdownHeader = content.trim().startsWith(\"##\");\n\n  if (hasTitleInFirstLine || startsWithMarkdownHeader) {\n    merged += `\\n\\n${content}`;\n  } else {\n    merged += `\\n\\n## ${rawTitle}\\n\\n${content}`;\n  }\n}\n\nreturn [\n  {\n    json: {\n      output: {\n        content: merged.trim(),\n      },\n    },\n  },\n];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -304,
        560
      ],
      "id": "f20cb775-6ffe-429a-930b-9ab30321f6bc",
      "name": "Code in JavaScript3"
    },
    {
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"type\": \"object\",\n  \"properties\": {\n    \"@context\": {\n      \"type\": [\"string\", \"null\"]\n    },\n    \"@graph\": {\n      \"type\": [\"array\", \"null\"],\n      \"items\": {\n        \"type\": [\"object\", \"null\"],\n        \"properties\": {\n          \"@type\": {\n            \"type\": [\"string\", \"null\"]\n          },\n\n          \"mainEntity\": {\n            \"type\": [\"array\", \"null\"],\n            \"items\": {\n              \"type\": [\"object\", \"null\"],\n              \"properties\": {\n                \"@type\": { \"type\": [\"string\", \"null\"] },\n                \"name\": { \"type\": [\"string\", \"null\"] },\n                \"acceptedAnswer\": {\n                  \"type\": [\"object\", \"null\"],\n                  \"properties\": {\n                    \"@type\": { \"type\": [\"string\", \"null\"] },\n                    \"text\": { \"type\": [\"string\", \"null\"] }\n                  },\n                  \"additionalProperties\": false\n                }\n              },\n              \"additionalProperties\": false\n            }\n          },\n\n          \"name\": {\n            \"type\": [\"string\", \"null\"]\n          },\n          \"description\": {\n            \"type\": [\"string\", \"null\"]\n          },\n\n          \"step\": {\n            \"type\": [\"array\", \"null\"],\n            \"items\": {\n              \"type\": [\"object\", \"null\"],\n              \"properties\": {\n                \"@type\": { \"type\": [\"string\", \"null\"] },\n                \"name\": { \"type\": [\"string\", \"null\"] },\n                \"text\": { \"type\": [\"string\", \"null\"] }\n              },\n              \"additionalProperties\": false\n            }\n          },\n\n          \"supply\": {\n            \"type\": [\"array\", \"null\"],\n            \"items\": {\n              \"type\": [\"object\", \"null\"],\n              \"properties\": {\n                \"@type\": { \"type\": [\"string\", \"null\"] },\n                \"name\": { \"type\": [\"string\", \"null\"] }\n              },\n              \"additionalProperties\": false\n            }\n          },\n\n          \"tool\": {\n            \"type\": [\"array\", \"null\"],\n            \"items\": {\n              \"type\": [\"object\", \"null\"],\n              \"properties\": {\n                \"@type\": { \"type\": [\"string\", \"null\"] },\n                \"name\": { \"type\": [\"string\", \"null\"] }\n              },\n              \"additionalProperties\": false\n            }\n          }\n        },\n\n        \"additionalProperties\": false\n      }\n    }\n  },\n\n  \"additionalProperties\": false\n}"
      },
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.3,
      "position": [
        448,
        1088
      ],
      "id": "0481c3a9-91bc-4656-920c-13c09fc11d4b",
      "name": "Structured Output Parser1"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=H\u00e3y t\u1ea1o \u0111o\u1ea1n JSON-LD Schema ho\u00e0n ch\u1ec9nh d\u1ef1a tr\u00ean d\u00e0n \u00fd b\u00e0i vi\u1ebft m\u00e0 t\u00f4i cung c\u1ea5p \u1edf ph\u1ea7n input.  \n\nY\u00eau c\u1ea7u:\n- Schema \u0111\u00fang chu\u1ea9n https://schema.org\n- T\u1ea1o \u0111\u1ea7y \u0111\u1ee7 3 ph\u1ea7n schema:\n  1. FAQPage\n  2. HowTo (quy tr\u00ecnh)\n  3. HowToSupply / HowToTool n\u1ebfu c\u00f3 trong n\u1ed9i dung\n- N\u1ed9i dung c\u00e2u h\u1ecfi, c\u00e2u tr\u1ea3 l\u1eddi, quy tr\u00ecnh ph\u1ea3i d\u1ef1a theo d\u00e0n \u00fd.\n- T\u1ef1 suy lu\u1eadn c\u00e2u h\u1ecfi t\u1eeb c\u00e1c ti\u00eau \u0111\u1ec1.\n- HowTo ph\u1ea3i c\u00f3 step, supply, tool khi ph\u00f9 h\u1ee3p.\n- Ch\u1ec9 output JSON-LD, kh\u00f4ng gi\u1ea3i th\u00edch g\u00ec th\u00eam.\n\nQuy t\u1eafc b\u1eaft bu\u1ed9c:\n- Kh\u00f4ng th\u00eam m\u00f4 t\u1ea3 b\u00ean ngo\u00e0i tag <script>.\n- Kh\u00f4ng escape k\u00fd t\u1ef1.\n- Kh\u00f4ng th\u00eam markdown.\n- Kh\u00f4ng gi\u1ea3i th\u00edch g\u00ec th\u00eam ngo\u00e0i output.\n\nInput \u0111\u1ea7u v\u00e0o: {{ $json.output.outline }}",
        "hasOutputParser": true,
        "options": {
          "systemMessage": "You are an expert in SEO and Schema Markup"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 2.2,
      "position": [
        368,
        864
      ],
      "id": "5d3d0dcb-51ac-4029-9dea-11c9e1722863",
      "name": "Create JSON Schema"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3.2,
      "position": [
        720,
        848
      ],
      "id": "1504b299-ffbe-4fb8-92d1-ca8ab01ceab7",
      "name": "Merge2"
    },
    {
      "parameters": {
        "jsCode": "// // Loop over input items and add a new field called 'myNewField' to the JSON of each one\n// for (const item of $input.all()) {\n//   item.json.myNewField = 1;\n// }\n\n// return $input.all();\n\n// L\u1ea5y d\u1eef li\u1ec7u merge t\u1eeb input\nconst content = $input.all()[0].json.content;\nconst context = $input.all()[1].json.output[\"@context\"] || \"https://schema.org\";\nconst graph = $input.all()[1].json.output[\"@graph\"] || [];\n\n// Build JSON-LD object\nconst jsonLd = {\n  \"@context\": context,\n  \"@graph\": graph\n};\n\n// Convert JSON-LD \u2192 string, format \u0111\u1eb9p\nconst jsonLdString = JSON.stringify(jsonLd, null, 2);\n\n// Build HTML final output\nconst finalHtml = `\n${content}\n\n<script type=\"application/ld+json\">\n${jsonLdString}\n</script>\n`.trim();\n\nreturn [{\n  content: finalHtml\n}];\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        944,
        848
      ],
      "id": "2e84cedb-0102-42aa-9679-8a5e1defbff5",
      "name": "Code in JavaScript"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Nhi\u1ec7m v\u1ee5:\nVi\u1ebft n\u1ed9i dung chi ti\u1ebft cho 1 ph\u1ea7n c\u1ee7a b\u00e0i vi\u1ebft SEO.\n\nD\u1eef li\u1ec7u \u0111\u1ea7u v\u00e0o:\nT\u1eeb kh\u00f3a ch\u00ednh c\u1ee7a ch\u1ee7 \u0111\u1ec1: {{ $items('Create Outline + Choose Keyword')[0].json.output.focus_keyword }}\nTi\u00eau \u0111\u1ec1 b\u00e0i vi\u1ebft: {{ $items('Create Outline + Choose Keyword')[0].json.output.title }}\nPh\u1ea7n c\u1ea7n vi\u1ebft: {{ $json.raw }}\nC\u00e1c ti\u1ec3u m\u1ee5c (n\u1ebfu c\u00f3): {{ $json.subsections || \"Kh\u00f4ng c\u00f3\" }}\n\nH\u01b0\u1edbng d\u1eabn vi\u1ebft:\n- V\u1edbi ph\u1ea7n gi\u1edbi thi\u1ec7u v\u00e0 k\u1ebft lu\u1eadn hay l\u1eddi m\u1eddi h\u1ee3p t\u00e1c, ch\u1ec9 vi\u1ebft 2-3 c\u00e2u ng\u1eafn.\n- V\u1edbi c\u00e1c ph\u1ea7n kh\u00e1c, h\u00e3y vi\u1ebft n\u1ed9i dung c\u1ef1c k\u1ef3 chi ti\u1ebft, c\u00f3 chi\u1ec1u s\u00e2u, ph\u00f9 h\u1ee3p v\u1edbi SEO.\n- M\u1ed7i ti\u1ec3u m\u1ee5c (sub-section) ph\u1ea3i d\u00e0i t\u1ed1i thi\u1ec3u 200 t\u1eeb.\n- Duy tr\u00ec m\u1eadt \u0111\u1ed9 t\u1eeb kh\u00f3a ch\u00ednh t\u1eeb 5% \u0111\u1ebfn 10% xuy\u00ean su\u1ed1t n\u1ed9i dung.\n- Vi\u1ebft theo \u0111o\u1ea1n ng\u1eafn 2\u20134 c\u00e2u, tr\u00e1nh \u0111o\u1ea1n d\u00e0i.\n- D\u00f9ng \u0111\u1ecbnh d\u1ea1ng Markdown, \u0111\u1eb7c bi\u1ec7t l\u00e0 danh s\u00e1ch g\u1ea1ch \u0111\u1ea7u d\u00f2ng \u0111\u1ec3 tr\u00ecnh b\u00e0y n\u1ed9i dung r\u00f5 r\u00e0ng, d\u1ec5 \u0111\u1ecdc.\n- Trong content n\u00ean c\u00f3 b\u1ea3ng (table) d\u01b0\u1edbi d\u1ea1ng html (n\u1ebfu c\u1ea7n thi\u1ebft cho s\u1ed1 li\u1ec7u).\n- Gi\u1eef gi\u1ecdng v\u0103n th\u00f4ng tin \u2013 chi ti\u1ebft \u2013 th\u00e2n thi\u1ec7n SEO (tr\u00e1nh lan man ho\u1eb7c qu\u1ea3ng c\u00e1o).\n\nY\u00eau c\u1ea7u \u0111\u1ea7u ra:\n- Ch\u1ec9 xu\u1ea5t n\u1ed9i dung thu\u1ea7n v\u0103n b\u1ea3n Markdown (ri\u00eang ph\u1ea7n b\u1ea3ng th\u00ec gi\u1eef nguy\u00ean html).\n- Ti\u00eau \u0111\u1ec1  v\u00e0 c\u00e1c ti\u00eau \u0111\u1ec1 ph\u1ee5 ph\u1ea3i \u0111\u01b0\u1ee3c \u0111\u00e1nh s\u1ed1 (1., 2. v\u1edbi ti\u00eau \u0111\u1ec1 ch\u00ednh v\u00e0 1.1, 1.2. v\u1edbi c\u00e1c ti\u00eau \u0111\u1ec1 con) nh\u01b0 d\u1eef li\u1ec7u \u0111\u1ea7u v\u00e0o.",
        "hasOutputParser": true,
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 2.2,
      "position": [
        -656,
        560
      ],
      "id": "7a48eded-76f5-476f-a248-e7775e663d88",
      "name": "AI Agent",
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "={{ $items('Webhook')[0].json.body.post_title }}_{{ $today }}"
      },
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "typeVersion": 1.3,
      "position": [
        -1456,
        816
      ],
      "id": "d61c60e0-6080-43d1-a26f-b693c52f71c9",
      "name": "Simple Memory"
    },
    {
      "parameters": {
        "jsonSchemaExample": "{\n  \"title\": \"1. Gi\u1edbi thi\u1ec7u\",\n  \"content\": \"N\u1ed9i dung c\u1ee7a ph\u1ea7n gi\u1edbi thi\u1ec7u\"\n}"
      },
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.3,
      "position": [
        -592,
        784
      ],
      "id": "eaa913fd-0fe2-427f-8ed9-b29f14d51503",
      "name": "Structured Output Parser5"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Nhi\u1ec7m v\u1ee5 c\u1ee7a b\u1ea1n bao g\u1ed3m ba ph\u1ea7n ch\u00ednh:\n\n1. Tr\u1ea3 v\u1ec1 ti\u00eau \u0111\u1ec1 b\u00e0i vi\u1ebft: \"{{ $json.body.post_title }}\".\n\n2. Tr\u00edch xu\u1ea5t T\u1eeb kh\u00f3a ch\u00ednh (SEO Focus Keyword)\n- H\u00e3y tr\u00edch xu\u1ea5t m\u1ed9t t\u1eeb kh\u00f3a ch\u00ednh th\u00e2n thi\u1ec7n v\u1edbi SEO t\u1eeb ti\u00eau \u0111\u1ec1: {{ $json.body.post_title }}\n- T\u1eeb kh\u00f3a ph\u1ea3i l\u00e0 m\u1ed9t c\u1ee5m t\u1eeb c\u00f3 xu\u1ea5t hi\u1ec7n trong ti\u00eau \u0111\u1ec1 g\u1ed1c.\n- Ch\u1ec9 tr\u1ea3 v\u1ec1 m\u1ed9t t\u1eeb kh\u00f3a ch\u00ednh h\u1ee3p l\u1ec7 duy nh\u1ea5t.\n\n3. T\u1ea1o D\u00e0n \u00fd B\u00e0i vi\u1ebft\nH\u00e3y t\u1ea1o m\u1ed9t d\u00e0n \u00fd ho\u00e0n ch\u1ec9nh cho b\u00e0i vi\u1ebft SEO d\u00e0i, s\u1eed d\u1ee5ng t\u1eeb kh\u00f3a ch\u00ednh \u0111\u00e3 tr\u00edch xu\u1ea5t.\nY\u00eau c\u1ea7u c\u1ee5 th\u1ec3:\n- Ph\u1ea7n m\u1edf \u0111\u1ea7u (h2):\n - Gi\u1edbi thi\u1ec7u v\u1ea5n \u0111\u1ec1 ho\u1eb7c n\u1ed7i \u0111au c\u1ee7a ng\u01b0\u1eddi \u0111\u1ecdc.\n - N\u00eau l\u1ee3i \u00edch ho\u1eb7c gi\u1ea3i ph\u00e1p m\u00e0 b\u00e0i vi\u1ebft mang l\u1ea1i.\n - M\u1edf \u0111\u1ea7u b\u1eb1ng th\u1ebb h2 (## ho\u1eb7c <h2>).\n- Th\u00e2n b\u00e0i:\n - T\u1ea1o 6-8 m\u1ee5c ch\u00ednh, m\u1ed7i m\u1ee5c l\u00e0 m\u1ed9t th\u1ebb H2, c\u00f3 s\u1ed1 th\u1ee9 t\u1ef1 (## 1., ## 2. ho\u1eb7c <h2> 1., <h2>2.).\n - \u00cdt nh\u1ea5t m\u1ed9t ti\u00eau \u0111\u1ec1 H2 ph\u1ea3i ch\u1ee9a ch\u00ednh x\u00e1c t\u1eeb kh\u00f3a ch\u00ednh.\n - C\u00f3 th\u1ec3 th\u00eam m\u1ee5c con (H3) n\u1ebfu c\u1ea7n, theo d\u1ea1ng: ### 1.1., ### 1.2 ho\u1eb7c <h3> 1.1., <h3> 1.2.\n - M\u1ed7i m\u1ee5c ho\u1eb7c m\u1ee5c con c\u1ea7n c\u00f3 1\u20132 c\u00e2u t\u00f3m t\u1eaft gi\u1ea3i th\u00edch n\u1ed9i dung.\n- K\u1ebft lu\u1eadn:\n - Vi\u1ebft ng\u1eafn g\u1ecdn, t\u00f3m t\u1eaft n\u1ed9i dung ch\u00ednh.\n- L\u1eddi m\u1eddi h\u1ee3p t\u00e1c c\u00f9ng Tindimedia:\n - Vi\u1ebft ng\u1eafn g\u1ecdn, C\u00f3 th\u1ec3 khuy\u1ebfn kh\u00edch h\u00e0nh \u0111\u1ed9ng (CTA) ho\u1eb7c n\u00eau l\u1ee3i \u00edch t\u1ed5ng th\u1ec3.",
        "hasOutputParser": true,
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 2.2,
      "position": [
        -1456,
        592
      ],
      "id": "76a2b113-7f07-4c00-a43a-48f50323dbeb",
      "name": "Create Outline + Choose Keyword"
    },
    {
      "parameters": {
        "jsonSchemaExample": "{\n\t\"title\": \"Ti\u00eau \u0111\u1ec1 b\u00e0i vi\u1ebft\",\n\t\"outline\": \"T\u00f3m t\u1eaft c\u00e1c \u0111\u1ea7u m\u1ee5c c\u1ee7a b\u00e0i vi\u1ebft\",\n    \"focus_keyword\": \"T\u1eeb kh\u00f3a ch\u00ednh\"\n}"
      },
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.3,
      "position": [
        -1328,
        816
      ],
      "id": "ab83d012-08f3-42a3-84bc-c1ee115e9d29",
      "name": "Structured Output Parser6"
    },
    {
      "parameters": {
        "jsCode": "// D\u00e1n v\u00e0o node Function c\u1ee7a n8n ho\u1eb7c ch\u1ea1y trong Node.js\nconst inputContent = $json.output.content || \"\"; // ho\u1eb7c l\u1ea5y t\u1eeb ngu\u1ed3n b\u1ea1n c\u1ea7n\n\n// T\u00e1ch th\u00e0nh d\u00f2ng\nconst lines = inputContent.split(/\\r?\\n/);\n\n// 1) X\u00f3a H2 \u0111\u1ea7u ti\u00ean\nlet removedFirstH2 = false;\nconst afterRemove = [];\nfor (const line of lines) {\n  if (!removedFirstH2 && /^##\\s+/.test(line)) {\n    removedFirstH2 = true;\n    continue; // b\u1ecf qua H2 \u0111\u1ea7u ti\u00ean\n  }\n  afterRemove.push(line);\n}\n\n// h\u00e0m t\u00ecm index k\u00fd t\u1ef1 ch\u1eef c\u00e1i Unicode \u0111\u1ea7u ti\u00ean\nfunction firstLetterIndex(s) {\n  for (let i = 0; i < s.length; i++) {\n    const ch = s[i];\n    // isAlpha approximation: ki\u1ec3m tra b\u1eb1ng regex Unicode letter\n    if (/\\p{L}/u.test(ch)) return i;\n  }\n  return -1;\n}\n\n// 2) \u0110\u00e1nh s\u1ed1 l\u1ea1i H2/H3, \u0111\u1ed3ng th\u1eddi x\u00f3a h\u1ebft s\u1ed1 c\u0169 (cho \u0111\u1ebfn ch\u1eef c\u00e1i \u0111\u1ea7u ti\u00ean)\nlet h2Count = 0;\nlet h3Count = 0;\nconst outLines = [];\n\nfor (const line of afterRemove) {\n  const m2 = line.match(/^\\s*##\\s+(.*)$/);\n  const m3 = line.match(/^\\s*###\\s+(.*)$/);\n\n  if (m2) {\n    h2Count += 1;\n    h3Count = 0;\n    let title = m2[1].trim();\n    const idx = firstLetterIndex(title);\n    if (idx > 0) title = title.slice(idx).trim();\n    // N\u1ebfu idx == -1 (kh\u00f4ng t\u00ecm th\u1ea5y ch\u1eef) th\u00ec gi\u1eef nguy\u00ean title\n    outLines.push(`## ${h2Count}. ${title}`);\n    continue;\n  }\n\n  if (m3) {\n    h3Count += 1;\n    let title = m3[1].trim();\n    const idx = firstLetterIndex(title);\n    if (idx > 0) title = title.slice(idx).trim();\n    outLines.push(`### ${h2Count}.${h3Count}. ${title}`);\n    continue;\n  }\n\n  outLines.push(line);\n}\n\n// K\u1ebft qu\u1ea3\nconst finalContent = outLines.join(\"\\n\");\n\n// Tr\u1ea3 v\u1ec1 cho n8n\nreturn [\n  {\n    json: {\n      output: {\n        content: finalContent.trim(),\n      },\n    },\n  },\n];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -80,
        560
      ],
      "id": "5d2316a2-2349-4716-be29-ca82353e5314",
      "name": "Code in JavaScript4"
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Create Outline + Choose Keyword",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Freepik Image": {
      "main": [
        [
          {
            "node": "Convert to File 1",
            "type": "main",
            "index": 0
          },
          {
            "node": "Convert to File 3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload Image 1": {
      "main": [
        [
          {
            "node": "Update Image 1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert to File 1": {
      "main": [
        [
          {
            "node": "Upload Image 1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert to File 2": {
      "main": [
        [
          {
            "node": "Upload Image 2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload Image 2": {
      "main": [
        [
          {
            "node": "Update Image 2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Agent SEO Expert",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "Create Image Generation Prompt",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "Create JSON Schema",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "Create Outline + Choose Keyword",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Create Image Generation Prompt": {
      "main": [
        [
          {
            "node": "Create Freepik Image",
            "type": "main",
            "index": 0
          },
          {
            "node": "Create Freepik Image 1",
            "type": "main",
            "index": 0
          },
          {
            "node": "Create Freepik Image 2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Markdown": {
      "main": [
        [
          {
            "node": "If Generate Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Generate Image Needed": {
      "main": [
        [
          {
            "node": "Create Image Generation Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Generate Image": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 3
          }
        ],
        [
          {
            "node": "Merge2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code": {
      "main": [
        [
          {
            "node": "Publish Post",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser2": {
      "ai_outputParser": [
        [
          {
            "node": "Agent SEO Expert",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Agent SEO Expert": {
      "main": [
        [
          {
            "node": "Set SEO Tags",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Freepik Image 1": {
      "main": [
        [
          {
            "node": "Convert to File 2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Freepik Image 2": {
      "main": [
        [
          {
            "node": "Convert to File ",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert to File ": {
      "main": [
        [
          {
            "node": "Upload Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload Image": {
      "main": [
        [
          {
            "node": "Update Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Generate Image 1": {
      "main": [
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 1
          }
        ],
        []
      ]
    },
    "Merge1": {
      "main": [
        [
          {
            "node": "Set Featured Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert to File 3": {
      "main": [
        [
          {
            "node": "Upload Image 3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload Image 3": {
      "main": [
        [
          {
            "node": "Update Image 3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Image 1": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Image 3": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Update Image 2": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Update Image": {
      "main": [
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Publish Post": {
      "main": [
        [
          {
            "node": "Agent SEO Expert",
            "type": "main",
            "index": 0
          },
          {
            "node": "If Generate Image 1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set SEO Tags": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript1": {
      "main": [
        [
          {
            "node": "Code in JavaScript2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript2": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript3": {
      "main": [
        [
          {
            "node": "Code in JavaScript4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser1": {
      "ai_outputParser": [
        [
          {
            "node": "Create JSON Schema",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Create JSON Schema": {
      "main": [
        [
          {
            "node": "Merge2",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge2": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "Publish Post",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Simple Memory": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "index": 0
          },
          {
            "node": "Create Outline + Choose Keyword",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser5": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Code in JavaScript3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Outline + Choose Keyword": {
      "main": [
        [
          {
            "node": "Create JSON Schema",
            "type": "main",
            "index": 0
          },
          {
            "node": "If Generate Image Needed",
            "type": "main",
            "index": 0
          },
          {
            "node": "Code in JavaScript1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser6": {
      "ai_outputParser": [
        [
          {
            "node": "Create Outline + Choose Keyword",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript4": {
      "main": [
        [
          {
            "node": "Markdown",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        []
      ]
    }
  },
  "active": true,
  "settings": {
    "executionOrder": "v1",
    "callerPolicy": "workflowsFromSameOwner",
    "errorWorkflow": "jaC81abdrkPRBGkT"
  },
  "versionId": "250a80c8-f956-4d42-affb-369f2dab393d",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "rG5bKILsFomWCuDP",
  "tags": []
}

Credentials you'll need

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

Pro

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

About this workflow

Tindi article. Uses httpRequest, lmChatOpenAi, chainLlm, outputParserStructured. Webhook trigger; 44 nodes.

Source: https://github.com/vinhlexuan/tindi-wp/blob/671195f8536aa57be703d70fb92c5c95755b4368/n8n/workflow/tindi_article.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

leads. Uses supabase, gmail, formTrigger, httpRequest. Webhook trigger; 62 nodes.

Supabase, Gmail, Form Trigger +13
AI & RAG

🧠 Gwen – The AI Voice Marketing Agent Gwen is your intelligent voice-powered marketing assistant built in n8n. She combines the power of OpenAI, ElevenLabs, and automation workflows to handle content

Tool Workflow, Memory Buffer Window, Agent +10
AI & RAG

Tired of grinding out YouTube content? This n8n workflow turns AI into your personal video factory—creating engaging, faceless shorts on autopilot. Perfect for creators, marketers, or side-hustlers lo

HTTP Request, Google Drive, Google Sheets +6
AI & RAG

Public-facing professionals (developer advocates, founders, marketers, content creators) who get bombarded with LinkedIn messages that aren't actually for them - support requests when you're in market

Slack, HTTP Request, Agent +4
AI & RAG

Faceless YouTube Generator. Uses httpRequest, limit, googleDrive, googleSheets. Webhook trigger; 49 nodes.

HTTP Request, Google Drive, Google Sheets +7