Strapi is great until you need TypeScript. Payload CMS is TypeScript-first, code-first, and now embeds directly into Next.js.
What is Payload CMS?
Payload is an open-source headless CMS and application framework built with TypeScript. Since v3, it runs directly inside your Next.js app — no separate server needed.
Why Payload Is Gaining Ground
1. Lives Inside Next.js
// payload.config.ts
import { buildConfig } from 'payload';
import { mongooseAdapter } from '@payloadcms/db-mongodb';
export default buildConfig({
collections: [
{
slug: 'posts',
fields: [
{ name: 'title', type: 'text', required: true },
{ name: 'content', type: 'richText' },
{ name: 'author', type: 'relationship', relationTo: 'users' },
{ name: 'publishedAt', type: 'date' },
{ name: 'status', type: 'select', options: ['draft', 'published'] },
],
},
],
db: mongooseAdapter({ url: process.env.MONGODB_URI }),
});
Your CMS is your Next.js app. One deployment, one codebase.
2. Type-Safe Everything
import { getPayload } from 'payload';
import config from '@payload-config';
const payload = await getPayload({ config });
// Fully typed — IDE autocomplete for all fields
const posts = await payload.find({
collection: 'posts',
where: { status: { equals: 'published' } },
sort: '-publishedAt',
limit: 10,
});
// posts.docs[0].title → string
// posts.docs[0].author → User object (auto-populated)
3. Access Control Built In
{
slug: 'posts',
access: {
read: () => true,
create: ({ req: { user } }) => Boolean(user),
update: ({ req: { user }, id }) => {
if (user.role === 'admin') return true;
return { author: { equals: user.id } };
},
delete: ({ req: { user } }) => user?.role === 'admin',
},
fields: [/* ... */],
}
Row-level security. Field-level access. No plugins needed.
4. Rich Text with Lexical
{
name: 'content',
type: 'richText',
editor: lexicalEditor({
features: ({ defaultFeatures }) => [
...defaultFeatures,
BlocksFeature({ blocks: [Banner, CodeBlock, MediaBlock] }),
],
}),
}
5. Auto-Generated REST & GraphQL
# REST API (automatic)
GET /api/posts
GET /api/posts/:id
POST /api/posts
PATCH /api/posts/:id
# GraphQL (opt-in)
POST /api/graphql
Both APIs generated from your config. Zero code.
Payload vs Strapi vs Directus
| Payload | Strapi | Directus | |
|---|---|---|---|
| TypeScript | First-class | Partial | No |
| Next.js embed | Yes (v3) | No | No |
| Access control | Code-based | Role-based | Role-based |
| Database | MongoDB, Postgres | SQLite, Postgres, MySQL | SQL databases |
| Rich text | Lexical | Blocks | WYSIWYG |
| Self-hosted | Free | Free | Free |
Getting Started
npx create-payload-app@latest
# Choose:
# - Next.js template
# - MongoDB or Postgres
# - Blank or with starter content
The Bottom Line
Payload is the CMS that developers actually want to use. TypeScript-first, lives in your Next.js app, and gives you code-level control over every aspect.
Need data solutions? I build web scraping tools. Check my Apify actors or email spinov001@gmail.com.
Top comments (0)