Site icon Multidots

Behind the Build: Creating a Ghost-like Newsletter Platform on Sanity

Modern publishing teams need more than a CMS. They need a content operating system — one that unifies writing, publishing, email, audience management, and performance into a single workflow.

We built a full-featured newsletter platform inside Sanity that mirrors the core publishing and newsletter experience of Ghost — and we delivered the entire system in approximately 100 hours.

Our goal was simple: combine the power of modern publishing with the flexibility of a fully programmable content platform.

This blog breaks down how we built a full Ghost-style publishing + newsletter platform inside Sanity, using Next.js and SendGrid and Vercel for hosting, in approximately 100 hours.

Why we looked at Ghost and what inspired us

Before building our current system, our marketing team has been using the Ghost newsletter platform for a couple of years. which gave us valuable hands-on experience with what makes a strong publishing product. Its clean writing tools, built-in newsletters, membership management, and monetization features showed us how powerful an all-in-one platform for publishers can be.

That experience shaped our thinking and became a key reference point as we set out to build our own solution — one that keeps the best of the Ghost model while offering greater flexibility, control, and deep integration with our long-term goals.

Why We Built This in Sanity

Ghost is a great platform, especially for quickly launching newsletters and content sites. However, for our use case, we needed something more flexible, scalable, and deeply integrated with our product and business goals.

What We Needed

  1. More flexibility: We required a system that fits seamlessly into our current infrastructure and can grow with our custom workflows — while staying deeply aligned with our long-term goals.
  2. Fully custom content structure: With Sanity, we design our own content models. This allows us to shape newsletters, articles, campaigns, and internal tools exactly the way our team works, ensuring the platform supports our objectives instead of constraining them.
  3. Complete control over the front end: Rather than working inside a fixed editor or theme, we control the entire user experience: website layout, subscription flows, email rendering, performance optimizations — all built to serve our product vision and business outcomes.
  4. One unified backend: We already use Sanity extensively. Building Ghost-like newsletter tools inside Sanity keeps everything in one ecosystem, making the platform not just a tool, but a core part of how we execute our strategy.

Sanity is a programmable content platform that lets developers build custom content workflows and applications while giving teams a unified system for all digital experiences — ensuring technology stays closely connected to our goals, users, and growth plans.

The Sanity Content Operating System

Sanity provides three interconnected layers:

  1. Content Lake — a real-time, structured content database
  2. Compute & AI — business logic, automation, and intelligent workflows
  3. APIs & SDKs — powerful developer tools to integrate content everywhere

On top of this runs the Sanity Dashboard, where teams manage their operations through:

What This Enables for Us

Using Sanity, we can:

Unlike traditional or even most headless CMS platforms, Sanity gives us a foundation for the entire content lifecycle — from creation and collaboration to delivery and optimization — with the freedom to evolve as our product and business grow.

How We Broke Down Ghost’s Newsletter Functionality

Before writing a single line of code, we spent time carefully studying how Ghost handles newsletters. Not just at the surface level, but at the workflow level — what an editor experiences, what the system manages behind the scenes, and how everything stays connected.

Instead of copying features, we deconstructed the product into simple building blocks.

Here’s how that breakdown looked.

1. Members Login & Profile Management

This turns your audience into a real community instead of just an email list.

2. Tags & labels Management

Tags form the backbone of content organization.

3. Author Management

This keeps collaboration structured and transparent.

4. Pages & Posts Management

This keeps the website organized and scalable.

5. Newsletter Management

This connects content creation with audience communication.

6. Post Working Flow

Ghost’s core publishing flow:

A simple process that keeps everything consistent.

7. Writing → Preview (Web + Email) → Send / Schedule

From one piece of content, you can:

  1. Write it once
  2. Preview it on the website
  3. Preview it in the email
  4. Choose the audience
  5. Send now or schedule for later

This is the heart of Ghost’s experience.

8. Settings & Customization

This is where Ghost becomes your own platform.

