Skip to main content

payload

Use when working with Payload projects (payload.config.ts, collections, fields, hooks, access control, Payload API). Use when debugging validation errors, security issues, relationship queries, transactions, or hook behavior.

Quellinformationen

Repository
payloadcms/skills
Letzte Quellaktivität
7. Juli 2026 um 16:51
Erkannte Sprache von SKILL.md
Englisch
Sterne
163
Forks
5

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
13 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
payload
description
Use when working with Payload projects (payload.config.ts, collections, fields, hooks, access control, Payload API). Use when debugging validation errors, security issues, relationship queries, transactions, or hook behavior.
# Payload Application Development Payload is a Next.js native CMS with TypeScript-first architecture, providing admin panel, database management, REST/GraphQL APIs, authentication, and file storage. ## Quick Reference | Task | Solution | Details | | ------------------------ | -------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | Auto-generate slugs | `slugField()` | [FIELDS.md#slug-field-helper](reference/FIELDS.md#slug-field-helper) | | Restrict content by user | Access control with query | [ACCESS-CONTROL.md#row-level-security-with-complex-queries](reference/ACCESS-CONTROL.md#row-level-security-with-complex-queries) | | Local API user ops | `user` + `overrideAccess: false` | [QUERIES.md#access-control-in-local-api](reference/QUERIES.md#access-control-in-local-api) | | Draft/publish workflow | `versions: { drafts: true }` | [COLLECTIONS.md#versioning--drafts](reference/COLLECTIONS.md#versioning--drafts) | | Computed fields | `virtual: true` with **field-level** `hooks.afterRead` returning the value | [FIELDS.md#virtual-fields](reference/FIELDS.md#virtual-fields) | | Conditional fields | `admin.condition` | [FIELDS.md#conditional-fields](reference/FIELDS.md#conditional-fields) | | Custom field validation | `validate` function | [FIELDS.md#validation](reference/FIELDS.md#validation) | | Filter relationship list | `filterOptions` on field | [FIELDS.md#relationship](reference/FIELDS.md#relationship) | | Select specific fields | `select` parameter | [QUERIES.md#field-selection](reference/QUERIES.md#field-selection) | | Auto-set author/dates | beforeChange hook | [HOOKS.md#collection-hooks](reference/HOOKS.md#collection-hooks) | | Prevent hook loops | `req.context` check | [HOOKS.md#context](reference/HOOKS.md#context) | | Cascading deletes | beforeDelete hook | [HOOKS.md#collection-hooks](reference/HOOKS.md#collection-hooks) | | Geospatial queries | `point` field with `near`/`within` | [FIELDS.md#point-geolocation](reference/FIELDS.md#point-geolocation) | | Reverse relationships | `join` field type | [FIELDS.md#join-fields](reference/FIELDS.md#join-fields) | | Next.js revalidation | Context control in afterChange | [HOOKS.md#nextjs-revalidation-with-context-control](reference/HOOKS.md#nextjs-revalidation-with-context-control) | | Query by relationship | Nested property syntax | [QUERIES.md#nested-properties](reference/QUERIES.md#nested-properties) | | Complex queries | AND/OR logic | [QUERIES.md#andor-logic](reference/QUERIES.md#andor-logic) | | Transactions | Pass `req` to operations | [ADAPTERS.md#threading-req-through-operations](reference/ADAPTERS.md#threading-req-through-operations) | | Background jobs | Jobs queue with tasks | [ADVANCED.md#jobs-queue](reference/ADVANCED.md#jobs-queue) | | Custom API routes | Collection custom endpoints | [ADVANCED.md#custom-endpoints](reference/ADVANCED.md#custom-endpoints) | | Cloud storage | Storage adapter plugins | [ADAPTERS.md#storage-adapters](reference/ADAPTERS.md#storage-adapters) | | Multi-language | `localization` config + `localized: true` | [ADVANCED.md#localization](reference/ADVANCED.md#localization) | | Create plugin | `(options) => (config) => Config` | [PLUGIN-DEVELOPMENT.md#plugin-architecture](reference/PLUGIN-DEVELOPMENT.md#plugin-architecture) | | Plugin package setup | Package structure with SWC | [PLUGIN-DEVELOPMENT.md#plugin-package-structure](reference/PLUGIN-DEVELOPMENT.md#plugin-package-structure) | | Add fields to collection | Map collections, spread fields | [PLUGIN-DEVELOPMENT.md#adding-fields-to-collections](reference/PLUGIN-DEVELOPMENT.md#adding-fields-to-collections) | | Plugin hooks | Preserve existing hooks in array | [PLUGIN-DEVELOPMENT.md#adding-hooks](reference/PLUGIN-DEVELOPMENT.md#adding-hooks) | | Check field type | Type guard functions | [FIELD-TYPE-GUARDS.md](reference/FIELD-TYPE-GUARDS.md) | ## Quick Start ```bash npx create-payload-app@latest my-app cd my-app pnpm dev ``` ### Minimal Config ```ts import { buildConfig } from 'payload' import { mongooseAdapter } from '@payloadcms/db-mongodb' import { lexicalEditor } from '@payloadcms/richtext-lexical' import path from 'path' import { fileURLToPath } from 'url' const filename = fileURLToPath(import.meta.url) const dirname = path.dirname(filename) export default buildConfig({ admin: { user: 'users', importMap: { baseDir: path.resolve(dirname), }, }, collections: [Users, Media], editor: lexicalEditor(), secret: process.env.PAYLOAD_SECRET, typescript: { outputFile: path.resolve(dirname, 'payload-types.ts'), }, db: mongooseAdapter({ url: process.env.DATABASE_URL, }), }) ``` ## Essential Patterns ### Defaults & Conventions Apply these defaults when modeling content unless there's a clear reason not to: - **Enable drafts/versions by default:** `versions: { drafts: true }`. This is the recommended starting point for any content collection. It auto-injects a `_status` field (`draft` / `published` / `changed`) — **don't add your own `status` field**, it's redundant. Only skip versions for collections that have no publish/draft lifecycle (e.g. internal join tables, settings). - **Use `slugField()` for all slugs** instead of hand-rolling `{ name: 'slug', type: 'text', unique: true }`. It auto-generates the slug from the title, adds a regenerate toggle, and handles uniqueness/indexing for you. It defaults to generating from a `title` field — if the collection has no `title`, pass the source field: `slugField({ useAsSlug: 'name' })`. - **`position: 'sidebar'` is for short, at-a-glance fields** — status, category, author, publish date. Avoid it for long fields that need horizontal space to be usable (description, rich text content, long text). Those belong in the main document area. ### Basic Collection ```ts import type { CollectionConfig } from 'payload' import { slugField } from 'payload' export const Posts: CollectionConfig = { slug: 'posts', admin: { useAsTitle: 'title', // _status (from versions.drafts) shows the draft/published state — no custom status field needed defaultColumns: ['title', 'author', '_status', 'createdAt'], }, versions: { drafts: true, }, fields: [ { name: 'title', type: 'text', required: true }, slugField(), // auto-generates from `title`, unique + indexed, sidebar position { name: 'content', type: 'richText' }, // long field — stays in the main area, not the sidebar // short, at-a-glance field — good sidebar candidate { name: 'author', type: 'relationship', relationTo: 'users', admin: { position: 'sidebar' } }, ], timestamps: true, } ``` For more collection patterns (auth, upload, drafts, live preview), see [COLLECTIONS.md](reference/COLLECTIONS.md). ### Common Fields ```ts // Text field { name: 'title', type: 'text', required: true } // Relationship { name: 'author', type: 'relationship', relationTo: 'users', required: true } // Rich text { name: 'content', type: 'richText', required: true } // Slug — use the helper instead of a hand-rolled text field slugField() // Select (for genuine taxonomy — NOT publish state; use versions.drafts + _status for that) { name: 'category', type: 'select', options: ['news', 'tutorial', 'opinion'] } // Upload { name: 'image', type: 'upload', relationTo: 'media' } ``` For all field types (array, blocks, point, join, virtual, conditional, etc.), see [FIELDS.md](reference/FIELDS.md). ### Hook Example Hooks live at one of two levels and they are not interchangeable. **Collection hooks** receive `{ doc, data, req, operation, ... }` and act on the whole document. **Field hooks** live inside an individual field's `hooks` object, receive `{ value, siblingData, ... }`, and **return the new value** for that field. Computed/virtual fields, per-field formatters, and per-field access masking are field hooks; cross-field business logic is a collection hook. ```ts // Collection-level: business logic across the document export const Posts: CollectionConfig = { slug: 'posts', hooks: { beforeChange: [ async ({ data, operation }) => { if (operation === 'create') { data.slug = slugify(data.title) } return data }, ], }, fields: [{ name: 'title', type: 'text' }], } // Field-level: compute / format a single field's value (virtual fields use this) export const Users: CollectionConfig = { slug: 'users', fields: [ { name: 'firstName', type: 'text' }, { name: 'lastName', type: 'text' }, { name: 'fullName', type: 'text', virtual: true, hooks: { afterRead: [({ siblingData }) => `${siblingData.firstName} ${siblingData.lastName}`], }, }, ], } ``` When asked to "compute a field" or "populate a field's value in a hook", use a **field-level** hook on that field — never a collection-level `afterRead` that mutates `doc`. For all hook patterns, see [HOOKS.md](reference/HOOKS.md). For access control, see [ACCESS-CONTROL.md](reference/ACCESS-CONTROL.md). ### Access Control with Type Safety ```ts import type { Access } from 'payload' import type { User } from '@/payload-types' // Type-safe access control export const adminOnly: Access = ({ req }) => { const user = req.user as User return user?.roles?.includes('admin') || false } // Row-level access control export const ownPostsOnly: Access = ({ req }) => { const user = req.user as User if (!user) return false if (user.roles?.includes('admin')) return true return { author: { equals: user.id }, } } ``` ### Query Example ```ts // Local API const posts = await payload.find({ collection: 'posts', where: { status: { equals: 'published' }, 'author.name': { contains: 'john' }, }, depth: 2, limit: 10, sort: '-createdAt', }) // Query with populated relationships const post = await payload.findByID({ collection: 'posts', id: '123', depth: 2, // Populates relationships (default is 2) }) // Returns: { author: { id: "user123", name: "John" } } // Without depth, relationships return IDs only const post = await payload.findByID({ collection: 'posts', id: '123', depth: 0, }) // Returns: { author: "user123" } ``` For all query operators and REST/GraphQL examples, see [QUERIES.md](reference/QUERIES.md). ### Getting Payload Instance ```ts // In API routes (Next.js) import { getPayload } from 'payload' import config from '@payload-config' export async function GET() { const payload = await getPayload({ config }) const posts = await payload.find({ collection: 'posts', }) return Response.json(posts)
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen