Headless CMS Compared: Six Options, One Blog

A headless CMS stores content and serves it through an API, leaving the website's design to your own code. Sanity and Contentful are hosted services, Strapi and Payload are open source and run on your own database, Storyblok adds a visual page editor, and Decap edits Markdown files in Git. The table below compares them side by side.

Quick picks
NeedPick
Flexible content modellingSanity
Own your data, free to self-hostStrapi or Payload
Visual editing for marketersStoryblok
Zero cost, content in GitDecap CMS

Updated

We are not affiliated with any of these vendors. Each section below fetches the same list of blog posts, so you can compare how each feels to code against, and the table shows listed prices as we read them on the day this page was updated.

Picking the site generator too? See static site generators compared.

The six at a glance

Six headless CMSs (prices as listed on 13 October 2026)
CMSTypeWhere content livesFree optionPaid from
SanityHosted content platform, open-source editor (Studio)Sanity's cloudFree plan$15 per seat a month (Growth)
ContentfulHosted, closed sourceContentful's cloudSee vendorSee vendor (page did not load for us)
StrapiOpen source (MIT), self-host or cloudYour databaseSelf-hosting is free$35 a month (Cloud Starter)
PayloadOpen source (MIT), runs inside Next.jsYour databaseSelf-hosting is freeYour hosting costs
StoryblokHosted, visual editorStoryblok's cloudStarter plan$99 a month (Growth)
Decap CMSOpen source (MIT), Git-basedMarkdown files in your repositoryFreeNone

Which fits your project

Which one fits
SituationGood fit
Developers want to model content in code and query it flexiblySanity
Large team, many locales, strict roles, budget for a vendorContentful
Want to own the database and the serverStrapi or Payload
Already on Next.js and want the CMS in the same appPayload
Marketers want to edit pages visuallyStoryblok
A small static site where content can live in GitDecap CMS

The same blog list from each CMS

Sanity: list posts with GROQ

GROQ selects and shapes documents in one query, so the slug arrives as a plain string.

import { createClient } from "next-sanity";

const client = createClient({ projectId: "your-id", dataset: "production", apiVersion: "2025-01-01", useCdn: true });

export async function getPosts() {
  return client.fetch(`*[_type == "post"] | order(publishedAt desc){ title, "slug": slug.current, publishedAt }`);
}

Contentful: list posts with the Delivery API

getEntries filters by content type; fields come back under fields.

import { createClient } from "contentful";

const client = createClient({ space: process.env.CONTENTFUL_SPACE_ID!, accessToken: process.env.CONTENTFUL_DELIVERY_TOKEN! });

export async function getPosts() {
  const res = await client.getEntries({ content_type: "blogPost", order: ["-fields.publishDate"] });
  return res.items.map((i) => ({ title: i.fields.title, slug: i.fields.slug }));
}

Strapi 5: list posts over REST

Strapi generates a REST API per content type. Version 5 returns fields directly on each item, without the attributes wrapper of version 4.

export async function getPosts() {
  const url = `${process.env.STRAPI_URL}/api/posts?sort=publishedAt:desc&fields[0]=title&fields[1]=slug`;
  const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.STRAPI_TOKEN}` } });
  if (!res.ok) throw new Error(`Strapi ${res.status}`);
  const { data } = await res.json();
  return data; // [{ id, documentId, title, slug }, ...]
}

Payload 3: query from a Server Component

Payload runs inside your Next.js app, so a Server Component can read the database through the Local API with no HTTP request.

// app/blog/page.tsx
import { getPayload } from "payload";
import config from "@payload-config";

export default async function Blog() {
  const payload = await getPayload({ config });
  const { docs } = await payload.find({ collection: "posts", sort: "-publishedAt", limit: 20 });
  return <ul>{docs.map((p) => <li key={p.id}><a href={`/blog/${p.slug}`}>{p.title}</a></li>)}</ul>;
}

Storyblok: list stories from the CDN API

Stories in a folder are fetched with starts_with. The public token is read-only and safe to use in a static build.

export async function getPosts() {
  const qs = new URLSearchParams({ starts_with: "blog/", version: "published", sort_by: "first_published_at:desc", token: process.env.STORYBLOK_TOKEN! });
  const res = await fetch(`https://api.storyblok.com/v2/cdn/stories?${qs}`);
  const { stories } = await res.json();
  return stories.map((s) => ({ title: s.name, slug: s.slug }));
}

Decap CMS: edit Markdown in your repository

Decap is an admin page that commits Markdown files to your Git repository. Your site generator builds them like any other file.

# public/admin/config.yml
backend:
  name: github
  repo: your-org/your-site
  branch: main
media_folder: public/images
collections:
  - name: posts
    label: Blog posts
    folder: content/posts
    create: true
    fields:
      - { label: Title, name: title, widget: string }
      - { label: Date, name: date, widget: datetime }
      - { label: Body, name: body, widget: markdown }

When you do not need a CMS

A headless CMS adds an account, an API, previews and a build hook to look after. For a five-page business site that changes a few times a year, that is overhead. Markdown in Git, or a builder where owners edit the page they see, often serves them better.

How it works

  1. Decide where content should live: a vendor's cloud, your database, or Git.
  2. Check whether editors need visual page editing or just forms.
  3. Compare the free option and the first paid tier against your team size.
  4. Model one content type, such as a blog post, and fetch it into your site before committing.

Tips

Frequently asked questions

What is the difference between a headless CMS and WordPress?

Traditional WordPress stores content and renders the pages with its themes. A headless CMS only stores and serves content; your own front end, such as a Next.js or Astro site, renders it.

Which headless CMS is best for Next.js?

Payload runs inside a Next.js app, which makes it the tightest fit. Sanity, Contentful and Storyblok also have official Next.js guides and work well with server rendering and revalidation.

Is there a free headless CMS?

Yes. Strapi, Payload and Decap CMS are open source and free to self-host. Sanity and Storyblok have free plans with limits on users and usage.

Do I need a headless CMS at all?

Not always. If developers edit the site, Markdown files in the repository are simpler. If non-technical people edit a small business site, a website builder with a built-in editor is usually quicker than wiring a CMS to custom code.

Related: Static site generators, Frontend framework comparison, React Server Components, Best blogging platforms, All free tools.

Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.

More in Guides

We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.

Product

Who It's For

Features

Resources

Company

View Sitemap