Vibe code your own Ghost
Vibe code your own Ghost as markdown posts, a public site, and an RSS feed. Paid memberships and newsletter deliverability are the other product.
You can vibe code your own Ghost. Start with markdown posts, a public site, and an RSS feed. The catalog calls Ghost Pro that loop, not a membership business.
You pay $9–$35 a month. The verdict is “Own the printing press”.
Last time I wrote about what stack for a SaaS clone. That was a regular backlog post. This one is a teardown.
Vibe code your own Ghost as markdown
The Ghost Pro page splits the work into three rows.
The first row is 12 hours. Markdown posts, public site, RSS feed. That is a post table, a list page, a permalink, and /rss.xml. You can vibe-code this.
The second row is 4 days. Newsletter sends, double opt-in, tags, scheduling. Still your list. A signup form, a confirm link, a send log.
The third row is 1 month and up. Paid memberships, theme engine, multi-author roles. Skip that row.
If you tell an agent to “clone Ghost”, it aims at the third row. The useful v1 is the first one.
Here is the shape of the data. Nothing else has to exist at 12 hours.
const post = {
id: 'post-pressroom-1',
slug: 'vibe-code-your-own-ghost',
title: 'Vibe code your own Ghost',
body: 'Start with markdown posts and an RSS feed.',
status: 'published',
publishedAt: '2026-10-25T07:00:00.000Z',
}
const tag = {
id: 'tag-publishing',
slug: 'publishing',
name: 'Publishing',
}
A post with three states (draft, scheduled, published), a slug, and tags. Subscribers can wait until Tuesday.
The audience line on the page is one writer publishing a blog and a newsletter under their own domain. If you wanted a folder of posts, the first row is enough.
The same v1 also replaces Substack, Medium, and WordPress.com if what you wanted was a site you host. Carrd is the one-page cousin at $2–$4 a month. Kit is the creator newsletter at $29–$79. Mailchimp is the list-and-broadcast at $20–$350.
Ghost itself is open source. If you want Ghost the product, install Ghost. The clone is for a press you can read on Monday.
How does Ghost work
Ghost publishes the architecture. I am summarizing those docs and two changelog posts, not reconstructing today’s cluster.
The architecture page splits the product into three parts that do not have to live in the same process: a JSON API, an admin client, and a front-end theme layer. The repo keeps core for Ghost and content for themes and images.
The API is two products with different keys. The Content API is read-only. You pass ?key= in the URL. Ghost says that key is safe in a browser because it only sees public data. The path is /ghost/api/content/. Posts, pages, tags, authors, tiers, settings.
The Admin API is read-write. Staff use a session. Integrations use a signed JWT. Posts, pages, tags, members, newsletters, tiers, offers, images, themes, webhooks. Publish from a desktop editor or a Git hook. The admin client is optional.
Storage is Bookshelf.js. SQLite3 in development. MySQL in production. Those are the supported pair. Other databases exist. The core team does not support them. Files start on disk. Storage adapters can move them out.
A published post on the Admin posts endpoint is a title, a status, a visibility, and a Lexical document. Ask for formats=html,lexical if you want HTML too. The Content API demo post looks like this:
const published = {
slug: 'welcome-short',
title: 'Welcome',
html: '<p>Welcome, it is great to have you here.</p>',
visibility: 'public',
published_at: '2019-11-26T02:44:17.000+00:00',
}
Koenig is the editor. The October 2023 changelog says they rebuilt it on React and Meta’s Lexical. The old store was Mobiledoc. Opening a Mobiledoc post converts it. Treat “every row is Lexical in 2026” as an educated guess. A v1 can store markdown and render HTML.
The default public site is Handlebars on Express. The theme docs require index.hbs, post.hbs, and package.json. gscan rejects a broken upload. Ghost can also run headless. Their JAMstack note is honest about the tax: tag archives, author pages, sitemap, Open Graph, Twitter Cards, pagination. Getting a list of posts is easy, and the long tail is the theme engine.
A v1 does not need Ember, Lexical, or MySQL. Markdown in D1, pages in Astro, images in R2. That is the stack on the card. Use Rails if that is your weekday language.
How Ghost newsletters work
Email is the second product.
Ghost’s newsletter docs say a site starts with one newsletter. You can add more. A post can go to free members, paid members, or a filter. Ghost(Pro) configures delivery for you. Self-hosted Ghost talks to Mailgun. SMTP is not an option for bulk mail.
Their Mailgun FAQ is blunt. A bulk send over SMTP gets the IP listed, so newsletters cannot use the same SMTP path as the login link. Mailgun is the only bulk API they support. They say they have no affiliate deal. Supporting a second provider is overhead they refused.
You publish and send in one Admin call. The sending guide adds ?newsletter=weekly-newsletter. email_segment filters members with NQL, often status:free, status:-free, or all. The response includes an email object: submitted, counts, HTML, plaintext. A failed send goes back to draft, then you publish again.
Members are a separate store. The memberships guide uses passwordless JWT links. Access on a post is public, members only, paid-members only, or a specific tier. Paid billing is Stripe Connect in the publisher’s Stripe account. Ghost takes 0% of that revenue. Stripe fees still apply.
const send = {
postId: 'post-pressroom-1',
newsletter: 'weekly',
segment: 'all',
status: 'queued',
}
const member = {
email: '[email protected]',
status: 'free',
confirmedAt: '2026-10-25T08:12:00.000Z',
unsubscribedAt: null,
}
A v1 send is one campaign to confirmed addresses. Honor unsubscribe in the same request. Make the job idempotent so a retry does not mail twice. The card’s guardrail already says that.
Kit is the same 4-day row with a different logo. Ten hours for subscribers and markdown broadcasts. Skip paid recommendations. Mailchimp is the list if you never wanted a public blog.
Paid memberships and the theme engine
The skip row is Ghost the platform.
Tiers, offers, complimentary members, and visibility: paid sit on Stripe webhooks. A leaked paid post is a refund, so gate it on the server. The members guide says content is protected at the server. Do not hide a <div> with CSS.
The theme marketplace is the other surface. Handlebars helpers, gscan, custom templates per post, code injection, accent colors. Ghost has shipped that layer since 2013. A v1 needs one layout.
ActivityPub is a third product they kept out of core. Their Fedify write-up compares it to email: one delivery is easy, and a hundred thousand deliveries with retries and dead inboxes are a service. Ghost hands the post to that service the way it hands a newsletter to Mailgun. Queue theory says Ghost(Pro) puts those jobs on Google Pub/Sub. Treat today’s exact worker count as an educated guess. You do not need a federation inbox to publish twelve essays.
Multi-author roles, offers, and a theme store are how a publication becomes a company. The catalog’s non-goal already names them.
A Ghost alternative for one writer
I would rebuild Ghost for the posts I already write in markdown, where the current “CMS” is a folder and a git push. One posts table, Astro routes, an RSS file generated from status = 'published'.
export function rssItems(posts) {
return posts
.filter((post) => post.status === 'published')
.sort((a, b) => b.publishedAt.localeCompare(a.publishedAt))
.map((post) => ({
title: post.title,
link: `https://flaviocopes.com/blog/${post.slug}/`,
pubDate: post.publishedAt,
}))
}
Astro already has @astrojs/rss. This site uses it. A confirm-and-send loop comes after the archive stays readable for a month. I would not build a tier picker or a theme upload.
Host it next to the product, on Astro, D1, and Workers, because that is the stack on the card. Put images in R2. Use Rails if that is your weekday language.
If the rent is one landing page, that is Carrd, 2 hours for sections and a form. If the rent is a list with no public archive, that is Mailchimp. If the rent is markdown that also arrives in inboxes, start on the Kit card after the feed works.
Start with the first row
Go to Build your own Ghost Pro. Copy the AHA prompt, or the stack you already write.
Tell the agent the first estimate only: markdown posts, public site, RSS feed. Twelve hours.
If the company already lives in paid tiers, a theme marketplace, and a shared newsroom, keep paying.