--- title: Collections description: Collection configurations and patterns tags: [payload, collections, auth, upload, drafts] --- # Payload CMS Collections ## Basic Collection ```typescript import type { CollectionConfig } from 'payload' export const Posts: CollectionConfig = { slug: 'posts', admin: { useAsTitle: 'title', defaultColumns: ['title', 'author', 'status', 'createdAt'], }, 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, } ``` ## Auth Collection with RBAC ```typescript export const Users: CollectionConfig = { slug: 'users', auth: true, fields: [ { name: 'roles', type: 'select', hasMany: true, options: ['admin', 'editor', 'user'], defaultValue: ['user'], required: true, saveToJWT: true, // Include in JWT for fast access checks access: { update: ({ req: { user } }) => user?.roles?.includes('admin'), }, }, ], } ``` ## Upload Collection ```typescript export const Media: CollectionConfig = { slug: 'media', upload: { staticDir: 'media', mimeTypes: ['image/*'], imageSizes: [ { name: 'thumbnail', width: 400, height: 300, position: 'centre', }, { name: 'card', width: 768, height: 1024, }, ], adminThumbnail: 'thumbnail', focalPoint: true, crop: true, }, access: { read: () => true, }, fields: [ { name: 'alt', type: 'text', required: true, }, ], } ``` ## Versioning & Drafts ```typescript export const Pages: CollectionConfig = { slug: 'pages', versions: { drafts: { autosave: true, schedulePublish: true, validate: false, // Don't validate drafts }, maxPerDoc: 100, }, access: { read: ({ req: { user } }) => { // Public sees only published if (!user) return { _status: { equals: 'published' } } // Authenticated sees all return true }, }, } ``` ### Draft API Usage ```typescript // Create draft await payload.create({ collection: 'posts', data: { title: 'Draft Post' }, draft: true, // Skips required field validation }) // Read with drafts const page = await payload.findByID({ collection: 'pages', id: '123', draft: true, // Returns draft version if exists }) ``` ## Globals Globals are single-instance documents (not collections). ```typescript import type { GlobalConfig } from 'payload' export const Header: GlobalConfig = { slug: 'header', label: 'Header', admin: { group: 'Settings', }, fields: [ { name: 'logo', type: 'upload', relationTo: 'media', required: true, }, { name: 'nav', type: 'array', maxRows: 8, fields: [ { name: 'link', type: 'relationship', relationTo: 'pages', }, { name: 'label', type: 'text', }, ], }, ], } ```