Automation Guide · March 2026

Automate your entire
content workflow with AI
in one afternoon

⏱ 45 min build
🎯 Intermediate
🔧 n8n + Claude Sonnet 4.6

From brief to draft to publish — a full n8n + Claude automation that handles ideation, drafting, SEO optimisation, and scheduling with one trigger. No more copy-pasting between tabs. One workflow, every content type, always consistent.

n8n Workflow Claude API Content Automation SEO Generation CMS Publishing Webhook Trigger
1
Trigger
Webhook receives your content brief
3
Claude Nodes
Ideation, drafting, and SEO in sequence
1
SEO Pass
Meta, keywords & schema auto-written
CMS Targets
WordPress, Ghost, Notion, Webflow & more
On This Page

What's in this guide

Section 01

The Full Pipeline — How It Works

The workflow chains five nodes in sequence. Each node does one thing well and passes its output to the next. The trigger accepts a JSON brief via webhook. Claude handles all the creative and analytical work across three dedicated nodes. A final HTTP node pushes the finished, SEO-optimised post to your CMS.

Input
Claude Processing
Publish
🌐
Webhook Trigger
Receives brief JSON
🧠 Claude
Ideation Node
Angles + outline
✍️ Claude
Drafting Node
Full article draft
🔍 Claude
SEO Node
Meta + schema
🚀
Publish Node
CMS + schedule

Each Claude node uses a separate, focused system prompt — ideation, drafting, and SEO are deliberately kept apart so each prompt can be tuned independently. The outputs chain: the ideation node's structured outline becomes the drafting node's input; the draft becomes the SEO node's input. This sequential chaining is what produces consistent, high-quality output rather than asking one prompt to do everything at once.

One Trigger
Send a webhook payload with topic, audience, tone, and target length. Everything else is automated — no manual steps between brief and published post.
🧠
Separate Claude Nodes
Ideation, drafting, and SEO use different system prompts. Tune each independently. Change the drafting style without touching SEO logic.
🔍
SEO Built-In
The SEO node generates title tag, meta description, focus keyword, secondary keywords, and JSON-LD schema markup automatically from the draft.
📅
Schedule or Publish Now
The publish node accepts a publish_at timestamp. Send it to publish immediately or at a future date — your CMS handles the scheduling.
🔌
CMS-Agnostic
The final HTTP node works with any CMS that has a REST API: WordPress, Ghost, Webflow, Notion, Contentful, Sanity, or a custom endpoint.
♻️
Reusable & Forkable
The workflow JSON is importable in one click. Fork it for different content types: blog posts, LinkedIn articles, email newsletters, product descriptions.
Section 02

Prerequisites & Stack Setup

Before building, get these in order. The whole pipeline takes under 45 minutes once these are ready — don't skip the setup.

ToolWhat you needCost
n8n Self-hosted (Docker) or n8n Cloud. Version 1.40+ recommended for the HTTP node improvements. Free (self-hosted) / $20+/mo cloud
Anthropic API Key Starts with sk-ant-. Get from console.anthropic.com. Set a usage cap before starting. Pay-per-token
CMS with REST API WordPress (WP REST API v2), Ghost (Admin API), or any CMS accepting JSON via HTTP POST. Depends on CMS
n8n Claude credential In n8n, go to Credentials → New → HTTP Header Auth. Set header x-api-key to your Anthropic key.
ℹ️
n8n Cloud vs self-hosted: Either works. If you're new to n8n, start with the free Cloud trial — you get 5 active workflows and 2,500 executions/month, more than enough to build and test this pipeline. For production use, self-host on a $5–6/mo VPS using the official Docker image.
01
Create a new workflow
In n8n, click New Workflow. Name it "Content Pipeline." Keep it inactive while building — you'll activate after testing.
02
Add Claude credential
Credentials → New → HTTP Header Auth. Name: "Claude API". Header name: x-api-key. Value: your Anthropic key. Save.
03
Add CMS credential
Add a second credential for your CMS. WordPress uses Basic Auth (username + app password). Ghost uses an Admin API key in the Authorization header.
Step 01

Webhook Trigger Node

The pipeline starts with an n8n Webhook node. It listens for an HTTP POST containing your content brief as JSON. This is what you send each time you want to kick off a new content run — manually, from a Slack command, a Notion button, a cron job, or any other trigger.

🌐
Node 1 — Webhook Trigger
Webhook
Node Type
Webhook
HTTP Method
POST
Path
/content-pipeline
Response Mode
Respond with Last Node

The webhook expects a JSON payload in this shape. All fields except publish_at are required.

