The headless CMS market is crowded. Sanity, Contentful, Strapi, Payload, Directus, Hygraph, Builder.io - the list keeps growing.
After implementing dozens of CMS projects, here's how to actually choose.
The Decision Framework
Before comparing features, answer these questions:
- Who's editing content? Technical team or marketing/content folks?
- How complex is your content model? Blog posts or interconnected product data?
- What's your budget? Free tier limits or enterprise pricing?
- Self-hosted or managed? Control vs convenience trade-off
- How important is the editing experience? Real-time preview? Visual builder?
Your answers narrow the field significantly.
The Contenders
Sanity
Best for: Complex content models, real-time collaboration, developer flexibility
Pricing: Generous free tier (10K documents, 500K API requests/month). Growth plans start around $99/month.
Standout features:
- GROQ query language - incredibly powerful
- Real-time collaborative editing
- Portable Text for rich content
- Customisable Studio (React-based)
// Sanity schema example
export default {
name: 'product',
type: 'document',
fields: [
{ name: 'title', type: 'string' },
{ name: 'slug', type: 'slug', options: { source: 'title' } },
{ name: 'description', type: 'portableText' },
{ name: 'price', type: 'number' },
{
name: 'categories',
type: 'array',
of: [{ type: 'reference', to: [{ type: 'category' }] }]
}
]
}
Downsides: Learning curve for GROQ. Studio customisation requires React knowledge.
Contentful
Best for: Enterprise teams, established workflows, extensive integrations
Pricing: Free tier limited (25K records). Paid plans from $300/month - expensive.
Standout features:
- Mature platform, battle-tested
- Excellent internationalisation
- Rich integration ecosystem
- Good for large editorial teams
Downsides: Pricing scales quickly. Less flexible than Sanity for custom fields.
Strapi
Best for: Developers who want full control, self-hosted preference, budget-conscious projects
Pricing: Free and open source. Cloud hosting from $29/month.
Standout features:
- Self-hostable (you own your data)
- Auto-generated REST and GraphQL APIs
- Plugin system for extensibility
- Content types built in admin UI
// Strapi content type (created via admin or code)
// api/product/content-types/product/schema.json
{
"kind": "collectionType",
"attributes": {
"title": { "type": "string", "required": true },
"description": { "type": "richtext" },
"price": { "type": "decimal" },
"images": { "type": "media", "multiple": true }
}
}
Downsides: Self-hosting means you manage infrastructure. Less polished editing experience than hosted options.
Payload CMS
Best for: Developers who want code-first config, TypeScript projects, full ownership
Pricing: Free and open source. Cloud coming.
Standout features:
- 100% TypeScript, code-first
- Built-in authentication and access control
- Excellent developer experience
- Growing rapidly
// Payload collection config
import { CollectionConfig } from 'payload/types';
const Products: CollectionConfig = {
slug: 'products',
admin: { useAsTitle: 'title' },
access: {
read: () => true,
create: ({ req }) => req.user?.role === 'admin'
},
fields: [
{ name: 'title', type: 'text', required: true },
{ name: 'price', type: 'number' },
{ name: 'description', type: 'richText' },
{
name: 'category',
type: 'relationship',
relationTo: 'categories'
}
]
};
Downsides: Younger ecosystem. Self-hosted only (for now). Smaller community than Strapi.
Builder.io
Best for: Visual editing, marketing teams, non-technical content creators
Pricing: Free tier available. Paid from $19/month.
Standout features:
- Visual drag-and-drop builder
- Integrates with existing React/Next.js components
- A/B testing built-in
- No developer bottleneck for landing pages
Downsides: Less suitable for structured data. Best for visual content, not complex data models.
Quick Comparison Table
| CMS | Self-Hosted | Visual Editor | Free Tier | Best For |
|---|---|---|---|---|
| Sanity | No | Studio (customisable) | Generous | Complex content, developers |
| Contentful | No | Yes | Limited | Enterprise, large teams |
| Strapi | Yes | Admin UI | Unlimited | Budget, full control |
| Payload | Yes | Admin UI | Unlimited | TypeScript projects |
| Builder.io | No | Visual builder | Yes | Marketing pages |
Integration with Next.js
All modern headless CMSs work with Next.js. Here's the typical pattern:
// lib/cms.js - Sanity example
import { createClient } from '@sanity/client';const client = createClient({
projectId: process.env.SANITY_PROJECT_ID,
dataset: 'production',
apiVersion: '2024-01-01',
useCdn: true
});
export async function getProducts() {
return client.fetch(`*[_type == "product"] {
_id,
title,
"slug": slug.current,
price,
"imageUrl": image.asset->url
}`);
}
// app/products/page.jsx
export default async function ProductsPage() {
const products = await getProducts();
return (
<div>
{products.map(product => (
<ProductCard key={product._id} {...product} />
))}
</div>
);
}
Preview and Draft Mode
Most CMSs support draft previews. Here's the pattern:
// app/api/preview/route.js
import { draftMode } from 'next/headers';
import { redirect } from 'next/navigation';
export async function GET(request) {
const { searchParams } = new URL(request.url);
const secret = searchParams.get('secret');
const slug = searchParams.get('slug');
if (secret !== process.env.PREVIEW_SECRET) {
return new Response('Invalid token', { status: 401 });
}
draftMode().enable();
redirect(`/products/${slug}`);
}
// In your data fetching
export async function getProduct(slug, preview = false) {
const query = preview
? `*[_type == "product" && slug.current == $slug][0]` // Include drafts
: `*[_type == "product" && slug.current == $slug && !(_id in path("drafts.**"))][0]`;
return client.fetch(query, { slug });
}
My Recommendations
Just starting out? Go with Sanity. The free tier is generous, and it scales well.
Need full control? Strapi or Payload, self-hosted. You own everything.
Marketing-heavy site? Builder.io for landing pages, combined with Sanity for structured content.
Enterprise with budget? Contentful - mature, well-supported, integrates with everything.
TypeScript purist? Payload. Best developer experience in the code-first space.
The Real Answer
The "best" CMS is the one your content editors will actually use.
Involve them in the decision. Let them try the editing experience. A technically superior CMS is worthless if your marketing team hates using it.
We've implemented headless CMS solutions for hotels, e-commerce, and content-heavy sites at LogicLeap. Happy to help you choose the right one.
Top comments (1)
Directus mentioned at the top, but not in the contender list? π€π
Anything we can do to rank in the contenders, in your opinion?
Based on your boxes -
Self-Hosted β
Visual Editor β
Free Tier Unlimited + all features for orgs under $5m annual revenue/funding (license required for above)
Best For CMS+, meaning your website + more since it is essentially a BaaS with an automation builder, visualizations, and advanced RBAC.
So just curious how we could get better! Thank you!