obsidian/wiki/tech-patterns/payload-cms-installation.md
2026-05-15 14:27:10 +01:00

4.1 KiB
Raw Permalink Blame History

title aliases tags sources created updated
Payload CMS — Installation & Setup
payload-cms
payloadcms-install
payload-nextjs
payload-cms
nextjs
cms
headless
typescript
raw/Installation Documentation.md
2026-05-15 2026-05-15

Payload CMS — Installation & Setup

Payload CMS is a TypeScript-first headless CMS that runs inside a Next.js app (App Router). No separate backend process — Payload lives in your /app/(payload)/ route group.

Requirements

Requirement Version
Node.js 20.9.0+
Next.js 15.2.915.2.x / 15.3.915.3.x / 15.4.1115.4.x / 16.2.2+
Package manager pnpm (preferred), npm, yarn 2+ (yarn 1.x not supported)
Database MongoDB, Postgres, or SQLite

Not all Next.js 15/16 patch releases are compatible — use only the version ranges above.

Quickstart (new project)

npx create-payload-app

Follow the prompts — you get a working Payload app in a new folder.

Add to Existing Next.js App

1. Install packages

pnpm i payload @payloadcms/next

# Optional but common:
pnpm i @payloadcms/richtext-lexical   # Rich text editor
pnpm i sharp                           # Image resize/crop/focal point
pnpm i graphql                         # Only if using GraphQL API

Database adapter — pick one:

pnpm i @payloadcms/db-mongodb    # MongoDB
pnpm i @payloadcms/db-postgres   # Postgres
pnpm i @payloadcms/db-sqlite     # SQLite

npm users: npm i --legacy-peer-deps

2. Copy Payload files into /app

Copy the (payload) route group from Blank Template:

app/
├── (payload)/      ← Payload admin + API routes (never edit these)
└── (my-app)/       ← Your existing frontend (rename freely)

Move existing frontend files into a new route group (e.g. (frontend)). Payload files import from @payloadcms/next — set once, never revisited.

3. Wrap Next.js config with withPayload

// next.config.mjs  ← must be ESM (.mjs or "type":"module" in package.json)
import { withPayload } from '@payloadcms/next/withPayload'

const nextConfig = {
  // your config
}

export default withPayload(nextConfig)

Payload is fully ESM — require() won't work. Use .mjs extension or set "type": "module".

4. Create payload.config.ts

import sharp from 'sharp'
import { lexicalEditor } from '@payloadcms/richtext-lexical'
import { mongooseAdapter } from '@payloadcms/db-mongodb'
import { buildConfig } from 'payload'

export default buildConfig({
  editor: lexicalEditor(),
  collections: [],
  secret: process.env.PAYLOAD_SECRET || '',
  db: mongooseAdapter({
    url: process.env.DATABASE_URL || '',
  }),
  sharp,
})

Register the config path in tsconfig.json:

{
  "compilerOptions": {
    "paths": {
      "@payload-config": ["./payload.config.ts"]
    }
  }
}

5. Start & create first user

pnpm dev
# → http://localhost:3000/admin

Key Takeaways

  • Payload runs inside Next.js — no separate server; admin panel at /admin
  • Only specific Next.js patch versions are compatible — check the list before upgrading
  • (payload) route group files are never edited — they're boilerplate from the template
  • withPayload in next.config must be ESM — use .mjs or "type":"module"
  • PAYLOAD_SECRET must be a strong random string (used to sign tokens)
  • sharp is optional — only needed for image manipulation in Upload collections
  • @payloadcms/richtext-lexical is optional — only needed if using Rich Text fields

Sources