JSON · Webhook payload schema
{
  "topic":        "How to reduce churn in B2B SaaS",
  "audience":     "SaaS founders and heads of customer success",
  "tone":         "Direct, data-led, no fluff. Use second person.",
  "content_type": "blog_post",
  "word_count":    1400,
  "keywords":     ["churn reduction", "customer retention SaaS", "churn prevention"],
  "publish_at":   "2026-03-20T09:00:00Z"  // optional — omit to publish immediately
}
💡
Testing the trigger: After saving the Webhook node, click Listen for Test Event in n8n, then send the payload above using curl or Postman. You'll see the data appear in the node's output panel. Only proceed to Node 2 once you've confirmed the payload comes through cleanly.
Step 02

Claude Ideation Node

The ideation node receives the brief and produces a structured content plan: three potential angles, a recommended angle with rationale, and a detailed section-by-section outline. This becomes the drafting node's structural input — critically, the draft never starts from a blank page.

🧠
Node 2 — Ideation (HTTP Request to Claude API)
Claude API
Node Type
HTTP Request
Method
POST
URL
https://api.anthropic.com/v1/messages
Headers
x-api-key: {{ $credentials.claudeApi.value }} anthropic-version: 2023-06-01 content-type: application/json
JSON · Ideation node body
{
  "model": "claude-sonnet-4-6",
  "max_tokens": 1024,
  "system": "You are an expert content strategist. Your job is to produce a structured content plan given a brief. Respond ONLY with valid JSON matching the schema in the user message. No preamble, no markdown fences.",
  "messages": [
    {
      "role": "user",
      "content": "Brief:\n- Topic: {{ $json.body.topic }}\n- Audience: {{ $json.body.audience }}\n- Tone: {{ $json.body.tone }}\n- Content type: {{ $json.body.content_type }}\n- Target length: {{ $json.body.word_count }} words\n- Seed keywords: {{ $json.body.keywords }}\n\nReturn JSON:\n{\n  \"angles\": [{\"angle\": \"...\", \"hook\": \"...\"}],\n  \"recommended_angle\": \"...\",\n  \"rationale\": \"...\",\n  \"outline\": [\n    {\"section\": \"...\", \"purpose\": \"...\", \"key_points\": [\"...\"]}\n  ]\n}"
    }
  ]
}
⚠️
Extracting the response: Claude's API returns the text inside {{ $json.content[0].text }}. Add a Set node immediately after the HTTP Request to parse this: set a field ideation_plan = {{ JSON.parse($json.content[0].text) }}. This makes the structured plan accessible by name in all downstream nodes.
n8n Set Node · Parse ideation response
// Set node configuration — add these fields:

ideation_plan  =  {{ JSON.parse($node["Ideation"].json.content[0].text) }}
topic          =  {{ $node["Webhook"].json.body.topic }}
audience       =  {{ $node["Webhook"].json.body.audience }}
tone           =  {{ $node["Webhook"].json.body.tone }}
word_count     =  {{ $node["Webhook"].json.body.word_count }}
content_type   =  {{ $node["Webhook"].json.body.content_type }}
publish_at     =  {{ $node["Webhook"].json.body.publish_at }}
Step 03

Claude Drafting Node

The drafting node takes the ideation plan — specifically the recommended angle and the full section outline — and writes the complete article. By injecting the structured outline into the system prompt, you ensure the draft always follows the planned structure. Claude writes section by section, hits the target word count, and maintains the specified tone throughout.

✍️
Node 4 — Drafting (HTTP Request to Claude API)
Claude API
URL & Headers
Same as Ideation node — reuse Claude API credential
JSON · Drafting node body
{
  "model": "claude-sonnet-4-6",
  "max_tokens": 4096,
  "system": "You are an expert content writer. Write exactly to the provided outline and word count. Use the specified tone throughout. Return ONLY the article in markdown — no preamble, no meta-commentary, no word count note at the end.",
  "messages": [
    {
      "role": "user",
      "content": "Write a {{ $json.content_type }} on this topic: {{ $json.topic }}\n\nAudience: {{ $json.audience }}\nTone: {{ $json.tone }}\nTarget length: {{ $json.word_count }} words\n\nUse this angle: {{ $json.ideation_plan.recommended_angle }}\n\nFollow this outline exactly:\n{{ JSON.stringify($json.ideation_plan.outline, null, 2) }}\n\nWrite the full article now."
    }
  ]
}
💡
Word count accuracy: Claude Sonnet 4.6 hits target word counts reliably when the count appears in both the system prompt context AND the user message. For articles over 2,000 words, increase max_tokens to 6,000. The 4,096 default is suitable for posts up to ~1,600 words.

