Strapi uses JavaScript and has quirky APIs. Directus wraps existing databases. Payload CMS is built TypeScript-first, embeds inside Next.js, and gives you full control.
What Is Payload CMS?
Payload is a headless CMS and application framework built with TypeScript. In v3, it embeds directly inside your Next.js app — one codebase, one deployment.
Quick Start
npx create-payload-app@latest
Define Collections
// collections/Posts.ts
import { CollectionConfig } from 'payload';
export const Posts: CollectionConfig = {
slug: 'posts',
admin: {
useAsTitle: 'title',
},
access: {
read: () => true,
create: ({ req: { user } }) => !!user,
},
fields: [
{ name: 'title', type: 'text', required: true },
{ name: 'content', type: 'richText' },
{ name: 'status', type: 'select', options: ['draft', 'published'] },
{ name: 'author', type: 'relationship', relationTo: 'users' },
{ name: 'tags', type: 'array', fields: [
{ name: 'tag', type: 'text' },
]},
{ name: 'featuredImage', type: 'upload', relationTo: 'media' },
{ name: 'publishedDate', type: 'date' },
],
};
Auto-Generated APIs
# REST
GET /api/posts
GET /api/posts/123
POST /api/posts
PATCH /api/posts/123
# GraphQL
POST /api/graphql
Inside Next.js (v3)
// app/posts/page.tsx
import { getPayload } from 'payload';
import config from '@payload-config';
export default async function PostsPage() {
const payload = await getPayload({ config });
const posts = await payload.find({
collection: 'posts',
where: { status: { equals: 'published' } },
sort: '-publishedDate',
limit: 10,
});
return (
<ul>
{posts.docs.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}
Key Features
- TypeScript-first — full type inference for collections
- Access control — field-level permissions
- Versions/Drafts — content versioning built-in
- Localization — multi-language content
- Rich text — Lexical editor with custom blocks
- Uploads — S3, local, or any storage
- Hooks — beforeChange, afterRead, etc.
- Custom components — extend the admin UI
Why Payload
| Feature | Payload v3 | Strapi | Sanity |
|---|---|---|---|
| Language | TypeScript | JavaScript | GROQ |
| Next.js embed | Yes | No | Plugin |
| Type safety | Full | Basic | Generated |
| Self-hosted | Yes | Yes | No |
| Rich text | Lexical | Custom | Portable Text |
| Versioning | Built-in | Plugin | Built-in |
Get Started
- Documentation
- GitHub — 25K+ stars
Populating your CMS with web data? My Apify scrapers extract content from any source. Custom solutions: spinov001@gmail.com
Top comments (0)