Home › Payload CMS › Payload CMS 3 + Next.js Cursor rules
Payload CMS 3 + Next.js Cursor rules
Cursor rules for Payload CMS 3 inside Next.js: collections and fields config, access control, hooks, Local API, generated types and migrations.
CursorPayload CMS
How to use
Save this as .cursor/rules/payload.mdc in your repository root, commit it, and your agent will pick it up automatically. Edit the commands to match your project.
Note: Review and test before use. Provided as is, without warranty. See Terms.
.cursor/rules/payload.mdcDownload ---
description: Payload CMS conventions
globs: ["src/collections/**/*.ts", "src/globals/**/*.ts", "src/payload.config.ts", "src/app/**/*.{ts,tsx}"]
alwaysApply: false
---
# Payload CMS 3
- Payload runs inside the Next.js app (`src/app/(payload)` admin, `src/app/(frontend)` site). Config in `src/payload.config.ts`; one file per collection in `src/collections/` and per global in `src/globals/`.
- Every collection defines `slug`, `fields`, `admin.useAsTitle` and explicit `access` (`read`, `create`, `update`, `delete`). Never leave write access open; default to `({ req: { user } }) => Boolean(user)` or a role check.
- Field-level `access` for sensitive fields; `hidden: true` for internal ones.
- After changing collections or fields, run `npm run generate:types` (writes `payload-types.ts`) and import types from there. Don't hand-write document types.
- Server code (RSC, route handlers, server actions) reads data with the Local API: `const payload = await getPayload({ config })`, then `payload.find({ collection, where, depth, limit })`. Pass `overrideAccess: false` and `user` when acting for a user; the default bypasses access control.
- Keep `depth` low (0-2) and select only needed fields for performance.
- Hooks (`beforeChange`, `afterChange`, `beforeValidate`) stay small and idempotent; pass `req` to nested Local API calls so they share the transaction.
- Postgres/SQLite adapters: create migrations with `npx payload migrate:create` and run `npx payload migrate`; don't rely on dev push mode in production.
- Rich text uses the Lexical editor; render with the official `RichText` converter, not `dangerouslySetInnerHTML`.
- Uploads: configure `upload` collections with `mimeTypes` and image sizes; store files in the configured storage adapter, not the repo.
## Done when
`npm run generate:types`, `npx tsc --noEmit` and `npm run build` pass, and new access rules are covered by a test or manual check as a non-admin user.