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: