How to Set Up Payload CMS with Next.js from Scratch in 2026

How to Set Up Payload CMS with Next.js from Scratch in 2026

Payload CMS has become the go-to headless CMS for Next.js developers in 2026 — and for good reason. It runs natively inside your Next.js app, is TypeScript-first, fully open-source, and requires zero vendor lock-in. In this guide, we’ll walk through setting up a brand-new Payload CMS + Next.js project from scratch.

Prerequisites

  • Node.js 20+ installed
  • A MongoDB Atlas account (or local MongoDB instance)
  • Basic familiarity with Next.js and TypeScript

Step 1: Scaffold a New Payload + Next.js App

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

npx create-payload-app@latest my-app

When prompted, choose the website or blank template, select MongoDB as your database, and let the CLI install all dependencies.

Step 2: Configure Your Environment Variables

Navigate into your project and create a .env file at the root:

DATABASE_URI=mongodb+srv://:@cluster.mongodb.net/my-app
PAYLOAD_SECRET=your-super-secret-key-here
NEXT_PUBLIC_SERVER_URL=http://localhost:3000

Replace the DATABASE_URI with your actual MongoDB connection string and set a strong PAYLOAD_SECRET.

Step 3: Explore the Project Structure

Your new project will have a structure like this:

my-app/
├── src/
│   ├── app/           # Next.js App Router pages
│   ├── collections/   # Payload CMS collections (data models)
│   └── payload.config.ts  # Main Payload configuration
├── .env
└── next.config.ts

The key file is payload.config.ts — this is where you define your collections, globals, plugins, and admin UI settings.

Step 4: Define Your First Collection

Collections are Payload’s equivalent of database models. Open src/collections/Posts.ts and define a simple blog post collection:

import { CollectionConfig } from 'payload'

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

export default Posts

Then register it in your payload.config.ts:

import Posts from './collections/Posts'

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

Step 5: Run the Development Server

Start your app with:

npm run dev

Navigate to http://localhost:3000/admin to access the Payload admin panel. Create your first admin user and start adding content!

Step 6: Query Payload Data in Next.js

Since Payload runs inside your Next.js app, you can use the Payload Local API directly in Server Components — no HTTP requests needed:

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',
    limit: 10,
  })

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

Step 7: Deploy to Vercel

Payload + Next.js apps deploy seamlessly to Vercel. Push your project to GitHub, connect it to Vercel, and add your environment variables in the Vercel dashboard. That’s it — your full-stack CMS is live!

Key Takeaways

  • Payload CMS runs natively inside Next.js — no separate backend server needed
  • The Local API gives you type-safe, zero-latency data access in Server Components
  • Collections are TypeScript-first, making your data models self-documenting
  • Deployment to Vercel is straightforward with environment variable configuration

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

Resources: