Case study · Stack

How Ghost built an open source publishing platform on Node.js

Ghost is an open source publishing platform run by a nonprofit foundation, used for blogs, newsletters and paid memberships. Its core is a Node.js JSON API with MySQL, a separate admin app now being rebuilt in React, and outside services like Stripe, Mailgun and Tinybird for payments, email and analytics.
Copy this stackghost.org Publishing platform for newsletters and paid memberships · SG · founded 2013

Language

  • TypeScriptgithub.com

    Language for all new code, as the codebase moves away from plain JavaScript.

    Why: Type safety is the team's top stated priority for the codebase.

UI library

  • Handlebarsdocs.ghost.org

    Template language for Ghost themes.

    Why: Ghost calls it both powerful and extremely performant while staying simple.

  • Reactgithub.com

    Framework of the admin app, where all new admin screens are built.

Full-stack framework

  • Expressdocs.ghost.org

    Web server that serves the theme layer of every Ghost site.

Hosting

  • Dockerghost.org

    Official way to install and run Ghost with its new side services, set to become the default in Ghost 7.0.

    Why: Analytics and the social web now run as separate services alongside Ghost.

Database

Payments

  • Stripeghost.org

    Handles paid memberships and the prices set in Ghost Admin.

Email

  • Mailgundocs.ghost.org

    Sends bulk newsletter emails to members.

    Why: Sending bulk email over plain SMTP can get the server's IP blacklisted.

Styling and UI kit

  • Tailwind CSSgithub.com

    Styles the admin and its Shade component library.

Build and runtime

  • Vitegithub.com

    Builds and serves the React admin in development.

ORM

  • Bookshelf.jsdocs.ghost.org

    ORM layer between Ghost and the database, now being replaced by repositories on top of Knex.

    Why: It let Ghost support more than one database.

Backend framework

  • Node.jsdocs.ghost.org

    Runs Ghost's core server and API.

    Why: Ghost wanted to feel familiar to teams already used to JavaScript codebases.

Testing

  • Vitestgithub.com

    Test runner for the admin app and the core server.

Analytics

  • Tinybirdghost.org

    Powers Ghost's native, cookie-free web analytics on top of ClickHouse.

Error monitoring

How they built it

An API at the core, with a separate admin

Ghost is built as a RESTful JSON API, split into a Content API and an Admin API. The admin is a completely separate client of that API, so the editor stays fast without slowing down the public site, and writers never need Git to publish.

The public site comes from a theme layer served by Express, with Handlebars templates. Ghost says it picked the whole JavaScript approach so teams already used to JavaScript codebases would feel at home.

Sources:docs.ghost.org

From Ember to React in the admin

For years the admin ran on Ember. The move to React happened screen by screen, with new React apps running inside the old Ember admin. Today the admin app in the monorepo is a React project built with Vite, styled with Tailwind and tested with Vitest, and the contributor guide says all new admin features must be built in React.

The server is going through a similar cleanup. The stated top priority is type safety: moving the code from JavaScript to TypeScript, validating incoming data with Zod and slowly replacing the Bookshelf ORM with services, repositories and plain Knex.

Sources:github.com github.com forum.ghost.org

Ghost 6.0: analytics and the social web as separate services

Until Ghost 6.0, released in August 2025, Ghost was a single app on a server with one MySQL database. Version 6 added native, cookie-free web analytics, built on ClickHouse through a partnership with Tinybird, and a connection to the open social web over ActivityPub.

Both features run as independent services next to Ghost. That is also why Docker Compose became an official way to install and run Ghost, and it is set to become the default in Ghost 7.0.

Sources:ghost.org github.com

Newsletters and payments rely on specialists

Ghost does not try to send bulk email itself. Newsletters go through Mailgun, the only supported bulk provider, because sending mass email over plain SMTP can get the server's IP blacklisted. Regular SMTP is still used for transactional messages like login links and invites.

Paid memberships run on Stripe: once a site connects its Stripe account, the prices created in Ghost Admin show up there automatically.

Sources:docs.ghost.org docs.ghost.org ghost.org

Also detected on their website

Found on the homepage with the open Wappalyzer rules (HTML, scripts and headers). It shows what runs in the browser, not the whole backend.

  • Alpine.js
  • FirstPromoter
  • HSTS
  • Hugo
  • Netlify