After the drafting HTTP Request, add another Set node to extract and store the draft:

n8n Set Node · Store draft
// Merge with previous fields, add:
draft_markdown  =  {{ $node["Drafting"].json.content[0].text }}

// Pass through all previous fields unchanged:
topic          =  {{ $json.topic }}
audience       =  {{ $json.audience }}
tone           =  {{ $json.tone }}
content_type   =  {{ $json.content_type }}
publish_at     =  {{ $json.publish_at }}
ideation_plan  =  {{ $json.ideation_plan }}
Step 04

SEO & Meta Generation Node

The SEO node reads the finished draft and generates all the metadata needed for publication: an SEO-optimised title tag, meta description, focus keyword, secondary keyword list, and JSON-LD Article schema markup. Claude reads the actual content — not just the topic — so the SEO output reflects what's really in the draft.

🔍
Node 6 — SEO Generation (HTTP Request to Claude API)
Claude API
max_tokens
1024 (SEO output is compact JSON)
JSON · SEO node body
{
  "model": "claude-sonnet-4-6",
  "max_tokens": 1024,
  "system": "You are an expert SEO specialist. Generate SEO metadata for the article provided. Return ONLY valid JSON. No markdown fences. No preamble.",
  "messages": [
    {
      "role": "user",
      "content": "Article:\n{{ $json.draft_markdown }}\n\nSeed keywords to incorporate: {{ $json.ideation_plan.outline[0].key_points }}\n\nReturn JSON:\n{\n  \"title_tag\": \"60 chars max, includes focus keyword\",\n  \"meta_description\": \"155 chars max, compelling CTA\",\n  \"focus_keyword\": \"primary keyword phrase\",\n  \"secondary_keywords\": [\"kw1\", \"kw2\", \"kw3\", \"kw4\", \"kw5\"],\n  \"slug\": \"url-friendly-slug\",\n  \"json_ld_schema\": { \"@context\": \"https://schema.org\", \"@type\": \"Article\", \"headline\": \"...\", \"description\": \"...\" },\n  \"og_title\": \"Social share title\",\n  \"og_description\": \"Social share description under 200 chars\"\n}"
    }
  ]
}
ℹ️
Why a separate SEO node? Asking the drafting prompt to also handle SEO metadata degrades both outputs — the draft loses focus and the SEO metadata gets generic. A dedicated SEO node with its own system prompt produces title tags and meta descriptions that are meaningfully better than what a combined prompt generates.

Add a final Set node after the SEO node to consolidate everything into the publish_payload object used by the publish node:

n8n Set Node · Build publish payload
seo_data         =  {{ JSON.parse($node["SEO"].json.content[0].text) }}
draft_markdown   =  {{ $json.draft_markdown }}
publish_at       =  {{ $json.publish_at }}
content_type     =  {{ $json.content_type }}

// Convenience shortcuts used by the publish node:
post_title       =  {{ JSON.parse($node["SEO"].json.content[0].text).title_tag }}
post_slug        =  {{ JSON.parse($node["SEO"].json.content[0].text).slug }}
post_excerpt     =  {{ JSON.parse($node["SEO"].json.content[0].text).meta_description }}
Step 05

CMS Publish & Scheduling

The final node posts the completed, SEO-enriched article to your CMS. The examples below cover WordPress REST API v2 and Ghost Admin API — the two most common targets. The pattern is identical for any CMS with an HTTP endpoint: construct the post body, set the auth header, fire the POST.

