Skip to content
STACK IT FAST

Payload CMS

Curated OSSHybridNext.js-Native Headless CMS & App Framework6-20 people

Audited from github.com/payloadcms/payload

Payload CMS is an open-source, MIT-licensed, Next.js-native headless CMS and application framework that installs into an existing /app folder, with swappable MongoDB, PostgreSQL, SQLite, or Cloudflare D1 database adapters.

Language
TypeScript
Database
MongoDB
Hosting
Vercel
License
MIT
Running for
4 years
Team
6-20 people

Why this architecture

A pnpm and Turborepo monorepo lets one core package share a common database-adapter export shape across MongoDB, Postgres, SQLite, and D1, while GraphQL, storage providers, and deployment templates stay in separate packages so a project only pulls in the pieces its target host and database actually need.

Tech stack by layer

10 technologies · audited Sep 17, 2026
Frontend & UI
  • ReactRenders the admin panel shipped by packages/ui and packages/next.
  • Next.jsPayload installs its admin UI and API routes directly into an existing Next.js app folder.
Backend & APIs
  • TypeScriptLanguage for the entire monorepo; by far the largest language by bytes in the repo.
  • Next.jspackages/next wires Payload’s REST, GraphQL and admin routes into Next.js route handlers.
  • GraphQLOptional GraphQL API shipped as a separate package with its own payload-graphql bin, peer-depending on graphql.
Data & Persistence
  • MongoDBOfficial adapter (@payloadcms/db-mongodb) built on Mongoose.
  • PostgreSQLOfficial adapter (@payloadcms/db-postgres) built on Drizzle, re-exported through a drizzle-proxy module.
  • SQLiteOfficial adapter (@payloadcms/db-sqlite) built on Drizzle with libsql, sharing the same drizzle-proxy export shape as the Postgres adapter.
  • DrizzleShared ORM layer (@payloadcms/drizzle) underlying the Postgres, SQLite, Vercel Postgres and D1 adapters.
Infrastructure & Deploy
  • pnpmWorkspace manager for the monorepo, with a workspace-level catalog pinning shared dependency versions.
  • TurborepoOrchestrates cross-package build/lint/dev tasks; build:core explicitly filters out plugin and template packages.
  • Verceltemplates/with-vercel-postgres, with-vercel-mongodb and with-vercel-website target Vercel deployment specifically.
Tooling, Testing & Ops

Payload CMS architecture diagram

Open SVG
Payload CMS architecture diagramAdmin panel → Next.js app (admin routes); Your frontend → Next.js app (REST); Your frontend → GraphQL (GraphQL); Next.js app → Payload core (Payload API); GraphQL → Payload core (resolvers); Payload core → Database adapter (Drizzle · Mongoose); Payload core → Upload storage (uploads)CLIENTSSERVICESWORKERS & JOBSDATA & STORAGEEXTERNALAdmin panelReact (packages/ui)Your frontendREST · GraphQLNext.js appPayload route handlersPayload corecollections · hooksGraphQLoptional packageDatabase adapterPostgres / SQLite / MongoDBUpload storageS3 · Azure · GCS …Payload APIadmin routesRESTresolversGraphQLDrizzle · Mongooseuploads
How the main components of Payload CMS connect, drawn from the audited repository.
Diagram as text
  • Admin panel (React (packages/ui)) → Next.js app (Payload route handlers): admin routes
  • Your frontend (REST · GraphQL) → Next.js app (Payload route handlers): REST
  • Your frontend (REST · GraphQL) → GraphQL (optional package): GraphQL
  • Next.js app (Payload route handlers) → Payload core (collections · hooks): Payload API
  • GraphQL (optional package) → Payload core (collections · hooks): resolvers
  • Payload core (collections · hooks) → Database adapter (Postgres / SQLite / MongoDB): Drizzle · Mongoose
  • Payload core (collections · hooks) → Upload storage (S3 · Azure · GCS …): uploads

Key architectural decisions

