Skip to main content
AC
Content & Publishing4.0 KBMIT licensed

substack-publisher

Original, written for TechTide client work

Prepare Substack-ready long-form drafts and publish them through the web editor, since Substack has no official public write API. Use for essays over 1000 words, builder stories that benefit from Substack's network, or paid-subscription content. Not for unattended API publishing: use beehiiv or ghost-publisher. Not for mirroring posts to email lists: use listmonk-publisher on the RSS feed.

  • substack
  • publisher

SKILL.md

Substack Publisher

Substack has no official public write API and no verified post-by-email address. So the workflow is: produce a clean, paste-ready draft file, then publish through the logged-in web editor with a human in the loop. Never pretend an unattended path exists.

Configuration

VariableMeaning
SUBSTACK_PUB_URLPublication URL, e.g. https://<PUBLICATION>.substack.com
SUBSTACK_RSSFeed URL, $SUBSTACK_PUB_URL/feed

Do not ask the owner for a publishing email address. That path is dead unless Substack reintroduces a verified post-by-email feature.

Workflow

  1. Draft in Markdown. Save to drafts/substack/YYYY-MM-DD-<slug>.md. Front-load a working title and a one-line subtitle at the top of the file; the editor asks for both.
  2. Format for the editor paste. Substack's editor handles pasted rich text better than raw Markdown. Keep structure simple: H2/H3 headings, short paragraphs, pull quotes as blockquotes, images referenced by URL with a caption line under each. No tables (Substack renders them poorly), no footnote syntax (add footnotes in the editor).
  3. Publish via browser. Open $SUBSTACK_PUB_URL/publish/post, paste, restore any formatting the paste dropped, set the audience (free vs paid), preview both email and web views, then let the human hit publish or schedule.
  4. Confirm and cross-publish. After publish, the post appears in $SUBSTACK_RSS. Downstream mirrors (email list sync, social snippets) consume the feed; run them after confirmation, not before.

Hard rule: no unattended publishing

Drafting is autonomous. Publishing is not. Any --publish style automation must refuse and route to the browser flow. If long-form needs true unattended publishing, move that content to beehiiv or ghost-publisher, which have real APIs.

Good vs bad

Bad: Agent writes the essay, finds no API, and "publishes" by emailing the draft to a guessed <publication>@substack.com address. The post never appears, the agent reports success anyway.

Good: Agent writes the essay to drafts/substack/2026-08-12-shipping-solo.md, formats it paste-ready, opens the editor URL, and tells the owner: "Draft ready and loaded. Review the email preview, then publish or tell me what to change."

Verification

After the human publishes, fetch the feed: curl -s $SUBSTACK_RSS | grep -o '<title>[^<]*</title>' | head -5. Expect the new post's title in the output within a few minutes. If it is absent, the post is still a draft or was scheduled: check the editor's post list before telling anyone it shipped.

Completion checklist

  • [ ] Draft saved to drafts/substack/ with title and subtitle lines
  • [ ] Formatting is paste-safe: no tables, no footnote syntax, simple headings
  • [ ] Audience (free/paid) set intentionally, not left on default
  • [ ] Human reviewed the email preview before publish
  • [ ] Post confirmed live via the RSS feed
  • [ ] Cross-publish steps run only after confirmation

Any box unchecked: not done. Fix or say so.

Footguns

  • Email preview differs from web preview. Long code blocks and wide images get clipped in email clients. Always check the email preview; that is what most subscribers see first.
  • Paste drops formatting silently. Blockquotes and nested lists are the usual casualties. Diff the pasted result against the draft by eye before publish, not after.
  • Reporting "published" from a draft save. Substack autosaves drafts; a saved draft looks like success in the editor. Only the RSS check proves it is live.

More in Content & Publishing

All skills