You’ve decided to try Payload, or you’ve just been handed a Payload project, and you want a working app with your own content in it. Payload 3 shipped on 19 November 2024, and walkthroughs written before then teach a setup that no longer exists.
As of 10 November 2026, the latest stable release of Payload is 3.93.0, published on 4 November, and Payload 4 is in beta (the 3.93.0 release notes). We scaffolded a blank project with create-payload-app 3.93.0 on 10 November 2026, and the requirements, the template list and the first step on this page come from that run.
This guide covers what you need before you start, which template to pick, six steps from an empty folder to a page that lists your content, how we start our own client projects, what to do when the first run fails, and where to learn next.
- What you need before you start
- Which Payload template should you start from?
- Build your first Payload project, step by step
- How we start a new Payload project
- What to do when the first run fails
- Where to learn Payload next
- Frequently asked questions
- What to do next
What you need before you start
You need a supported Node.js version, a package manager and a database Payload can reach.
- Node.js 22.23.4 or later on the 22 line, or 24.22.1 or later. That’s the range in the
enginesfield of thepayload3.93.0 package and in Payload’s installation docs. Payload’s own Get started page still lists Node.js 20.9.0+, so go by the package. Check yours withnode -v. - pnpm 10.26 or later. Payload prefers pnpm, and the blank template’s
pnpm-workspace.yamluses theallowBuildssetting, which pnpm added in 10.26.0 on 15 December 2025. npm and Yarn 2 or later also work; Yarn 1 doesn’t. - A database. SQLite is the shortest path on a laptop, because the database is a single file and there’s no server to run. Postgres and MongoDB are the other two official options, and which database to choose covers the trade-offs for a project you’ll deploy.
For example, when we scaffolded the blank template on 10 November 2026 with create-payload-app 3.93.0, pnpm 9.15.0 and Node.js 22.23.0, the install stopped at “packages field missing or empty”, and our Node version sat below the floor.
Which Payload template should you start from?
Start from blank if you’re learning Payload or designing your own content model, and from website if you’re building a marketing site or a blog. create-payload-app offers five templates in its picker as of version 3.93.0, all from the templates folder in Payload’s repository.
| Template | What you get | Pick it when |
|---|---|---|
| blank | A users collection for admin sign-in and a media collection for uploads | You’re learning, or the content model is yours to design |
| website | Pages, posts, categories, media and users, header and footer globals, a layout builder, drafts, live preview, SEO, search, redirects and a Next.js front end | You need a marketing site, a blog or a portfolio |
| ecommerce | Products with variants, carts, addresses, orders and transactions from Payload’s ecommerce plugin, plus pages, categories, media and users | You’re building a store |
| with-cloudflare-d1 | The blank setup on Cloudflare Workers, with D1 for data and R2 for media | You’re deploying to Cloudflare |
| plugin | A plugin package with a development project to test it in | You’re writing a Payload plugin |
The blog template people search for is the website template. Its posts carry categories, drafts and SEO fields, and the admin has a “seed database” link that fills it with sample pages and posts. Keep in mind, seeding drops your current database first, so only run it on a new project (the website template’s README).
The ecommerce template runs on Payload’s ecommerce plugin, which is still in beta, and what the ecommerce plugin covers goes through it. The Cloudflare template deploys only on Cloudflare’s paid Workers plan and can’t resize images, because Workers don’t support sharp (the template’s README); where to host Payload compares it with the other routes. The website template’s SEO, search, redirects and form features come from Payload’s official plugins.
The repository also holds templates the picker doesn’t list, such as with-postgres and the with-vercel-* variants behind Payload’s one-click Vercel deploy. It also holds 13 examples on the 3.x branch, each a small project showing one feature, which you start with npx create-payload-app --example <name> (Payload’s examples). The localization and multi-tenant examples are the starting points for translated content and one admin serving several sites.
If you’re after a demo, there’s no public admin to log in to. The website template’s front end runs as a live demo on Vercel, and running the template locally gives you its admin. The “Schedule a Demo” button on Payload’s site books a sales call.
For example, an independent bookshop that wants its catalogue online starts on blank, because the catalogue is its content model. It’s the project for the rest of this tutorial.
Build your first Payload project, step by step
You’ll build the bookshop’s catalogue in six steps:
- Create the project
- Find your way around the project
- Start it and create the first admin user
- Add your first collection
- Add books in the admin panel
- Show the books on a page
1. Create the project
Run create-payload-app in the folder where you keep your projects:
npx create-payload-app@latestIt asks for the project name, the template, the database, the database’s connection string (with a local default you can accept) and the coding agent to install Payload’s skill for, in that order. Pick blank and SQLite for the bookshop.
The last question arrived in version 3.83.0 on 15 April 2026 (the 3.83.0 release notes). Choose Claude Code, Codex or Cursor and the CLI downloads Payload’s skill into the project and writes a CLAUDE.md or AGENTS.md at the root, so your coding assistant follows Payload’s own rules. Choose None to skip it. Payload’s agent skills covers what the skill gives an assistant.
You can answer everything up front instead:
npx create-payload-app@latest --name bookshop -t blank --db sqlite --db-accept-recommended --no-agent --use-pnpmThe CLI writes a .env file with DATABASE_URL pointing at the SQLite file and a generated PAYLOAD_SECRET, then installs the dependencies. Read the install line before you move on, because in our run the install failed and the CLI still finished with “Payload project successfully created!”
2. Find your way around the project
The blank template gives you a Next.js app with Payload inside it. Trimmed to the parts you’ll touch, our scaffold looked like this:
bookshop/
├── .env
├── docker-compose.yml
├── next.config.ts
├── package.json
└── src/
├── app/
│ ├── (frontend)/
│ │ ├── layout.tsx
│ │ └── page.tsx
│ └── (payload)/
│ ├── admin/
│ └── api/
├── collections/
│ ├── Media.ts
│ └── Users.ts
├── payload-types.ts
└── payload.config.tspayload.config.ts registers your collections, the database adapter, the rich text editor and plugins. The (payload) folder holds the admin panel and the REST and GraphQL routes, generated for you and not meant to be edited. Your own pages go in (frontend), and how Payload runs inside a Next.js app explains the two route groups. payload-types.ts holds TypeScript types generated from your config.
3. Start it and create the first admin user
If the CLI’s install failed, run pnpm install first. Then start the development server:
pnpm devOpen http://localhost:3000/admin. With no users in the database yet, Payload sends you to its create-first-user screen at /admin/create-first-user, where you set the email and password of the first admin (Payload’s admin panel docs). After that, the dashboard lists the template’s two collections, Users and Media.
4. Add your first collection
A collection is a set of documents with the same fields, and Payload builds the admin screens, the database table and the APIs from its config. Create src/collections/Books.ts:
import type { CollectionConfig } from 'payload'
export const Books: CollectionConfig = {
slug: 'books',
admin: {
useAsTitle: 'title',
},
access: {
read: () => true,
create: ({ req: { user } }) => Boolean(user),
update: ({ req: { user } }) => Boolean(user),
delete: ({ req: { user } }) => Boolean(user),
},
fields: [
{ name: 'title', type: 'text', required: true },
{ name: 'slug', type: 'text', required: true, unique: true },
{ name: 'author', type: 'text', required: true },
{ name: 'publishedOn', type: 'date' },
{
name: 'format',
type: 'select',
options: ['hardback', 'paperback', 'ebook'],
defaultValue: 'paperback',
},
{ name: 'cover', type: 'upload', relationTo: 'media' },
{ name: 'description', type: 'richText' },
],
}Then register it in src/payload.config.ts:
import { Books } from './collections/Books'
// inside buildConfig
collections: [Users, Media, Books],The access block is there because Payload’s default for every action is “signed-in users only”, so without a public read rule, visitors couldn’t read the catalogue through the API (Payload’s access control docs). The other three rules repeat the default, so anyone reading the file can see who may change a book.
On SQLite and Postgres, Payload pushes the new table to your database automatically in development (Payload’s migration docs). Before you deploy, you switch to migrations, and moving content and running payload migrate covers that step. Outside production, Payload also regenerates payload-types.ts when the config changes, and pnpm generate:types does it by hand.
5. Add books in the admin panel
Reload the admin and Books appears in the sidebar. The list view shows each book by its title, because of useAsTitle, and the edit view shows one input per field, with a text box for the author, a date picker, a dropdown for the format, an upload field for the cover and a rich text editor for the description.
For example, add a paperback with a cover image. The cover uploads into the Media collection, and the blank template’s Media collection asks for alt text on every image. Save, and the book is in your database.
The users collection is what lets you into the admin, because it has auth: true in its config. How Payload handles users and sign-in covers roles and access beyond this.
6. Show the books on a page
Your pages read content through Payload’s Local API, which calls the database directly from server code in the same app. Create src/app/(frontend)/books/page.tsx:
import { getPayload } from 'payload'
import config from '@payload-config'
export default async function BooksPage() {
const payload = await getPayload({ config })
const { docs: books } = await payload.find({
collection: 'books',
sort: 'title',
limit: 50,
})
return (
<main>
<h1>Books</h1>
<ul>
{books.map((book) => (
<li key={book.id}>
{book.title} by {book.author}
</li>
))}
</ul>
</main>
)
}Open http://localhost:3000/books and the list renders from your database. The same books are available over REST at /api/books, which is the route a separate front end or a mobile app would use (Payload’s REST API docs).
The Local API skips access rules by default, because overrideAccess is true on every Local API call (Payload’s Local API docs). The public read rule is what lets visitors reach /api/books. When the bookshop grows, whether to keep one app or split the site out, and how to refresh pages after an edit, are covered in Payload and Next.js.
How we start a new Payload project
For a one-off project, create-payload-app is the right start. As of October 2026, we manage 29 Payload codebases, all built on Next.js, and every client project starts as a clone of our project template (v2.3.2, 4 November 2026), never from create-payload-app or one of Payload’s templates. One setup command then creates each app’s local settings from the template’s examples, generates fresh secrets for that project, creates a local Postgres database, stamps the project with the template release it came from and links it back to the template. It finishes with a short checklist of the values a person still pastes in by hand, such as the settings for third-party accounts.
A fresh clone already has a Payload admin, two front ends that read the same content (one through GraphQL, one through REST), an Expo mobile app, and shared packages for UI, types, design tokens and an API client, and each build uses the ones it needs. In development, a seed creates the first tenant and a default user, so the admin opens with something in it. The official plugins and our own are configured. For AI-powered development, the repository carries an agent guide at the root, the project’s own architecture docs, a written, spec-driven workflow for changes, and a copy of Payload’s documentation, so assistants read the real docs. Our coding agents also load Payload’s own payload skill, the skill create-payload-app offers to install in step 1.
Adding a collection works differently from the bookshop’s too. A project’s own collections, blocks, globals, plugins, seed and theme live in a folder of their own, and the shared core is never edited in place. The build refuses a collection that leaves any access action to Payload’s default, so every collection states who can read, create, update and delete, as the bookshop’s does. A new collection ships with its database migration in the same change, and it’s scoped to its tenant automatically.
The template ships numbered releases, and a project takes one with a single command. The command merges the release, then runs the install, the type check, the build, the tests and a check that nothing outside the project’s own folder changed, stopping at the first failure. Because each project’s work lives in its own folder, a release merges cleanly, much as a WordPress child theme takes updates to its parent. If you’d rather start from a team’s template than a blank app, our Payload development work starts every project this way.
What to do when the first run fails
The failures below are listed by the message you’ll see, starting with the two our own scaffold hit.
“packages field missing or empty” during the install
Your pnpm is older than the template expects. The blank template’s workspace file uses allowBuilds, added in pnpm 10.26.0, and pnpm 9 rejects the file. Upgrade pnpm, then run pnpm install again.
Node.js below Payload’s range
Payload 3.93.0 declares ^22.23.4 || >=24.22.1 in its engines field. If node -v prints anything lower, upgrade Node before installing, even where a guide lists 20.9.0.
Error: cannot connect to Postgres or cannot connect to SQLite
Payload couldn’t open the database in DATABASE_URL. For Postgres or MongoDB, check the server is running and the connection string in .env matches it. The template’s docker-compose.yml starts the app with a MongoDB container, and a commented-out Postgres service you can switch on. For SQLite, check the file path in DATABASE_URL.
Error: missing secret key
Payload stops at startup with Error: missing secret key. A secret key is needed to secure Payload. when PAYLOAD_SECRET is empty. create-payload-app writes one for you, so this usually means the .env file wasn’t created or wasn’t loaded. Set a long random string and restart.
A Next.js version Payload doesn’t support
@payloadcms/next lists the Next.js releases it accepts as a peer dependency, so your package manager flags a version outside that range. Upgrading Next.js and Payload together covers how to read the range.
New fields missing from your types
If your editor doesn’t know a field you just added, run pnpm generate:types to rebuild payload-types.ts.
A custom admin component doesn’t show
Payload finds custom admin components through an import map it regenerates at startup. If one doesn’t appear, run pnpm payload generate:importmap and restart (Payload’s custom components docs).
Where to learn Payload next
Payload’s own material is the place to go next, because it tracks the release you’ve installed.
- The docs. Payload’s documentation covers 3.x, with separate docs for the 4.0 beta. For AI tools, llms.txt points to a single-file version of each.
- Guides and tutorials. Payload’s guides list 21 as of 10 November 2026, from collections and globals to rich text, blocks, the Local API, SEO and storage.
- GitHub. The Payload repository is MIT licensed and had 45,747 stars on 10 November 2026. It holds the templates, the examples, the releases and Discussions.
- The community. Payload’s Discord, its Community Help archive, its YouTube channel and the r/PayloadCMS subreddit.
- Courses. Payload doesn’t offer an official course as of 10 November 2026, and a GitHub discussion asking for one has been open since March 2024. Community courses and video series exist. Check which version each teaches, because anything made before Payload 3.0 covers Payload 2 or earlier. For example, a course whose config imports
buildConfigfrompayload/configteaches Payload 2, because Payload 3 imports it frompayload.
Once the bookshop works, this order follows the questions a first project raises next:
