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 →
{
"name": "Blog Post \u2192 Social Media",
"nodes": [
{
"parameters": {},
"id": "3ddb7b5e-c6e1-4046-92c7-be1af5fd04a6",
"name": "New Blog Post",
"type": "n8n-nodes-base.rssFeedTrigger",
"typeVersion": 1,
"position": [
-2672,
96
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "f1",
"name": "postTitle",
"value": "={{ $json.title }}",
"type": "string"
},
{
"id": "f2",
"name": "postUrl",
"value": "={{ $json.link }}",
"type": "string"
},
{
"id": "f3",
"name": "postDescription",
"value": "={{ $json.contentSnippet || $json.description || '' }}",
"type": "string"
},
{
"id": "f4",
"name": "postCategories",
"value": "={{ Array.isArray($json.categories) ? $json.categories.join(', ') : ($json.categories || '') }}",
"type": "string"
}
]
},
"options": {}
},
"id": "e31081a3-b1fc-41c5-9928-05d2f95711af",
"name": "Prepare Post Data",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
-2432,
96
]
},
{
"parameters": {
"jsCode": "const d = $input.first().json;\n\nreturn [{\n json: {\n ...d,\n anthropicBody: JSON.stringify({\n model: 'claude-sonnet-4-6',\n max_tokens: 1024,\n messages: [{\n role: 'user',\n content: [\n 'You are the social media manager for Teddy Spark (teddyspark.co), a maker, tech, and DIY blog.',\n '',\n 'A new blog post has just been published. Draft three platform-specific posts to promote it. Each post should be written for a different audience and context \u2014 not just the same text reformatted.',\n '',\n 'Post details:',\n 'Title: ' + d.postTitle,\n 'URL: ' + d.postUrl,\n 'Description: ' + d.postDescription,\n 'Categories: ' + d.postCategories,\n '',\n 'Platform requirements:',\n '- facebook: Audience is hobbyists, makers, and general tech enthusiasts. Conversational and personal. Tell the story behind the build or problem solved. 100-200 words. Include the URL at the end.',\n '- linkedin: Audience is professionals and engineers. Lead with the insight or skill. Highlight what someone could learn or apply. Professional but not corporate. Include the URL at the end. 150-250 words.',\n '- bluesky: Audience is tech-forward early adopters and the open web crowd. Punchy, opinionated, slightly nerdy. Under 240 characters total including URL and 2-3 hashtags.',\n '',\n 'Return ONLY a valid JSON object with exactly three keys: facebook, linkedin, bluesky.',\n 'No markdown code fences. No explanation. Just the raw JSON object.'\n ].join('\\n')\n }]\n })\n }\n}];"
},
"id": "01306e17-767a-4cf9-a0aa-da66f9e082d8",
"name": "Build Claude Request",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-2192,
96
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.anthropic.com/v1/messages",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "anthropic-version",
"value": "2023-06-01"
}
]
},
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "={{ $json.anthropicBody }}",
"options": {}
},
"id": "bc45bf06-1ab2-47c0-9e0b-f477f9163855",
"name": "Draft with Claude",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-1952,
96
]
},
{
"parameters": {
"jsCode": "const apiResp = $input.first().json;\nconst postData = $('Prepare Post Data').first().json;\n\nlet drafts;\ntry {\n const text = apiResp.content[0].text;\n const cleaned = text.replace(/^```(?:json)?\\s*/i, '').replace(/\\s*```$/i, '').trim();\n drafts = JSON.parse(cleaned);\n} catch (e) {\n throw new Error('Failed to parse Claude response as JSON. Raw: ' + apiResp.content[0].text);\n}\n\nreturn [{\n json: {\n postTitle: postData.postTitle,\n postUrl: postData.postUrl,\n facebook: drafts.facebook,\n linkedin: drafts.linkedin,\n bluesky: drafts.bluesky\n }\n}];"
},
"id": "51d98b50-665b-42fe-9fcc-38238f701252",
"name": "Parse Drafts",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-1712,
96
]
},
{
"parameters": {
"sendTo": "buzzsurfr@gmail.com",
"subject": "=[Facebook] Review post: {{ $json.postTitle }}",
"message": "=<div style=\"font-family:sans-serif;max-width:600px;margin:0 auto;color:#111\">\n <h2 style=\"color:#3b5998\">Facebook Post Review</h2>\n <p><strong>Post:</strong> <a href=\"{{ $json.postUrl }}\">{{ $json.postTitle }}</a></p>\n <p style=\"color:#555;font-size:13px\">Audience: hobbyists, makers, general tech enthusiasts</p>\n\n <h3>Draft</h3>\n <blockquote style=\"background:#f0f2f5;border-left:4px solid #3b5998;padding:12px 16px;margin:0 0 24px;white-space:pre-wrap;font-size:14px;border-radius:0 4px 4px 0\">{{ $json.facebook }}</blockquote>\n\n <hr style=\"border:none;border-top:1px solid #ddd;margin:24px 0\">\n <p>\n <a href=\"{{ $execution.resumeUrl }}\" style=\"display:inline-block;background:#3b5998;color:#fff;padding:14px 28px;text-decoration:none;border-radius:6px;font-size:15px;font-weight:bold\">Approve / Edit / Reject</a>\n </p>\n <p style=\"color:#999;font-size:12px\">LinkedIn and Bluesky are running in parallel \u2014 review those separately.</p>\n</div>",
"options": {}
},
"id": "be0e883d-2c32-45ba-81f3-bb1839b08506",
"name": "Send Facebook Email",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
-1424,
-80
]
},
{
"parameters": {
"resume": "form",
"formTitle": "Facebook Post Review",
"formDescription": "={{ 'Draft:\\n\\n' + $('Parse Drafts').first().json.facebook + '\\n\\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\\n\\nApprove, edit, or reject below. To edit: select \"Approve with edits\" and paste your revised text.' }}",
"formFields": {
"values": [
{
"fieldLabel": "Decision",
"fieldType": "dropdown",
"fieldOptions": {
"values": [
{
"option": "Approve"
},
{
"option": "Approve with edits"
},
{
"option": "Reject"
}
]
},
"requiredField": true
},
{
"fieldLabel": "Edited text",
"fieldType": "textarea",
"placeholder": "Leave blank to use the AI draft. Paste your revised text here if editing."
}
]
},
"options": {}
},
"id": "eddacb56-5f0f-4cd1-85c8-ee014670c258",
"name": "Facebook Form",
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [
-1184,
-80
]
},
{
"parameters": {
"jsCode": "const form = $input.first().json;\nconst drafts = $('Parse Drafts').first().json;\n\nconst editedText = (form['Edited text'] || '').trim();\nconst decision = form.Decision;\n\nreturn [{\n json: {\n decision,\n shouldPost: decision !== 'Reject',\n postText: editedText || drafts.facebook,\n postUrl: drafts.postUrl,\n postTitle: drafts.postTitle\n }\n}];"
},
"id": "c146fd2e-0297-4ee8-b4db-64ae5b7ba6b1",
"name": "Resolve Facebook Text",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-944,
-80
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "fb-condition",
"leftValue": "={{ $json.decision }}",
"rightValue": "Reject",
"operator": {
"type": "string",
"operation": "notEquals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "8943acab-023e-4007-9440-d5d20589ed3a",
"name": "IF: Post to Facebook",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
-704,
-80
]
},
{
"parameters": {
"method": "POST",
"url": "=https://graph.facebook.com/v19.0/{{ $vars.FACEBOOK_PAGE_ID }}/feed",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "message",
"value": "={{ $json.postText }}"
},
{
"name": "link",
"value": "={{ $json.postUrl }}"
}
]
},
"options": {}
},
"id": "6f09ba61-3937-4e94-a802-5e357dc924b4",
"name": "Facebook: Post",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-464,
-96
]
},
{
"parameters": {
"sendTo": "buzzsurfr@gmail.com",
"subject": "=[LinkedIn] Review post: {{ $('Parse Drafts').first().json.postTitle }}",
"message": "=<div style=\"font-family:sans-serif;max-width:600px;margin:0 auto;color:#111\">\n <h2 style=\"color:#0077b5\">LinkedIn Post Review</h2>\n <p><strong>Post:</strong> <a href=\"{{ $('Parse Drafts').first().json.postUrl }}\">{{ $('Parse Drafts').first().json.postTitle }}</a></p>\n <p style=\"color:#555;font-size:13px\">Audience: professionals, engineers \u2014 insight-led, professional tone</p>\n\n <h3>Draft</h3>\n <blockquote style=\"background:#f0f7fc;border-left:4px solid #0077b5;padding:12px 16px;margin:0 0 24px;white-space:pre-wrap;font-size:14px;border-radius:0 4px 4px 0\">{{ $('Parse Drafts').first().json.linkedin }}</blockquote>\n\n <hr style=\"border:none;border-top:1px solid #ddd;margin:24px 0\">\n <p>\n <a href=\"{{ $execution.resumeUrl }}\" style=\"display:inline-block;background:#0077b5;color:#fff;padding:14px 28px;text-decoration:none;border-radius:6px;font-size:15px;font-weight:bold\">Approve / Edit / Reject</a>\n </p>\n <p style=\"color:#999;font-size:12px\">Facebook and Bluesky are running in parallel \u2014 review those separately.</p>\n</div>",
"options": {}
},
"id": "820d7a5c-bdaa-43dc-be45-ca6e3447b99d",
"name": "Send LinkedIn Email",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
-1424,
96
]
},
{
"parameters": {
"resume": "form",
"formTitle": "LinkedIn Post Review",
"formDescription": "={{ 'Draft:\\n\\n' + $('Parse Drafts').first().json.linkedin + '\\n\\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\\n\\nApprove, edit, or reject below. To edit: select \"Approve with edits\" and paste your revised text.' }}",
"formFields": {
"values": [
{
"fieldLabel": "Decision",
"fieldType": "dropdown",
"fieldOptions": {
"values": [
{
"option": "Approve"
},
{
"option": "Approve with edits"
},
{
"option": "Reject"
}
]
},
"requiredField": true
},
{
"fieldLabel": "Edited text",
"fieldType": "textarea",
"placeholder": "Leave blank to use the AI draft. Paste your revised text here if editing."
}
]
},
"options": {}
},
"id": "934f479d-7bc9-40b5-9ddf-17b05a2a6edb",
"name": "LinkedIn Form",
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [
-1184,
96
]
},
{
"parameters": {
"jsCode": "const form = $input.first().json;\nconst drafts = $('Parse Drafts').first().json;\n\nconst editedText = (form['Edited text'] || '').trim();\nconst decision = form.Decision;\n\nreturn [{\n json: {\n decision,\n shouldPost: decision !== 'Reject',\n postText: editedText || drafts.linkedin,\n postUrl: drafts.postUrl,\n postTitle: drafts.postTitle\n }\n}];"
},
"id": "b173dbc4-02c9-493b-b675-cf97b730835a",
"name": "Resolve LinkedIn Text",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-944,
96
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "li-condition",
"leftValue": "={{ $json.decision }}",
"rightValue": "Reject",
"operator": {
"type": "string",
"operation": "notEquals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "036cf144-da88-4f8e-814a-6b99fcc9db9a",
"name": "IF: Post to LinkedIn",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
-704,
96
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.linkedin.com/v2/ugcPosts",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "X-Restli-Protocol-Version",
"value": "2.0.0"
}
]
},
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "={{ JSON.stringify({ author: 'urn:li:person:' + $vars.LINKEDIN_PERSON_ID, lifecycleState: 'PUBLISHED', specificContent: { 'com.linkedin.ugc.ShareContent': { shareCommentary: { text: $json.postText }, shareMediaCategory: 'ARTICLE', media: [{ status: 'READY', originalUrl: $json.postUrl, title: { text: $json.postTitle } }] } }, visibility: { 'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC' } }) }}",
"options": {}
},
"id": "e8dad6d4-f053-4a3f-8c79-946f2ab05338",
"name": "LinkedIn: Post",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-464,
80
]
},
{
"parameters": {
"sendTo": "buzzsurfr@gmail.com",
"subject": "=[Bluesky] Review post: {{ $('Parse Drafts').first().json.postTitle }}",
"message": "=<div style=\"font-family:sans-serif;max-width:600px;margin:0 auto;color:#111\">\n <h2 style=\"color:#0085ff\">Bluesky Post Review</h2>\n <p><strong>Post:</strong> <a href=\"{{ $('Parse Drafts').first().json.postUrl }}\">{{ $('Parse Drafts').first().json.postTitle }}</a></p>\n <p style=\"color:#555;font-size:13px\">Audience: tech-forward, open web crowd \u2014 punchy, opinionated, ≤240 chars</p>\n\n <h3>Draft</h3>\n <blockquote style=\"background:#f0f6ff;border-left:4px solid #0085ff;padding:12px 16px;margin:0 0 8px;white-space:pre-wrap;font-size:14px;border-radius:0 4px 4px 0\">{{ $('Parse Drafts').first().json.bluesky }}</blockquote>\n <p style=\"color:#888;font-size:12px;margin:0 0 24px\">{{ $('Parse Drafts').first().json.bluesky.length }} / 240 chars</p>\n\n <hr style=\"border:none;border-top:1px solid #ddd;margin:24px 0\">\n <p>\n <a href=\"{{ $execution.resumeUrl }}\" style=\"display:inline-block;background:#0085ff;color:#fff;padding:14px 28px;text-decoration:none;border-radius:6px;font-size:15px;font-weight:bold\">Approve / Edit / Reject</a>\n </p>\n</div>",
"options": {}
},
"id": "18895a14-9183-41c3-b307-9e75b0c90e77",
"name": "Send Bluesky Email",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
-1424,
272
]
},
{
"parameters": {
"resume": "form",
"formTitle": "Bluesky Post Review",
"formDescription": "={{ 'Draft (' + $('Parse Drafts').first().json.bluesky.length + '/240 chars):\\n\\n' + $('Parse Drafts').first().json.bluesky + '\\n\\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\\n\\nApprove, edit, or reject below. Keep edits under 240 characters.' }}",
"formFields": {
"values": [
{
"fieldLabel": "Decision",
"fieldType": "dropdown",
"fieldOptions": {
"values": [
{
"option": "Approve"
},
{
"option": "Approve with edits"
},
{
"option": "Reject"
}
]
},
"requiredField": true
},
{
"fieldLabel": "Edited text",
"fieldType": "textarea",
"placeholder": "Leave blank to use the AI draft. Keep under 240 characters."
}
]
},
"options": {}
},
"id": "38ed7a4b-fcc7-4470-99e7-8a0191ab47d5",
"name": "Bluesky Form",
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [
-1184,
272
]
},
{
"parameters": {
"jsCode": "const form = $input.first().json;\nconst drafts = $('Parse Drafts').first().json;\n\nconst editedText = (form['Edited text'] || '').trim();\nconst decision = form.Decision;\n\nreturn [{\n json: {\n decision,\n shouldPost: decision !== 'Reject',\n postText: editedText || drafts.bluesky,\n postUrl: drafts.postUrl,\n postTitle: drafts.postTitle\n }\n}];"
},
"id": "9799679d-47cc-4b13-baea-fd3f2c7a64f8",
"name": "Resolve Bluesky Text",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-944,
272
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "bs-condition",
"leftValue": "={{ $json.decision }}",
"rightValue": "Reject",
"operator": {
"type": "string",
"operation": "notEquals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "9b377da5-9aa6-44d8-b551-87b1a52d4e2d",
"name": "IF: Post to Bluesky",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
-704,
272
]
},
{
"parameters": {
"method": "POST",
"url": "https://bsky.social/xrpc/com.atproto.server.createSession",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "identifier",
"value": "={{ $vars.BLUESKY_HANDLE }}"
},
{
"name": "password",
"value": "={{ $env.BLUESKY_APP_PASSWORD }}"
}
]
},
"options": {}
},
"id": "7b2bce5d-eaeb-419d-9c7d-0970937520af",
"name": "Bluesky: Auth",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-464,
256
]
},
{
"parameters": {
"jsCode": "const session = $input.first().json;\nconst resolved = $('Resolve Bluesky Text').first().json;\n\nreturn [{\n json: {\n accessJwt: session.accessJwt,\n did: session.did,\n blueskyBody: JSON.stringify({\n repo: session.did,\n collection: 'app.bsky.feed.post',\n record: {\n '$type': 'app.bsky.feed.post',\n text: resolved.postText,\n createdAt: new Date().toISOString()\n }\n })\n }\n}];"
},
"id": "71049d2f-8c1d-455a-be1e-e1ccace64b92",
"name": "Build Bluesky Post",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-224,
256
]
},
{
"parameters": {
"method": "POST",
"url": "https://bsky.social/xrpc/com.atproto.repo.createRecord",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{ $json.accessJwt }}"
}
]
},
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "={{ $json.blueskyBody }}",
"options": {}
},
"id": "551f52f9-8f2d-4f34-b150-39e73fceae60",
"name": "Bluesky: Post",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
16,
256
]
}
],
"connections": {
"Prepare Post Data": {
"main": [
[
{
"node": "Build Claude Request",
"type": "main",
"index": 0
}
]
]
},
"Build Claude Request": {
"main": [
[
{
"node": "Draft with Claude",
"type": "main",
"index": 0
}
]
]
},
"Draft with Claude": {
"main": [
[
{
"node": "Parse Drafts",
"type": "main",
"index": 0
}
]
]
},
"Parse Drafts": {
"main": [
[
{
"node": "Send Facebook Email",
"type": "main",
"index": 0
},
{
"node": "Send LinkedIn Email",
"type": "main",
"index": 0
},
{
"node": "Send Bluesky Email",
"type": "main",
"index": 0
}
]
]
},
"Send Facebook Email": {
"main": [
[
{
"node": "Facebook Form",
"type": "main",
"index": 0
}
]
]
},
"Facebook Form": {
"main": [
[
{
"node": "Resolve Facebook Text",
"type": "main",
"index": 0
}
]
]
},
"Resolve Facebook Text": {
"main": [
[
{
"node": "IF: Post to Facebook",
"type": "main",
"index": 0
}
]
]
},
"IF: Post to Facebook": {
"main": [
[
{
"node": "Facebook: Post",
"type": "main",
"index": 0
}
]
]
},
"Send LinkedIn Email": {
"main": [
[
{
"node": "LinkedIn Form",
"type": "main",
"index": 0
}
]
]
},
"LinkedIn Form": {
"main": [
[
{
"node": "Resolve LinkedIn Text",
"type": "main",
"index": 0
}
]
]
},
"Resolve LinkedIn Text": {
"main": [
[
{
"node": "IF: Post to LinkedIn",
"type": "main",
"index": 0
}
]
]
},
"IF: Post to LinkedIn": {
"main": [
[
{
"node": "LinkedIn: Post",
"type": "main",
"index": 0
}
]
]
},
"Send Bluesky Email": {
"main": [
[
{
"node": "Bluesky Form",
"type": "main",
"index": 0
}
]
]
},
"Bluesky Form": {
"main": [
[
{
"node": "Resolve Bluesky Text",
"type": "main",
"index": 0
}
]
]
},
"Resolve Bluesky Text": {
"main": [
[
{
"node": "IF: Post to Bluesky",
"type": "main",
"index": 0
}
]
]
},
"IF: Post to Bluesky": {
"main": [
[
{
"node": "Bluesky: Auth",
"type": "main",
"index": 0
}
]
]
},
"Bluesky: Auth": {
"main": [
[
{
"node": "Build Bluesky Post",
"type": "main",
"index": 0
}
]
]
},
"Build Bluesky Post": {
"main": [
[
{
"node": "Bluesky: Post",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "",
"meta": {
"templateCredsSetupCompleted": true
},
"tags": []
}
About this workflow
Blog Post → Social Media. Uses rssFeedTrigger, httpRequest, gmail. Event-driven trigger; 22 nodes.
Source: https://github.com/buzzsurfr/site/blob/172598e20b109182c83da0c08b064079790bd7f5/.n8n/workflows/blog-social-media.json — original creator credit. Request a take-down →