These settings allow you to fully control how your site and emails look and behave — without touching code.

Core Components & Building Blocks Used in Sanity

Sanity provides a modular architecture made up of powerful building blocks that allow us to design highly customized content systems and workflows.

1. Content Lake (The Foundation)

A real-time, structured content database that stores all content in a single source of truth.

What it gives us:

2. Sanity Studio (Custom CMS Interface)

A fully customizable editing environment where teams manage and produce content.

Key building blocks inside Studio:

3. APIs & Developer Toolkit

Core APIs:

SDKs & Tools:

4. Asset & Media Infrastructure

5. Dashboard & Application Layer

Where operational tools live:

6. Frontend Integration Layer

How everything connects to our product:

Step-by-Step Implementation Overview

Step 1 – System Architecture Planning

We built the platform using a modern, flexible architecture that gives us full control over both content management and the user experience.

LayerTechnology
Backend / Content OSSanity: Sanity serves as our core content and data platform. It acts as the single source of truth for all structured content, including:Posts & PagesTags & LabelsAuthorsMembersSite configuration and global settingsSanity’s schema-driven approach allows us to define precise content models and enforce validation rules, ensuring consistency across all channels.
FrontendNext.js powers the entire front-end experience:Public website and landing pagesSubscription flowsNewsletter/posts archive and reading experienceSEO and analytics integrationThis separation allows us to evolve the UI and product experience independently from the content layer.
Admin & Internal ToolsWe built a custom admin interface using Sanity’s App SDK to support our editorial and operational workflows.Through this interface, our team can manage:Posts and pagesTags and labelsMembersGlobal site settingsPreview & custom website viewsThis gives non-technical users powerful, purpose-built tools while keeping the system aligned with our product goals and publishing workflows.
Email InfrastructureFor email delivery and campaign management, we use SendGrid as our primary email infrastructure. It handles all transactional and marketing communications

This stack gives us:

Together, Sanity + Next.js + App SDK form a flexible foundation that supports our current needs while remaining adaptable for future growth.

Step 2 – Content Modeling in Sanity

We designed a fully structured content system in Sanity using custom schemas that define how every piece of content is created, validated, and connected.

Each schema was carefully structured with strong validation rules and document relationships to ensure consistency, reliability, and long-term scalability across the platform.

Custom Page Builder with Reusable Blocks

To give editors complete flexibility while maintaining design control, we built a custom page builder system for both Posts and Pages using modular blocks. These blocks allow non-technical teams to assemble rich pages and posts without breaking layout or design standards, while developers retain full control over how each block renders on the frontend.

Here is the code for the post schema:

