DEV Community

Alex Spinov
Alex Spinov

Posted on

Payload CMS Has a Free Headless CMS — Here's Why It's Replacing Strapi

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 }),
});
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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: [/* ... */],
}
Enter fullscreen mode Exit fullscreen mode

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] }),
    ],
  }),
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)