6 decisions
  1. 01

    Four database adapters share one export contract

    packages/db-postgres/package.json and packages/db-sqlite/package.json both expose ./drizzle, ./drizzle/relations, and a driver-specific subpath (pg-core vs sqlite-core/libsql) through a drizzle-proxy directory, so switching from Postgres to SQLite (or to db-vercel-postgres or db-d1-sqlite) means swapping the adapter package, not the calling code.

  2. 02

    Payload installs into an existing Next.js /app folder, not a standalone server

    The repository tree has an app/(payload) route group alongside the user’s own app/(app) routes, and packages/next is the package that wires Payload’s admin UI, REST, and GraphQL handlers into Next.js route handlers, matching the README’s claim of installing "directly in your existing /app folder."

  3. 03

    GraphQL ships as an optional package, not a core dependency

    packages/graphql/package.json lists graphql as a peerDependency (not a dependency) and exposes its own payload-graphql binary, so projects that only need the REST or Local API do not pull in graphql-scalars or graphql-http.

  4. 04

    Turborepo build:core deliberately excludes plugins, storage adapters, and app templates

    The root package.json build:core script runs turbo build with --filter "!@payloadcms/plugin-*" --filter "!@payloadcms/storage-*" --filter "!blank" --filter "!blank-tanstack" --filter "!website" --filter "!ecommerce", keeping the everyday build loop to core packages while build:all covers everything.

  5. 05

    Upload storage backends are one package per cloud provider

    packages/storage-azure, storage-gcs, storage-r2, storage-s3, and storage-vercel-blob each wrap a specific provider’s SDK behind the same plugin-cloud-storage interface, so a project picks one storage package instead of configuring a generic multi-provider client.

  6. 06

    Deployment templates target specific hosts by name

    templates/with-vercel-postgres, templates/with-vercel-mongodb, and templates/with-cloudflare-d1 are separate, host-specific starter templates rather than one generic template with environment-variable switches, so the database-and-host combination is chosen at project creation time via create-payload-app.

How Payload CMS is built

How Payload CMS is structured

