Introduction
Payload CMS 3.0 has revolutionized the headless CMS landscape by becoming the first CMS that installs directly into any Next.js application with just one command. This integration eliminates the complexity of managing separate backend infrastructure while providing a powerful, TypeScript-first content management system.
In this comprehensive guide, we’ll walk through setting up Payload CMS 3.0 with Next.js from scratch, covering installation, configuration, and best practices for production deployment.
Prerequisites
- Node.js 18+ installed
- Basic knowledge of Next.js and React
- Understanding of TypeScript (recommended)
- MongoDB database (local or cloud)
Step 1: Create a New Next.js Project
Start by creating a new Next.js application with TypeScript support:
npx create-next-app@latest my-payload-app --typescript --tailwind --eslint --app
cd my-payload-app
Step 2: Install Payload CMS 3.0
Install Payload CMS and its dependencies:
npm install payload @payloadcms/next @payloadcms/richtext-lexical
npm install --save-dev @types/node
Step 3: Configure Environment Variables
Create a .env.local file in your project root:
PAYLOAD_SECRET=your-secret-key-here
DATABASE_URI=mongodb://localhost:27017/my-payload-app
NEXT_PUBLIC_SERVER_URL=http://localhost:3000
Step 4: Create Payload Configuration
Create a payload.config.ts file in your project root:
import { buildConfig } from 'payload/config'
import { mongooseAdapter } from '@payloadcms/db-mongodb'
import { lexicalEditor } from '@payloadcms/richtext-lexical'
import { nextPayload } from '@payloadcms/next/utilities'
export default buildConfig({
admin: {
user: 'users',
importMap: {
baseDir: process.cwd(),
},
},
collections: [
{
slug: 'users',
auth: true,
fields: [
{
name: 'name',
type: 'text',
required: true,
},
],
},
{
slug: 'posts',
fields: [
{
name: 'title',
type: 'text',
required: true,
},
{
name: 'content',
type: 'richText',
editor: lexicalEditor({}),
},
{
name: 'publishedDate',
type: 'date',
},
],
},
],
editor: lexicalEditor({}),
secret: process.env.PAYLOAD_SECRET || '',
typescript: {
outputFile: process.cwd() + '/payload-types.ts',
},
db: mongooseAdapter({
url: process.env.DATABASE_URI || '',
}),
})
Step 5: Update Next.js Configuration
Modify your next.config.js to include Payload:
import { withPayload } from '@payloadcms/next/withPayload'
/** @type {import('next').NextConfig} */
const nextConfig = {
// Your Next.js config
}
export default withPayload(nextConfig)
Step 6: Create API Routes
Create the API route handler at src/app/(payload)/admin/[[...segments]]/page.tsx:
import { RootPage, generatePageMetadata } from '@payloadcms/next/views'
import { Metadata } from 'next'
import config from '@payload-config'
type Args = {
params: {
segments: string[]
}
searchParams: { [key: string]: string | string[] | undefined }
}
export const generateMetadata = ({ params, searchParams }: Args): Promise =>
generatePageMetadata({ config, params, searchParams })
const Page = ({ params, searchParams }: Args) =>
RootPage({ config, params, searchParams })
export default Page
Step 7: Create REST API Endpoints
Create src/app/api/(payload)/[...segments]/route.ts:
import { REST_DELETE, REST_GET, REST_PATCH, REST_POST } from '@payloadcms/next/routes'
import config from '@payload-config'
export const GET = REST_GET(config)
export const POST = REST_POST(config)
export const DELETE = REST_DELETE(config)
export const PATCH = REST_PATCH(config)
Step 8: Initialize the Database
Run the development server and create your first admin user:
npm run dev
Navigate to http://localhost:3000/admin and create your first admin user.
Step 9: Fetching Data in Your Next.js Components
Create a component to display posts:
import { getPayloadHMR } from '@payloadcms/next/utilities'
import config from '@payload-config'
export default async function PostsList() {
const payload = await getPayloadHMR({ config })
const posts = await payload.find({
collection: 'posts',
limit: 10,
})
return (
Latest Posts
{posts.docs.map((post) => (
{post.title}
))}
)
}
Best Practices and Tips
1. Environment Security
Always use strong, unique secrets for production and never commit sensitive environment variables to version control.
2. Database Optimization
Consider using MongoDB Atlas for production deployments with proper indexing for better performance.
3. Type Safety
Payload automatically generates TypeScript types. Import them for better development experience:
import { Post } from '../payload-types'
4. Caching Strategy
Implement proper caching strategies using Next.js built-in caching or external solutions like Redis for high-traffic applications.
Deployment Considerations
When deploying to production:
- Set up proper environment variables on your hosting platform
- Configure your MongoDB connection for production
- Enable HTTPS and configure CORS settings
- Set up proper backup strategies for your database
Conclusion
Payload CMS 3.0’s integration with Next.js represents a significant leap forward in headless CMS technology. By following this guide, you now have a fully functional Next.js application with a powerful, type-safe CMS that scales with your needs.
The seamless integration eliminates the complexity of managing separate backend infrastructure while providing enterprise-grade features like authentication, file uploads, and a beautiful admin interface.
Start building your next project with this powerful combination and experience the future of content management!