I built an n8n community node that turns articles into X thread drafts (article → thread variants → review queue)

Overview

Turning a good article into an X thread was eating my time in one specific place. Not the summarizing, the hook. Figuring out which angle makes a stranger stop scrolling is a judgment call, and I kept second-guessing it. So I built SocialSwarm, a community node that generates the drafts and leaves the judgment to you:

RSS trigger (new post) → SocialSwarm (thread drafts, each with a different hook) → Split Out (one item per draft) → the review step you add (Slack / Google Sheets / Notion)

One deliberate difference from most posting pipelines in this category: it does not auto-post. The pipeline ends where you read, not at the X API. It runs on a hosted service with a free tier, details below.

What it does

  1. Triggers when your RSS feed publishes a new post, pulling the article URL from $json.link. For one-off articles you can also run it manually with any URL, or paste the article text straight in
  2. SocialSwarm generates complete X thread drafts, each built around a different hook. Hooks come in a fixed order (curiosity, challenge, story, stat, question) sliced to your variant count. The template ships with variantCount set to 3, so out of the box you get a curiosity-led draft (the open loop), a challenge-led one (pushing against the obvious take), and a story-led one (the anecdote buried in paragraph six). Raise it to 5 for the stat and question hooks too
  3. The node returns a single item carrying a variants array (it’s a declarative node, so it hands back the API response as-is)
  4. Split Out, splitting on variants, fans that into one item per draft
  5. The template ends at Split Out. You wire the final step yourself: a Slack channel, a Google Sheet, a Notion database, whichever you actually read
  6. You read the drafts side by side, pick the winner, or take the opening from one and the structure from another and post that

Nodes used

  • RSS Feed Trigger (“On new blog post”): fires when the feed publishes; the article URL comes from $json.link
  • SocialSwarm (community node): article in, thread variants out. Generation runs on the hosted service, so no LLM key is needed on your side
  • Split Out (core node): fieldToSplitOut set to variants, turns the single response item into one item per draft

That’s the whole template; it ends at Split Out. The review destination is the part you add: a Slack node, a Google Sheets append, a Notion database, whichever one you’ll actually check.

Requirements / credentials

  • SocialSwarm connector credential: free for 15 requests a month, paid after that. Rates are public and you don’t need to sign up to see them (link below)
  • Credentials for your review destination, if you use the Slack, Sheets, or Notion node
  • No OpenAI or other LLM key required

Setup notes for anyone trying this

  • URL fetching fails on plenty of real sites. Paywalls and bot-blocking are everywhere: a hard-paywalled news article or a member-gated Substack hands back a login wall or nothing at all. When that happens, paste the article text into the node instead. You get the same drafts
  • Resist wiring the output straight to the X API. The whole value is a human choosing between drafts and splicing the good parts together, and that only works if a human actually sees them
  • If you need full control of the prompt or a locked-down brand voice, you’ll fight this node. An HTTP Request node against your own LLM key is cheaper and fully controllable, and for some of you that’s the right trade
  • X only for now. If you post somewhere else, this is the wrong tool

Links

SocialSwarm is my product, so read the above with that in mind. If you try it and a fetch fails on a specific site, drop the URL in the replies. That list genuinely shapes what gets fixed next. And if you have suggestions, better variant logic, other review destinations worth supporting, anything else, I’d love to hear them.

the decision not to auto-post is the right one and it’s worth saying louder :blush:. most nodes in this space end at the api call, so the failure mode is a weak hook going out before anyone has read it.

one thing i’d add to the draft object:

-the source url

-the hook variant id

-the reason the model gave for that angle

once your reviewing twenty drafts a week you stop remembering why variant 3 existed, and that reason field is what makes review fast instead of a re-read.

the natural extension is letting people bolt a publish step on after their own review node, so the shape stays rss, socialswarm, split out, review, then whichever publisher they already use. blotato sits in that last slot for me, keeping it optional is what keeps the node honest.

does socialswarm return the hook type as its own field, or only the text?

yes, hook is its own field. and your other two points were good enough that i just shipped both instead of replying first.

each variant now comes back as:

{
“hook”: “curiosity”,
“reason”: “the essay’s core claim is that great work follows a hidden four-step shape rather than being random, so opening with a loop about that pattern mirrors the essay’s own reveal”,
“tweetCount”: 6,
“tweets”: [ …trimmed for length… ],
“sourceUrl”: " How to Do Great Work "
}

the reason and sourceUrl there are verbatim from a live run against the pg essay. tweets elided so this doesn’t eat the thread.

so, in order:

hook as variant id: already worked. hooks are pulled from a fixed sequence so they don’t repeat within a response, which makes hook the identifier.

sourceUrl: you were right that it wasn’t echoed back. it’s now on every variant rather than top-level, specifically so items still stand alone after Split Out. no reaching back to the trigger node.

reason: this was the one that stuck with me. the selection logic knows why it went with an angle and then drops that on the floor, which is exactly what you end up reconstructing by hand at twenty drafts a week. it’s now generated at selection time and rides on each variant. the bar i held it to is that the reason has to name something in the actual source. if it would survive being pasted under a different article, it’s filler. from the same test run, the challenge variant’s reason was “the piece directly attacks the assumption that schools help you pick a path, calling that assumption a lie the system won’t admit.” that’s the kind of thing that makes review a glance instead of a re-read.

if the model fails to produce a reason, the variant still delivers with reason: null rather than erroring the response. review speed shouldn’t cost reliability.

one more thing if you’re already running it: you get both fields without touching anything. the node forwards the api response as-is, so no npm update and no template change. the new keys just show up.

on publishing: yeah, the shape you describe is the intended one. review sits with you, and whatever you already push through goes after it. the node stops at drafts on purpose. wiring your own publisher behind your review step is the design, not a workaround, and keeping that slot open is what keeps it composable.