How to Set Up Payload CMS with Next.js 16

How to Set Up Payload CMS with Next.js 16

Payload CMS is the only headless CMS that installs directly into your Next.js application — no separate server, no extra deployment, no schema drift. With Next.js 16 now the active LTS release, this guide walks you through setting up a fresh Payload + Next.js 16 project from scratch.

Prerequisites

  • Node.js 20 or later
  • A PostgreSQL database (local or hosted, e.g. Neon, Supabase, Railway)
  • Basic familiarity with Next.js App Router

Step 1: Scaffold a New Project

The fastest way to get started is with the official create-payload-app CLI, which scaffolds a Next.js 16 app with Payload pre-configured:

npx create-payload-app@latest my-site
cd my-site

When prompted, choose the website or blank template and select PostgreSQL as your database adapter.

Step 2: Configure Your Database

Open the generated .env file and add your database connection string:

DATABASE_URI=postgresql://user:password@localhost:5432/my_payload_db
PAYLOAD_SECRET=your-super-secret-key-here

The PAYLOAD_SECRET is used to sign JWTs and encrypt sensitive data — use a long, random string in production.

Step 3: Explore the Payload Config

The heart of your Payload setup lives in src/payload.config.ts. A minimal config looks like this:

import { buildConfig } from 'payload'
import { postgresAdapter } from '@payloadcms/db-postgres'
import { lexicalEditor } from '@payloadcms/richtext-lexical'

export default buildConfig({
  secret: process.env.PAYLOAD_SECRET || '',
  db: postgresAdapter({
    pool: { connectionString: process.env.DATABASE_URI },
  }),
  editor: lexicalEditor(),
  collections: [],
})

Step 4: Create Your First Collection

Collections are the building blocks of your content model. Create a Posts collection by adding a file at src/collections/Posts.ts:

import type { CollectionConfig } from 'payload'

export const Posts: CollectionConfig = {
  slug: 'posts',
  admin: {
    useAsTitle: 'title',
  },
  fields: [
    {
      name: 'title',
      type: 'text',
      required: true,
    },
    {
      name: 'content',
      type: 'richText',
    },
    {
      name: 'publishedAt',
      type: 'date',
    },
  ],
}

Then register it in your payload.config.ts:

import { Posts } from './collections/Posts'

export default buildConfig({
  // ...
  collections: [Posts],
})

Step 5: Run Migrations and Start the Dev Server

Payload uses Drizzle ORM under the hood. Push your schema to the database and start the dev server:

npx payload migrate
npm run dev

Navigate to http://localhost:3000/admin to create your first admin user and start adding content.

Step 6: Query Content with the Local API

The real power of Payload inside Next.js is the Local API — you can query your database directly in Server Components without any HTTP round-trips:

import { getPayload } from 'payload'
import config from '@payload-config'

export default async function BlogPage() {
  const payload = await getPayload({ config })

  const posts = await payload.find({
    collection: 'posts',
    where: {
      publishedAt: { less_than_equal: new Date().toISOString() },
    },
    sort: '-publishedAt',
    limit: 10,
  })

  return (
    <ul>
      {posts.docs.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  )
}

Step 7: Deploy

Because Payload runs inside your Next.js app, deployment is the same as any Next.js project. Push to Vercel, Railway, or any Node.js host. Make sure your environment variables (DATABASE_URI and PAYLOAD_SECRET) are set in your hosting dashboard.

Key Takeaway: Payload CMS eliminates the friction of managing a separate CMS server. By living inside your Next.js 16 app, you get full TypeScript types, zero-latency Local API queries, and a single deployment — making it one of the most developer-friendly CMS setups available in 2026.

Hashtags: #PayloadCMS #NextJS #WebDevelopment #HeadlessCMS #TypeScript #ReactJS #FullStack

Resources: