collections

star 0

This skill should be used when the user asks to "create a Payload collection", "define a CollectionConfig", "set up an auth collection", "build an upload collection", "add drafts/versions", "configure admin panel for a collection", "enable live preview", "set defaultColumns", or needs to model any content type in PayloadCMS v3.

Agents-Store By Agents-Store schedule Updated 5/17/2026

name: collections description: This skill should be used when the user asks to "create a Payload collection", "define a CollectionConfig", "set up an auth collection", "build an upload collection", "add drafts/versions", "configure admin panel for a collection", "enable live preview", "set defaultColumns", or needs to model any content type in PayloadCMS v3.

PayloadCMS — Collections

Collections are the building blocks of every Payload app. Each collection is a typed document store, a REST/GraphQL endpoint, an admin panel page, and an auto-generated TypeScript type — all from one config object.

Minimal Collection

import type { CollectionConfig } from 'payload'

export const Posts: CollectionConfig = {
  slug: 'posts',
  admin: {
    useAsTitle: 'title',
    defaultColumns: ['title', 'author', 'status', 'updatedAt'],
  },
  fields: [
    { name: 'title', type: 'text', required: true },
    { name: 'slug', type: 'text', unique: true, index: true },
    { name: 'content', type: 'richText' },
    { name: 'author', type: 'relationship', relationTo: 'users' },
  ],
  timestamps: true,
}

Register it in payload.config.ts:

collections: [Posts, Users, Media],

Re-run pnpm generate:types after every collection change.

CollectionConfig Reference

Property Type Purpose
slug string Unique key. Becomes /api/<slug>, the table/collection name, and the type name (Post for slug posts). Use kebab-case plural.
labels { singular, plural } Override singular/plural labels in the admin UI. Defaults to inflected slug.
fields Field[] Document schema. See the fields skill.
timestamps boolean Default true. Adds createdAt / updatedAt.
defaultSort string Initial sort for list view, e.g. '-createdAt'.
admin object Admin panel behavior (see below).
access object Permission rules. See the access-control skill.
hooks object Lifecycle callbacks. See the hooks skill.
auth boolean | AuthConfig Turn this collection into a login source.
upload boolean | UploadConfig Turn this collection into a file store.
versions boolean | VersionsConfig Enable version history / drafts.
endpoints Endpoint[] Custom API routes scoped to this collection.
indexes object[] Compound indexes across multiple fields.
disableDuplicate boolean Hide the "Duplicate" admin action.

admin Options

admin: {
  useAsTitle: 'title',                  // Field shown as document label everywhere
  defaultColumns: ['title', 'author'],  // Columns in list view
  group: 'Content',                     // Sidebar grouping
  description: 'Blog posts and articles',
  listSearchableFields: ['title', 'excerpt'],
  pagination: { defaultLimit: 25, limits: [10, 25, 50, 100] },
  preview: (doc, { req }) =>            // "Preview" button URL
    `${process.env.NEXT_PUBLIC_SITE_URL}/preview?slug=${doc.slug}&secret=${process.env.PREVIEW_SECRET}`,
  livePreview: {
    url: ({ data }) =>
      `${process.env.NEXT_PUBLIC_SITE_URL}/posts/${data.slug}?draft=true`,
    breakpoints: [
      { name: 'mobile', width: 375, height: 667, label: 'Mobile' },
      { name: 'tablet', width: 768, height: 1024, label: 'Tablet' },
      { name: 'desktop', width: 1440, height: 900, label: 'Desktop' },
    ],
  },
  components: {                         // Custom React components (path strings)
    views: { Edit: { Default: '@/components/CustomEditView' } },
    BeforeDashboard: ['@/components/Banner'],
  },
}

Auth Collections

Setting auth: true enables login on the collection. The most common is Users:

export const Users: CollectionConfig = {
  slug: 'users',
  auth: {
    tokenExpiration: 7200,          // 2h JWT
    verify: true,                   // Email verification flow
    maxLoginAttempts: 5,
    lockTime: 600 * 1000,           // 10 min lockout
    cookies: { secure: true, sameSite: 'Strict' },
    useAPIKey: false,
  },
  admin: { useAsTitle: 'email' },
  fields: [
    {
      name: 'roles',
      type: 'select',
      hasMany: true,
      saveToJWT: true,              // Include in JWT so access fns can read it
      options: [
        { label: 'Admin', value: 'admin' },
        { label: 'Editor', value: 'editor' },
        { label: 'User', value: 'user' },
      ],
      defaultValue: ['user'],
      required: true,
    },
    { name: 'fullName', type: 'text' },
  ],
}

