Payload CMS Installation and Setup
Payload CMS is installed as an npm package in a Next.js project. From version 2.x onwards, a monorepo approach is recommended — CMS and frontend in a single application.
Requirements
- Node.js 18.20.2+ or 20.9.0+
- PostgreSQL 11+ or MongoDB 4.2+
- npm 9+ / yarn 3+ / pnpm 8+
Installation via create-payload-app
npx create-payload-app@latest my-project
An interactive wizard will prompt:
- Template: blank, website, ecommerce, blog — choose the appropriate one
- Database: MongoDB or PostgreSQL
cd my-project
cp .env.example .env
.env:
DATABASE_URI=postgresql://user:password@localhost:5432/payload_db
PAYLOAD_SECRET=super-secret-key-min-32-chars
NEXT_PUBLIC_SERVER_URL=http://localhost:3000
npm run dev
# CMS admin: http://localhost:3000/admin
# On first run, create an administrator
Project Structure (Next.js Monolith)
my-project/
├── app/
│ ├── (frontend)/ # Public frontend
│ └── (payload)/ # Admin panel
│ └── admin/[[...segments]]/page.tsx
├── collections/ # Content types
├── globals/ # Global settings
├── payload.config.ts # Main configuration
├── payload-types.ts # Auto-generated types
└── next.config.js
Basic Configuration
// payload.config.ts
import { buildConfig } from 'payload/config'
import { postgresAdapter } from '@payloadcms/db-postgres'
import { lexicalEditor } from '@payloadcms/richtext-lexical'
import { s3Storage } from '@payloadcms/storage-s3'
import path from 'path'
export default buildConfig({
serverURL: process.env.NEXT_PUBLIC_SERVER_URL || '',
admin: {
user: 'users',
},
editor: lexicalEditor({}),
collections: [
// Import collections
],
db: postgresAdapter({
pool: { connectionString: process.env.DATABASE_URI || '' },
}),
plugins: [
s3Storage({
collections: { media: true },
bucket: process.env.S3_BUCKET!,
config: {
region: process.env.S3_REGION,
credentials: {
accessKeyId: process.env.S3_ACCESS_KEY!,
secretAccessKey: process.env.S3_SECRET_KEY!,
},
},
}),
],
typescript: {
outputFile: path.resolve(__dirname, 'payload-types.ts'),
},
})
Production Deployment
# Build
npm run build
# Start
npm start
# Docker
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]
Timeline
Basic installation with PostgreSQL and S3 for media — 2–4 hours. Project-specific configuration with initial collections — 1 day.







