DEV Community

Alex Spinov
Alex Spinov

Posted on

Payload CMS Has a Free TypeScript-First Headless CMS — Here's How to Use It

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

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

Auto-Generated APIs

# REST
GET /api/posts
GET /api/posts/123
POST /api/posts
PATCH /api/posts/123

# GraphQL
POST /api/graphql
Enter fullscreen mode Exit fullscreen mode

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

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


Populating your CMS with web data? My Apify scrapers extract content from any source. Custom solutions: spinov001@gmail.com

Top comments (0)