import { defineField, defineType } from "sanity";
import { StickyNote } from "lucide-react";
export default defineType({
  name: 'post',
  title: 'Posts',
  type: 'document',
  fields: [
    defineField({
      name: 'title',
      title: 'Title',
      type: 'string',
      validation: rule => rule.required()
    }),
    defineField({
      name: 'slug',
      title: 'Slug',
      type: 'slug',
      options: {
        source: 'title',
      },
      validation: rule => rule.required()
    }),
    defineField({
      name: 'excerpt',
      title: 'Subtitle (Excerpt)',
      description: 'The subtitle of the post. This will be used to display the subtitle of the post on the post page.',
      type: 'text',
      rows: 4  
    }),
    defineField({
      name: 'pageBuilder',
      title: 'Content',
      type: 'pageBuilder',
    }),
    defineField({
      name: 'image',
      title: 'Image',
      type: 'image',
      fields: [
        defineField({
          name: 'altText',
          title: 'Alternative Text',
          type: 'string'
        }),
        defineField({
          name: 'caption',
          title: 'Caption',
          type: 'string'
        }),
      ],
    }),
    defineField({
      name: 'author',
      title: 'Author',
      type: 'array',
      description: 'The authors of the post. This will be used to display the authors of the post on the post page.',
      of: [
        {
          type: 'reference',
          to: [{ type: 'author' }],
        },
      ],
      options: {
        layout: 'tags',
      },
      validation: rule => rule.required()
    }),
    defineField({
      name: 'tag',
      title: 'Tags',
      type: 'array',
      description: 'The tags for the post.',
      of: [
        {
          type: 'reference',
          to: [{ type: 'tag' }],
        },
      ],
      options: {
        layout: 'tags',
      },
      validation: rule => rule.required()
    }),
	  defineField({
      name: 'isFeatured',
      title: 'Feature this post',
      type: 'boolean',
      initialValue: false,
    }),
    defineField({
      name: "seo",
      title: 'SEO',
      type: "seoObject",
    }),
  ],
  icon: StickyNote,
  // ✅ Custom Preview Section
  preview: {
    select: {
      title: "title",
      media: "image",
      author0: "author.0.name", // first author name
      author1: "author.1.name", // optional if multiple authors
    },
    prepare(selection) {
      const { title, media, author0, author1 } = selection;
      let subtitle = "";
      if (author0 && author1) subtitle = `By ${author0}, ${author1}`;
      else if (author0) subtitle = `By ${author0}`;
      else subtitle = "By Unknown";

      return {
        title: title || "Untitled Post",
        subtitle,
        media: media || StickyNote, // default icon if no image
      };
    },
  },
  
})

You can find the full code in our GitHub repository.

Step 3 – Building the Custom Admin Experience

Using the Sanity App SDK, we built a fully customized admin interface tailored to our editorial and operational workflows.

Through this custom admin UI, our editors and administrators can:

This purpose-built interface gives non-technical users powerful, easy-to-use tools while ensuring that publishing remains consistent, efficient, and aligned with our product goals.

Key Complex Features Implemented within the custom admin

1. Posts & Pages Editor

We built a powerful and flexible editor that allows content teams to create and structure content exactly as required. Editors have full control over the content layout through a rich text editing experience combined with custom page builder blocks.

This approach enables them to design rich, engaging pages while maintaining consistent UI and UX across the platform — without requiring developer involvement.

To further support content quality and confidence before publishing, we added a comprehensive preview system:

2. Advanced Email Functionality

We implemented a custom email workflow tightly integrated with the publishing process. When creating a post, editors can choose between multiple publishing actions:

This flexible workflow allows the editorial team to manage website content and email campaigns from a single interface, streamlining operations and improving efficiency.

3. Site Configuration & Global Settings

We developed a centralized configuration system where administrators can manage all global website settings, including:

This ensures consistency across the platform and enables rapid updates without code changes.

3.1 Email settings

Allows administrators to manage all email-related configurations from a single place, including sender details, templates, and delivery options.

This ensures consistent branding and reliable communication across the platform without code changes.

3.2 Navigation settings

Provides a centralized way to define and manage the site’s navigation structure.

Admins can create, update, and reorder menus easily, ensuring consistent navigation across pages and quick updates as content evolves.

Step 4 – Frontend Development with Next.js

We built the entire frontend experience using Next.js, focusing on performance, flexibility, and seamless integration with the Sanity backend.

Key implementations include:

This frontend architecture ensures a fast, scalable, and highly customizable reading and publishing experience.

Key Decisions, Tradeoffs, and Learnings

1. Build vs Buy: Choosing Sanity Over a Turnkey Platform

2. Structured Content Over Freeform Flexibility

3. Custom Page Builder Instead of Generic Editor

Final Thoughts

Building a Ghost-like newsletter tool doesn’t require years of work.

It requires clear content structure, strong fundamentals, and disciplined execution.

We built this tool in ~100 hours to prove a simple point: when your content model is right, everything else moves faster.

Instead of obsessing over features, focus on signal:

At Multidots, we’re an official Sanity Enterprise Agency Partner. We help teams turn structured content into real platforms—not demos or prototypes, but production systems that scale.

If you want to explore this in practice:

Exit mobile version