DEV Community

Alex Spinov
Alex Spinov

Posted on

Payload CMS Has a Free Headless CMS: TypeScript-Native, Self-Hosted, No Vendor Lock-In

Contentful costs $300/month for a small team. Sanity charges per API call. Strapi's free tier works until you need custom fields — then you're rewriting plugins.

What if your CMS was code-first, fully typed, self-hosted, and free forever?

That's Payload CMS — a headless CMS that lives in YOUR codebase, not on someone else's server.

What Payload Gives You

  • TypeScript-native — collections defined in code, fully typed API
  • Self-hosted — runs on your server, your database, your rules
  • Admin panel — auto-generated from your collection config
  • REST + GraphQL API — auto-generated endpoints
  • Authentication — built-in user management, access control, 2FA
  • File uploads — media library with image resizing
  • Versions & drafts — content versioning out of the box
  • Localization — multi-language content with fallbacks
  • Free forever — MIT licensed, no usage limits

Quick Start

npx create-payload-app@latest
cd my-cms && npm run dev
Enter fullscreen mode Exit fullscreen mode

Define Collections in Code

// collections/Posts.ts
import type { CollectionConfig } from "payload";

export const Posts: CollectionConfig = {
  slug: "posts",
  admin: {
    useAsTitle: "title",
  },
  access: {
    read: () => true,  // Public
    create: ({ req }) => !!req.user,  // Authenticated only
    update: ({ req }) => req.user?.role === "admin",
    delete: ({ req }) => req.user?.role === "admin",
  },
  fields: [
    { name: "title", type: "text", required: true },
    { name: "slug", type: "text", unique: true, required: true },
    { 
      name: "content", 
      type: "richText",
      // Lexical editor with custom blocks
    },
    { 
      name: "author", 
      type: "relationship", 
      relationTo: "users", 
      required: true 
    },
    { 
      name: "category", 
      type: "select",
      options: ["technology", "business", "design", "culture"],
    },
    { 
      name: "featuredImage", 
      type: "upload", 
      relationTo: "media" 
    },
    { name: "publishedDate", type: "date" },
    { name: "status", type: "select", options: ["draft", "published"], defaultValue: "draft" },
  ],
};
Enter fullscreen mode Exit fullscreen mode

This generates:

  • Admin UI with form fields, validation, and preview
  • REST endpoints: GET /api/posts, POST /api/posts, etc.
  • GraphQL schema with queries and mutations
  • TypeScript types for the entire collection

Auto-Generated API

# REST — auto-generated from collections
GET    /api/posts?where[status][equals]=published&limit=10&sort=-publishedDate
POST   /api/posts
PATCH  /api/posts/:id
DELETE /api/posts/:id

# GraphQL — also auto-generated
POST /api/graphql
Enter fullscreen mode Exit fullscreen mode
// Type-safe local API (for Next.js, server functions, etc.)
const posts = await payload.find({
  collection: "posts",
  where: { status: { equals: "published" } },
  limit: 10,
  sort: "-publishedDate",
});
// posts is fully typed based on your collection config
Enter fullscreen mode Exit fullscreen mode

Payload + Next.js Integration

Payload 3.0 embeds directly into Next.js:

// payload.config.ts
import { buildConfig } from "payload";
import { mongooseAdapter } from "@payloadcms/db-mongodb";
import { lexicalEditor } from "@payloadcms/richtext-lexical";

export default buildConfig({
  admin: { user: "users" },
  editor: lexicalEditor(),
  db: mongooseAdapter({ url: process.env.DATABASE_URI }),
  collections: [Posts, Users, Media],
});
Enter fullscreen mode Exit fullscreen mode

Your CMS admin panel and your Next.js app run in the same process. No API latency for server-side rendering.

When to Choose Payload

Choose Payload when:

  • You want CMS data in your codebase, not a third-party dashboard
  • TypeScript-first development is non-negotiable
  • You need fine-grained access control (RBAC, field-level permissions)
  • Self-hosting is preferred (compliance, data sovereignty)

Skip Payload when:

  • Non-technical editors need to manage content alone (Contentful/Sanity have better editor UX)
  • You want zero infrastructure management (SaaS CMS is simpler)
  • You need a CMS for a static site (Decap CMS or Tina CMS is lighter)

The Bottom Line

Payload CMS proves that "code-first" and "editor-friendly" aren't opposites. Developers define the schema in TypeScript; editors get an auto-generated admin panel that just works.

Start here: payloadcms.com


Need custom data extraction, scraping, or automation? I build tools that collect and process data at scale — 78 actors on Apify Store and 265+ open-source repos. Email me: Spinov001@gmail.com | My Apify Actors

Top comments (0)