Payload auto-generates email, password, resetPasswordToken, loginAttempts, lockUntil, etc. Set admin.user: 'users' in payload.config.ts so the admin panel signs in against this collection.

Upload Collections

Setting upload: true (or a config object) makes the collection store files:

export const Media: CollectionConfig = {
  slug: 'media',
  upload: {
    staticDir: path.resolve(dirname, '../media'),  // Local FS (dev only)
    mimeTypes: ['image/*', 'application/pdf'],
    imageSizes: [
      { name: 'thumbnail', width: 400, height: 300, position: 'centre' },
      { name: 'card', width: 768, height: 1024, position: 'centre' },
      { name: 'hero', width: 1920 },              // Height auto
    ],
    adminThumbnail: 'thumbnail',
    focalPoint: true,
    crop: true,
  },
  fields: [
    { name: 'alt', type: 'text', required: true },
    { name: 'caption', type: 'text' },
  ],
}

Payload auto-adds filename, mimeType, filesize, width, height, url, and per-size variants. For production, swap staticDir for a storage adapter (S3, R2, Vercel Blob) — see the adapters skill.

Versions & Drafts

export const Pages: CollectionConfig = {
  slug: 'pages',
  versions: {
    drafts: {
      autosave: { interval: 100 },   // ms between autosaves
      schedulePublish: true,          // Allow scheduling future publish
      validate: true,
    },
    maxPerDoc: 50,                   // Keep last 50 versions
  },
  fields: [/* ... */],
}

A _status field ('draft' | 'published') is added automatically. Querying drafts requires draft: true:

const drafts = await payload.find({ collection: 'pages', draft: true, where: { _status: { equals: 'draft' } } })

Custom Endpoints

Add bespoke routes scoped to the collection:

endpoints: [
  {
    path: '/popular',
    method: 'get',
    handler: async (req) => {
      const posts = await req.payload.find({
        collection: 'posts',
        sort: '-views',
        limit: 5,
        depth: 1,
      })
      return Response.json(posts)
    },
  },
],

Mounted at /api/posts/popular.

Compound Indexes

indexes: [
  { fields: ['author', 'status'], unique: false },
  { fields: ['slug', 'locale'], unique: true },
],

Improves query performance for multi-field where clauses.

Project Structure

src/
├── collections/
│   ├── Users.ts        # Auth collection
│   ├── Media.ts        # Upload collection
│   ├── Posts.ts        # Content with versions+drafts
│   └── index.ts        # Optional barrel re-export
├── payload.config.ts

Keep each collection in its own file. Group related access functions, hooks, and helpers in sibling files like Posts.access.ts, Posts.hooks.ts.

**User**: "I need a Tutorials collection with drafts, autosave, live preview, and admin grouping under 'Learning'."

Solution:

export const Tutorials: CollectionConfig = {
  slug: 'tutorials',
  admin: {
    group: 'Learning',
    useAsTitle: 'title',
    defaultColumns: ['title', 'difficulty', 'updatedAt', '_status'],
    livePreview: {
      url: ({ data }) => `${process.env.NEXT_PUBLIC_SITE_URL}/tutorials/${data.slug}?draft=true`,
    },
  },
  versions: { drafts: { autosave: { interval: 800 }, schedulePublish: true } },
  fields: [
    { name: 'title', type: 'text', required: true },
    { name: 'slug', type: 'text', unique: true, index: true },
    { name: 'difficulty', type: 'select', options: ['beginner', 'intermediate', 'advanced'] },
    { name: 'body', type: 'richText' },
  ],
}

After your collections are defined, the next likely topics are fields (full field reference), access-control (who can do what), and hooks (lifecycle automation).

Install via CLI
npx skills add https://github.com/Agents-Store/claude-plugins --skill collections
Repository Details
star Stars 0
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator
Agents-Store
Agents-Store Explore all skills →