🟡
Node 8 — WordPress Publish
HTTP Request
URL
https://yourdomain.com/wp-json/wp/v2/posts
Method
POST
Authentication
Basic Auth — WP username + Application Password (not your login password)
JSON · WordPress post body
{
  "title":        "{{ $json.post_title }}",
  "content":      "{{ $json.draft_markdown }}",
  "excerpt":      "{{ $json.post_excerpt }}",
  "slug":         "{{ $json.post_slug }}",
  "status":       "{{ $json.publish_at ? 'future' : 'publish' }}",
  "date":         "{{ $json.publish_at || new Date().toISOString() }}",
  "meta": {
    "_yoast_wpseo_title":    "{{ $json.seo_data.title_tag }}",
    "_yoast_wpseo_metadesc": "{{ $json.seo_data.meta_description }}",
    "_yoast_wpseo_focuskw":  "{{ $json.seo_data.focus_keyword }}"
  },
  "yoast_head_json": {{ JSON.stringify($json.seo_data.json_ld_schema) }}
}
👻
Node 8 (alt) — Ghost Publish
HTTP Request
URL
https://yourdomain.com/ghost/api/admin/posts/
Auth Header
Authorization: Ghost [your-admin-api-key]
JSON · Ghost post body
{
  "posts": [{
    "title":             "{{ $json.post_title }}",
    "markdown":          "{{ $json.draft_markdown }}",
    "slug":              "{{ $json.post_slug }}",
    "custom_excerpt":    "{{ $json.post_excerpt }}",
    "status":            "{{ $json.publish_at ? 'scheduled' : 'published' }}",
    "published_at":      "{{ $json.publish_at || new Date().toISOString() }}",
    "og_title":          "{{ $json.seo_data.og_title }}",
    "og_description":    "{{ $json.seo_data.og_description }}",
    "meta_title":        "{{ $json.seo_data.title_tag }}",
    "meta_description":  "{{ $json.seo_data.meta_description }}",
    "codeinjection_head": "<script type='application/ld+json'>{{ JSON.stringify($json.seo_data.json_ld_schema) }}</script>"
  }]
}
💡
Non-WordPress/Ghost CMS: For Notion, Contentful, or Sanity, replace Node 8 with the corresponding n8n built-in node (Notion has a native n8n integration). Pass post_title, draft_markdown, and seo_data as the content fields. The upstream nodes stay identical.
Section 08

Full Workflow JSON & Customisations

The importable n8n workflow JSON below wires all eight nodes together with the correct data mappings. Import it via Workflows → Import from File in your n8n instance, then update three things before activating: your Claude credential, your CMS credential, and your CMS endpoint URL.

JSON · n8n workflow import skeleton
{
  "name": "Content Pipeline — n8n + Claude",
  "nodes": [
    { "id": "1", "name": "Webhook",        "type": "n8n-nodes-base.webhook",    "position": [240, 300] },
    { "id": "2", "name": "Ideation",       "type": "n8n-nodes-base.httpRequest", "position": [460, 300] },
    { "id": "3", "name": "Set Ideation",   "type": "n8n-nodes-base.set",         "position": [680, 300] },
    { "id": "4", "name": "Drafting",       "type": "n8n-nodes-base.httpRequest", "position": [900, 300] },
    { "id": "5", "name": "Set Draft",      "type": "n8n-nodes-base.set",         "position": [1120, 300] },
    { "id": "6", "name": "SEO",            "type": "n8n-nodes-base.httpRequest", "position": [1340, 300] },
    { "id": "7", "name": "Set SEO",        "type": "n8n-nodes-base.set",         "position": [1560, 300] },
    { "id": "8", "name": "Publish to CMS", "type": "n8n-nodes-base.httpRequest", "position": [1780, 300] }
  ],
  "connections": {
    "Webhook":       { "main": [[{ "node": "Ideation",       "type": "main", "index": 0 }]] },
    "Ideation":      { "main": [[{ "node": "Set Ideation",   "type": "main", "index": 0 }]] },
    "Set Ideation":  { "main": [[{ "node": "Drafting",       "type": "main", "index": 0 }]] },
    "Drafting":      { "main": [[{ "node": "Set Draft",      "type": "main", "index": 0 }]] },
    "Set Draft":     { "main": [[{ "node": "SEO",            "type": "main", "index": 0 }]] },
    "SEO":           { "main": [[{ "node": "Set SEO",        "type": "main", "index": 0 }]] },
    "Set SEO":       { "main": [[{ "node": "Publish to CMS", "type": "main", "index": 0 }]] }
  },
  "active": false
}

Forks & extensions worth building next

Once the core pipeline runs reliably, these are the highest-value extensions:

A
Human-in-the-loop gate
After the SEO node, add a Wait node + a Slack message with approve/reject buttons. The pipeline pauses until you sign off. Approved posts proceed to publish; rejected ones go into a Notion review queue.
B
Social media derivatives
Branch after the draft node: send the article to a 4th Claude node that writes 3 LinkedIn post variants and a Twitter/X thread. Route to Buffer or Typefully via their APIs.
C
Batch mode from Airtable
Replace the webhook trigger with an Airtable node that reads rows from a content calendar. Add a Schedule trigger to run every Monday morning — your whole week's content publishes automatically.
🔮
Quality control tip: Run the pipeline 3–5 times on different topics before enabling batch mode. Tune the ideation and drafting system prompts based on what you see. The prompts in this guide are solid starting points, but your specific topic niche, tone, and CMS conventions will benefit from one iteration cycle.

Workflows like
this, every Tuesday.

n8n builds, Claude teardowns, and the AI workflow patterns your competitors haven't found yet. 8 minutes. Free forever.

Subscribe to OutClaw AI →