{
  "id": "3RrE9MTfcGIPM4nh",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Generate LinkedIn Post from Web Page - text only",
  "tags": [],
  "nodes": [
    {
      "id": "b019d964-c28f-4685-b1b5-2a7bed8b29dc",
      "name": "On form submission",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -4280,
        1040
      ],
      "parameters": {
        "options": {},
        "formTitle": "LinkedIn Post Generator",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Page URL",
              "placeholder": "https://www.airtop.ai/automations/ai-web-agent-n8n",
              "requiredField": true
            },
            {
              "fieldType": "textarea",
              "fieldLabel": "Instructions"
            }
          ]
        },
        "formDescription": "Fill out these fields and you'll have a full LinkedIn post ready to go in a minute. "
      },
      "typeVersion": 2.2
    },
    {
      "id": "f73c1893-11e6-46a2-8e45-60472c150bc2",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -4020,
        820
      ],
      "parameters": {
        "width": 2040,
        "height": 480,
        "content": "# Content Generation & Revisions"
      },
      "typeVersion": 1
    },
    {
      "id": "ebf8a3a0-c823-4384-83c6-f8b7bfb02a84",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -4500,
        820
      ],
      "parameters": {
        "color": 6,
        "width": 440,
        "height": 480,
        "content": "# To generate post and visual - start here!"
      },
      "typeVersion": 1
    },
    {
      "id": "ad860e11-b154-4401-8e58-950b6e7a9afb",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -2560,
        1100
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1",
          "cachedResultName": "gpt-4.1"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "5c5e136e-76cb-4747-add1-90e5636f7890",
      "name": "Set Post",
      "type": "n8n-nodes-base.set",
      "position": [
        -3160,
        920
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "346bd2cf-743b-4b13-a34e-528a95e1a617",
              "name": "URL",
              "type": "string",
              "value": "={{ $('Set Params').item.json.URL }}"
            },
            {
              "id": "8430fd16-f865-4b37-b7bc-7e910badbb19",
              "name": "Instructions",
              "type": "string",
              "value": "= - "
            },
            {
              "id": "35a9e113-ea92-438d-ac25-41ed9a74071f",
              "name": "Post",
              "type": "string",
              "value": "={{ $json.output }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "239536cc-62ef-415d-a39f-4e42a583899f",
      "name": "Set Params",
      "type": "n8n-nodes-base.set",
      "position": [
        -3760,
        1040
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "346bd2cf-743b-4b13-a34e-528a95e1a617",
              "name": "URL",
              "type": "string",
              "value": "={{ $('On form submission').item.json['Page URL'] }}"
            },
            {
              "id": "8430fd16-f865-4b37-b7bc-7e910badbb19",
              "name": "Instructions",
              "type": "string",
              "value": "={{ $('On form submission').item.json.Instructions }}"
            },
            {
              "id": "35a9e113-ea92-438d-ac25-41ed9a74071f",
              "name": "Post",
              "type": "string",
              "value": "= - "
            },
            {
              "id": "cd1fac8d-6b57-4072-966f-67e3cf1b9cc4",
              "name": "=Webpage_content",
              "type": "string",
              "value": "={{ $json.data.modelResponse.scrapedContent.text }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "c5b7b602-604b-4176-98b4-2d6d8f433a27",
      "name": "Set Post1",
      "type": "n8n-nodes-base.set",
      "position": [
        -2280,
        580
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "346bd2cf-743b-4b13-a34e-528a95e1a617",
              "name": "URL",
              "type": "string",
              "value": "={{ $('Set Params').item.json.URL }}"
            },
            {
              "id": "8430fd16-f865-4b37-b7bc-7e910badbb19",
              "name": "Instructions",
              "type": "string",
              "value": "={{ $json.data.text }}"
            },
            {
              "id": "35a9e113-ea92-438d-ac25-41ed9a74071f",
              "name": "Post",
              "type": "string",
              "value": "={{ $('Set Post').item.json.Post }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "9498e4b7-187b-42fc-9d37-fc395bbe683d",
      "name": "Check Post Text Feedback",
      "type": "@n8n/n8n-nodes-langchain.textClassifier",
      "position": [
        -2560,
        920
      ],
      "parameters": {
        "options": {
          "multiClass": false
        },
        "inputText": "={{ $json.data.text }}",
        "categories": {
          "categories": [
            {
              "category": "Edit",
              "description": "The email has been reviewed, but the human requests modifications to the post text before it is sent like tweaks, removing parts, rewording, etc. This could include suggested edits, rewording, or major revisions to the post text. |Example phrases include:\"Can we tweak this part of the post?\"\"Needs some changes to this sentence.\"\"I\u2019d like to reword the post.\"\"Not quite right\u2014let\u2019s revise the text.\"\"Can you adjust the text before sending?\"\"Don't mention Make in the text\"\"change the style of the writing\"\"tone of voice is not consistent with our branding\""
            },
            {
              "category": "Approved",
              "description": "The email has been reviewed and accepted as-is. The human explicitly or implicitly expresses approval, indicating that no changes are needed. |Example phrases include:\"Looks good.\"\"Go ahead and send it.\"\"This works for me.\"\"Approved.\"\"No changes needed.\"\"ok\""
            },
            {
              "category": "Declined",
              "description": "The email has been reviewed, but the human requests not to proceed with the post. |Example phrases include:\"Let's cancel this post.\"\"Don't post\""
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "8f686580-ae0a-4001-9852-b50efb9d6e03",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1920,
        820
      ],
      "parameters": {
        "color": 4,
        "width": 440,
        "height": 480,
        "content": "# Send Final Post"
      },
      "typeVersion": 1
    },
    {
      "id": "268337f8-8ade-45ab-86b3-c4d9a436ed93",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -4500,
        -480
      ],
      "parameters": {
        "color": 5,
        "width": 1060,
        "height": 1140,
        "content": "README\n# Generate LinkedIn Posts from Any Webpage (text only)\n## Use Case\nTurn any web page into a compelling LinkedIn post \u2014 complete with an AI-generated image. This automation is ideal for sharing content like blog posts, case studies, or product updates in a polished and engaging format.\n\n## What This Automation Does\nGiven a page URL and optional user instructions, this automation:\n- Scrapes the content of the webpage\n- Uses AI to write a clear, educational, and LinkedIn-optimized post\n- Sends both to Slack for review and approval\n- Handles feedback and revisions via Slack interactions\n\nInput:\n- **Page URL** \u2014 The link to the webpage (required)\n- **Instructions** \u2014 Optional notes on tone, emphasis, or format\n\nOutput:\n- LinkedIn post text\n- Slack message with review/approval options\n\n## How It Works\n1. **Form Submission**: User inputs a web page and optional instructions.\n2. **Web Scraping**: Uses Airtop to extract page content.\n3. **Post Generation**: AI agent writes a post based on the page and instructions.\n4. **Slack Review Flow**:\n   - Post and image sent to Slack for feedback\n   - User can approve, request revisions, or decline\n   - Revisions trigger reprocessing steps automatically\n5. **Final Post Delivery**: Approved post is sent back to Slack, ready to publish.\n\n## Setup Requirements\n1. Airtop API key\n2. OpenAI credentials for post and image prompt generation\n3. Slack OAuth integration with a review channel\n4. A sub-workflow for branded image generation\n\n## Next Steps\n- **Post Directly**: Add LinkedIn publishing to automate the full content workflow.\n- **Template Variations**: Offer post style presets (e.g., technical, story-driven, short-form).\n- **CRM Sync**: Save approved posts and stats in Airtable or Notion for team use.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "32ed47df-d2f2-483a-b011-7adad6559007",
      "name": "Final Version",
      "type": "n8n-nodes-base.slack",
      "position": [
        -1740,
        920
      ],
      "parameters": {
        "text": "=----------------  \nFINAL POST:\n----------------  \n\n{{ $('Set Post').item.json.Post }}\n",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C08QUB9N5FX",
          "cachedResultName": "gen-social-posts"
        },
        "otherOptions": {
          "unfurl_links": false,
          "unfurl_media": false
        },
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "58845733-16ca-4d29-bc75-f3334cea4be2",
      "name": "Human Revision of Text",
      "type": "n8n-nodes-base.slack",
      "position": [
        -2860,
        920
      ],
      "parameters": {
        "select": "channel",
        "message": "=----------------\n\n{{ $json.Post }}\n\n-----------------\nBased on: {{ $json.URL }}",
        "options": {
          "limitWaitTime": {
            "values": {
              "resumeUnit": "days",
              "resumeAmount": 3
            }
          },
          "appendAttribution": false,
          "responseFormTitle": "Image Feedback"
        },
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C08QUB9N5FX",
          "cachedResultName": "gen-social-posts"
        },
        "operation": "sendAndWait",
        "responseType": "freeText",
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "86e48876-440b-485a-893a-a691424d3dba",
      "name": "Generate Post Text",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        -3540,
        1040
      ],
      "parameters": {
        "text": "=Write a helpful educational, and engaging LinkedIn posts based on a webpage scraped content below or the Post text below and according to the instructions provided by the user.\n\nInstructions: {{ $json.Instructions }}\n\n{{ $json.Post }}\n\n{{ $json.Webpage_content }}",
        "prompt": "define",
        "options": {},
        "resource": "assistant",
        "assistantId": {
          "__rl": true,
          "mode": "list",
          "value": "asst_aYEHuzWeFxMBN2qu4FnXRsJ4",
          "cachedResultName": "Social Media Writer"
        }
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "d6e68ba2-49c2-4e39-806d-4e70fa9f4cac",
      "name": "Get Page",
      "type": "n8n-nodes-base.airtop",
      "position": [
        -3980,
        1040
      ],
      "parameters": {
        "url": "={{ (() => {\n  const url = ($json['Page URL'] || '').trim();\n  return url && (url.startsWith('http://') || url.startsWith('https://')) ? url : 'http://' + url;\n})() }}",
        "resource": "extraction",
        "operation": "scrape",
        "sessionMode": "new"
      },
      "credentials": {
        "airtopApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "e0eb5228-9ec6-465c-b323-fd2ee9962719",
  "connections": {
    "Get Page": {
      "main": [
        [
          {
            "node": "Set Params",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Post": {
      "main": [
        [
          {
            "node": "Human Revision of Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Post1": {
      "main": [
        [
          {
            "node": "Generate Post Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Params": {
      "main": [
        [
          {
            "node": "Generate Post Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Check Post Text Feedback",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Generate Post Text": {
      "main": [
        [
          {
            "node": "Set Post",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "On form submission": {
      "main": [
        [
          {
            "node": "Get Page",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Human Revision of Text": {
      "main": [
        [
          {
            "node": "Check Post Text Feedback",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Post Text Feedback": {
      "main": [
        [
          {
            "node": "Set Post1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Final Version",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}