Payload is a pnpm workspace (pnpm-workspace.yaml lists packages/*, tools/*, test, and four templates/* entries) orchestrated by Turborepo (turbo.json), currently on a 4.0.0-canary version per the root package.json's payload-monorepo name. The core package, payload, is complemented by database adapters (packages/db-mongodb, db-postgres, db-sqlite, db-vercel-postgres, db-d1-sqlite), a shared Drizzle layer (packages/drizzle), an optional GraphQL package (packages/graphql), a family of storage adapters (packages/storage-azure/-gcs/-r2/-s3/-vercel-blob), and a growing plugin ecosystem (plugin-ecommerce, plugin-form-builder, plugin-search, plugin-seo, plugin-stripe, plugin-mcp, and more). packages/next is the integration point that turns all of this into route handlers and an admin UI inside a consuming Next.js app; a parallel, newer app-tanstack/ and packages/tanstack-start show an emerging TanStack Start integration alongside the primary Next.js target.

Frontend

The admin panel is built with React and shipped from packages/ui and packages/next, rendered as part of the Next.js app/(payload) route group that Payload installs alongside the rest of a project's app/ directory. packages/live-preview, packages/live-preview-react, and packages/live-preview-vue provide framework-specific live-preview bridges so a Payload-driven site can preview draft content while editing, independent of whether the site itself is built with React, Vue, or something else.

Backend & APIs

packages/next wires Payload's REST API, Local API, and admin routes into Next.js route handlers, which is what allows the CMS to run inside the same process as a project's own Next.js app rather than as a separate service. GraphQL is deliberately kept out of that core path: packages/graphql/package.json declares graphql as a peerDependency, not a dependency, ships its own payload-graphql binary, and depends on graphql-scalars and graphql-http only within its own package, so consumers who only need REST or the Local API do not install any GraphQL tooling. packages/sdk provides a typed client for calling a Payload instance's REST API from outside the Next.js process.

Data & persistence

Database access is fully adapter-based. packages/db-mongodb depends on mongoose (pinned to 9.9.2) and mongoose-paginate-v2 for MongoDB. The SQL adapters — packages/db-postgres, packages/db-sqlite, packages/db-vercel-postgres, and packages/db-d1-sqlite — all build on packages/drizzle and expose matching export subpaths (./drizzle, ./drizzle/relations, plus a driver-specific path like ./drizzle/pg-core or ./drizzle/sqlite-core/./drizzle/libsql), so application code written against one Drizzle-based adapter needs only its adapter import changed to move between Postgres, SQLite, Vercel Postgres, or Cloudflare D1. File uploads route through one of five provider-specific storage packages (Azure, GCS, R2, S3, Vercel Blob), each depending on that provider's own SDK rather than a shared abstraction library.

Build, test & deploy

The root package.json's build:core script runs turbo build with filters that exclude every @payloadcms/plugin-* and @payloadcms/storage-* package plus the blank, blank-tanstack, website, and ecommerce templates, keeping the everyday build fast; build:all drops those filters to build everything. turbo.json defines build, build:debug, build:bundle-for-analysis, dev, lint, and lint:fix tasks, with build caching its dist/** output and depending on upstream packages' builds (dependsOn: ["^build"]). The extensive test/ directory (well over 100 subdirectories, one per feature area such as test/database, test/graphql, test/localization, test/plugin-search) runs against multiple database adapters via test/dbAdapters.ts and test/docker-compose.yml, and GitHub Actions' main.yml is the primary CI workflow alongside dedicated release workflows (publish-release.yml, publish-prerelease.yml, release-bump.yml).

Self-hosting notes

Because Payload installs into a Next.js app rather than running as a separate server, self-hosting follows normal Next.js deployment: the templates/ directory offers blank, website, and ecommerce starters that are host-agnostic, alongside host-specific starters with-vercel-postgres, with-vercel-mongodb, with-vercel-website, and with-cloudflare-d1 that pre-wire a matching database adapter to that host's native database offering. create-payload-app (packages/create-payload-app) is the scaffolding tool referenced in the README for generating a new project from any of these templates.

What to copy (and what not to)

Giving every SQL database adapter the same export shape (./drizzle, ./drizzle/relations, a driver-specific subpath) so switching databases is a dependency swap, not a rewrite, is a strong pattern for any framework that wants to support multiple backends without forking application code. Filtering the everyday build:core task away from plugins and templates in Turborepo is a simple, effective way to keep a large monorepo's default build fast as the package count grows. The one-package-per-cloud-provider approach to storage adapters is easy to reuse, but a smaller project without Payload's plugin ecosystem should weigh whether five separate packages are worth the maintenance surface compared to one configurable client.

Sources & repo audit

Audited
Sep 17, 2026
Commit
9a2cdcb
License
MIT

Independent analysis of repository at github.com/payloadcms/payload. Spotted an inaccuracy? Use the claim form to request a correction.

Show this stack on your README or website
Tech stack of Payload CMS
[![Tech stack of Payload CMS on STACK IT FAST](https://stackitfast.com/badge/payload-cms.svg)](https://stackitfast.com/project/payload-cms)

Paste it into your README. It shows your current stack and links to this page.

Use this stack

Scaffold it with your agent

Paste this prompt into Claude Code, Cursor, Windsurf or AGY to start a project with Payload CMS's architecture.

  1. 1Copy the promptThe full markdown spec, with every layer and decision.
  2. 2Open your AI toolClaude Code, Cursor, Windsurf or Copilot, in a new repo.
  3. 3Paste and scaffoldUse it as the first instruction; review before you ship.
use-this-stack.md · 61 lines · 8.0 KB
# MISSION: Scaffold "Payload CMS" Production Architecture
You are an expert Senior Staff Software Architect and Full-Stack Engineer. Your mission is to scaffold and implement a production-grade, highly reliable, and modular codebase following the proven architecture of **Payload CMS**.
---
## 1. PROJECT SPECIFICATIONS & BENCHMARK
- **Reference Architecture**: Payload CMS
- **What It Does**: Payload CMS is an open-source, MIT-licensed, Next.js-native headless CMS and application framework that installs into an existing /app folder, with swappable MongoDB, PostgreSQL, SQLite, or Cloudflare D1 database adapters.
- **Domain & Category**: Next.js-Native Headless CMS & App Framework
- **Production Scale**: 6-20 people
- **Development Mode**: HYBRID
- **Architectural Rationale**: A pnpm and Turborepo monorepo lets one core package share a common database-adapter export shape across MongoDB, Postgres, SQLite, and D1, while GraphQL, storage providers, and deployment templates stay in separate packages so a project only pulls in the pieces its target host and database actually need.
- **Live Website Reference**: https://payloadcms.com
- **Source Repository**: https://github.com/payloadcms/payload
---
## 2. PRODUCTION TECH STACK
- **Full Stack Array**: TypeScript, Next.js, React, GraphQL, MongoDB, PostgreSQL, SQLite, Drizzle, pnpm, Turborepo
- **Primary Language(s)**: TypeScript, CSS, JavaScript
- **License of the reference repo**: MIT
- **Frontend**: React — Renders the admin panel shipped by packages/ui and packages/next.; Next.js — Payload installs its admin UI and API routes directly into an existing Next.js app folder.
- **Backend & APIs**: TypeScript — Language for the entire monorepo; by far the largest language by bytes in the repo.; Next.js — packages/next wires Payload’s REST, GraphQL and admin routes into Next.js route handlers.; GraphQL — Optional GraphQL API shipped as a separate package with its own payload-graphql bin, peer-depending on graphql.
- **Data & persistence**: MongoDB — Official adapter (@payloadcms/db-mongodb) built on Mongoose.; PostgreSQL — Official adapter (@payloadcms/db-postgres) built on Drizzle, re-exported through a drizzle-proxy module.; SQLite — Official adapter (@payloadcms/db-sqlite) built on Drizzle with libsql, sharing the same drizzle-proxy export shape as the Postgres adapter.; Drizzle — Shared ORM layer (@payloadcms/drizzle) underlying the Postgres, SQLite, Vercel Postgres and D1 adapters.
- **Infrastructure & deploy**: pnpm — Workspace manager for the monorepo, with a workspace-level catalog pinning shared dependency versions.; Turborepo — Orchestrates cross-package build/lint/dev tasks; build:core explicitly filters out plugin and template packages.; Vercel — templates/with-vercel-postgres, with-vercel-mongodb and with-vercel-website target Vercel deployment specifically.
- **Tooling, testing & ops**: Model Context Protocol — packages/plugin-mcp exposes Payload collections and operations to MCP clients.
---
## 3. KEY ARCHITECTURAL DECISIONS (audited from https://github.com/payloadcms/payload @ 9a2cdcb)
1. **Four database adapters share one export contract**: packages/db-postgres/package.json and packages/db-sqlite/package.json both expose ./drizzle, ./drizzle/relations, and a driver-specific subpath (pg-core vs sqlite-core/libsql) through a drizzle-proxy directory, so switching from Postgres to SQLite (or to db-vercel-postgres or db-d1-sqlite) means swapping the adapter package, not the calling code.
2. **Payload installs into an existing Next.js /app folder, not a standalone server**: The repository tree has an app/(payload) route group alongside the user’s own app/(app) routes, and packages/next is the package that wires Payload’s admin UI, REST, and GraphQL handlers into Next.js route handlers, matching the README’s claim of installing "directly in your existing /app folder."
3. **GraphQL ships as an optional package, not a core dependency**: packages/graphql/package.json lists graphql as a peerDependency (not a dependency) and exposes its own payload-graphql binary, so projects that only need the REST or Local API do not pull in graphql-scalars or graphql-http.
4. **Turborepo build:core deliberately excludes plugins, storage adapters, and app templates**: The root package.json build:core script runs turbo build with --filter "!@payloadcms/plugin-*" --filter "!@payloadcms/storage-*" --filter "!blank" --filter "!blank-tanstack" --filter "!website" --filter "!ecommerce", keeping the everyday build loop to core packages while build:all covers everything.
5. **Upload storage backends are one package per cloud provider**: packages/storage-azure, storage-gcs, storage-r2, storage-s3, and storage-vercel-blob each wrap a specific provider’s SDK behind the same plugin-cloud-storage interface, so a project picks one storage package instead of configuring a generic multi-provider client.
6. **Deployment templates target specific hosts by name**: templates/with-vercel-postgres, templates/with-vercel-mongodb, and templates/with-cloudflare-d1 are separate, host-specific starter templates rather than one generic template with environment-variable switches, so the database-and-host combination is chosen at project creation time via create-payload-app.
---
## 4. NON-NEGOTIABLE ARCHITECTURAL GUARDRAILS
1. **Monorepo & Modular Separation**:
   - Structure as a Turborepo monorepo with strict package boundaries:
     - `apps/web`: Application UI, routing, layouts, and server endpoints.
     - `packages/ui`: Shared design tokens, CSS variables, and Radix UI primitive components.
     - `packages/db`: Database schemas, client singleton, declarative migrations, and seed scripts.
     - `packages/config`: Shared TypeScript, ESLint, and build configurations.
2. **Strict Type Safety & Zero `any` Policy**:
   - Enable `strict: true`, `noImplicitAny: true`, and `strictNullChecks: true`.
   - Validate ALL external inputs, API request bodies, and query parameters with **Zod** schemas before execution.
3. **Frontend & Rendering Guidelines**:
   - Utilize Next.js 15 App Router: default to React Server Components (RSC) for data fetching. Handle mutations through Server Actions with Zod validation. Keep 'use client' directives restricted strictly to interactive leaf components.
4. **Design System & Aesthetics**:
   - Keep every color, radius, shadow and font in a single token file (CSS variables) and consume tokens everywhere; never hardcode hex values in components.
   - Prefer crisp 1px borders and one subtle shadow scale over blurry default shadows. Pair one sans-serif for body/headings with one monospace for tags, badges, metrics, and code.
5. **Data Layer & Reliability**:
   - Write declarative schema definitions with foreign keys, composite indexes on queried filters, and automated timestamp triggers.
   - Use connection pooling and prepared statements for serverless database execution.
---
## 5. STEP-BY-STEP SCAFFOLDING ROADMAP
- **Phase 1: Workspace & Root Config**: Initialize package manager, monorepo configuration (`turbo.json`, `tsconfig.base.json`, `package.json`).
- **Phase 2: Database Schema & Client**: Set up the data layer (MongoDB, PostgreSQL, SQLite, Drizzle): client, connection pool, models, and migration scripts.
- **Phase 3: Design Tokens & UI Primitives**: Build accessible `Button`, `Input`, `Card`, `Badge`, and layout wrappers inside `packages/ui`.
- **Phase 4: Core Application Routes & Handlers**: Implement primary authentication, user session handling, and application routes.
- **Phase 5: Quality Assurance & Build Verification**: Run `tsc --noEmit`, ESLint, Prettier, and smoke test suites to ensure zero compilation or runtime errors.
---
## 6. EXECUTION INSTRUCTIONS
1. Review all specifications, architectural guardrails, and stack choices above.
2. Present the full monorepo directory tree structure.
3. Systematically generate the complete, production-ready codebase according to the 5-phase roadmap above — starting with the root workspace setup, followed by the database schema, UI design system package, and full-stack application routes until the repository is fully scaffolded and ready to run.
Scaffolded something with this prompt?
Would you pick this stack for a next.js-native headless cms & app framework project?

Frequently asked about Payload CMS

What is Payload CMS built with?

TypeScript throughout a pnpm and Turborepo monorepo, with React and Next.js for the admin panel and route handlers, and an optional GraphQL API alongside the REST and Local APIs.

What database does Payload CMS use?

Whichever adapter you install: MongoDB via Mongoose (@payloadcms/db-mongodb), or PostgreSQL, SQLite, Vercel Postgres, or Cloudflare D1 SQLite via Drizzle-based adapters that share one export shape.

Does Payload need a separate backend server?

No. packages/next wires Payload’s admin UI and API routes directly into an existing Next.js app folder, matching the README’s description of installing "directly in your existing /app folder."

Can Payload CMS be deployed to Vercel or Cloudflare?

Yes. The templates directory includes host-specific starters: with-vercel-postgres, with-vercel-mongodb, with-vercel-website, and with-cloudflare-d1.

Does Payload CMS support GraphQL?

Yes, as an optional package (@payloadcms/graphql) that peer-depends on graphql rather than bundling it into the core, alongside the always-available REST and Local APIs.

One email a month: new deep dives and stack trends

New source-audited architectures, head-to-head comparisons and the monthly stack report. No spam, unsubscribe anytime.

use-this-stack.md