Payload Collections: Build Your First Collection
In this video we build collections from scratch.
You've got Payload CMS running, and you've got an admin panel with basically nothing in it. Let's fix that. A collection is where your content lives, and by the end of this tutorial you'll have a collection you can log into, edit, and control who can access.
This builds on the setup post, where we install Payload and go through the config file. If you don't have a Payload project running, or you don't know where to start, start there and come back to this one.
The exact version I'm on is 3.88.0. Payload 4 is on the way as I'm writing this, so expect an update shortly after that releases.
What is a collection in Payload CMS?
A collection is a group of documents that share the same structure. Some examples include posts, pages, products, and users. You can have as many as you need, and each one gets its own card in your admin panel.
When you define a collection, you automatically get three ways to read it: the Local API, a REST API, and a GraphQL API. You don't write any of them. You can see the JSON for any single document in its API tab in the admin panel.
How to create your first collection
To create a collection, I'll build a posts collection. Create a folder called collections, and inside it a file called Posts.ts. You don't have to organise it this way, but a collection per file is what keeps your file structure readable.
In Posts.ts, import the CollectionConfig type from payload. Then export a constant (I'll call mine Posts) and assign it the CollectionConfig type. It needs a slug, and a fields array, which will just have our title text field for now.
1import type { CollectionConfig } from 'payload'23export const Posts: CollectionConfig = {4 slug: 'posts',5 fields: [{ name: 'title', type: 'text' }],6}
You'll want to keep the slug the same as the collection name.
The fields array is what your documents actually hold. I've put one text field in for now. We'll talk about fields in more detail in the next post.
Now you can open up your payload.config.ts and import it into the collections array.
1import { Posts } from '@/collections/Posts'23// inside buildConfig4collections: [Users, Media, Posts],
Save that, and Posts shows up in your admin UI.
Admin options: how your collection looks in the admin panel
Everything from here on is optional, but these options can help make your collections more useful. The first group is admin, which controls how the collection behaves in the admin panel.
useAsTitle is a common admin option. It tells Payload which field labels the document everywhere it's used, like in the list view, in the breadcrumb, and inside any relationship field using this collection.
Without it, every row in the list view is an ID. That's the default, and it's the single most common thing people complain about with their first Payload project. Set useAsTitle to title and that same list becomes readable.
There is one catch. It has to be a top-level field. You can't use a group or an array for it, nor can you use a virtual field.
Next is defaultColumns, which sets what the list view opens with. That way you decide what an editor sees first, instead of taking whatever order the fields happen to be in.
group puts related collections under one heading in your sidebar and admin homepage. If you've got categories and tags and topics, group them under something like Meta and your sidebar becomes more easily accessible.
If you set group to false the collection disappears from the navigation entirely, but the API still works. That's useful for a collection your editors never need to open.
description puts a line of help text under the collection title. It's a small thing, but it can be helpful when you have a lot of similar collections.
The last one I'll talk about is listSearchableFields, which controls what the search box in the list view searches. Be sure to set it if you want to change the default behavior.
1admin: {2 useAsTitle: 'title',3 defaultColumns: ['title', 'createdAt'],4 group: 'Content',5 description: 'Blog posts, shown newest first.',6 listSearchableFields: ['title'],7},
Access control: who can do what
The access option is where you decide who can do what in a collection.
There are five basic functions: read, create, update, delete, and admin. Each one can return true, false, or a query.
read returning true means anybody can read it. false means nobody can read it.
The query version is where this gets powerful. Instead of answering yes or no, you return a filter, and Payload applies it to every request.
So let's say posts should only be readable by the author who wrote them. We'll add the access option, and within the object, assign a function to read. The function takes some arguments, which we can use to pull out our request, which holds our user. If there's no user, we return false. Otherwise, we return a query that returns documents only if the user's id is equal to the author's id.
1access: {2 read: ({ req: { user } }) => {3 if (!user) return false4 return { author: { equals: user.id } }5 },6},
That's a where clause Payload merges into the query, so an author can't see anybody else's posts.
Posts doesn't have an author field yet. We add it as a relationship field in the fields post.
We'll talk more about roles and full role-based access control in a future tutorial.
Auth: the collection people log in with
The auth option is short. Add auth: true to a collection and it becomes the collection people log in with. That's it in its most basic form.
Your Users collection already has it, which is why Payload asked you to create a user the first time you started it up.
There's much more to it, like token expiry, email verification, lockouts after failed attempts, and API keys. Authentication gets its own tutorial, so we'll come back to those later.
Upload: turning a collection into a media collection
The upload option turns a regular collection into a media collection.
Set upload to true and you're done. The collection takes files now, and you get a file picker in the admin panel.
You'll almost always want the object form instead, though, because that's where the useful stuff is.
mimeTypesis a whitelist. Passimage/*and it only takes images. Pass webp and png specifically and it only takes those two. And this isn't just for images. You can restrict a collection to PDFs the same way.imageSizesgenerates variants on upload, so one file gives you a thumbnail, a card, and a hero. This needssharpinstalled. If you skipped that in the setup post, this won't work.formatOptionsconverts files as they come in. Set the format to webp and everything that is uploaded in this collection gets converted.adminThumbnailcontrols what you see in the dashboard. Pass a string matching one of yourimageSizesand it uses that size. Or pass a function, which is what I prefer, and build the path yourself.
1adminThumbnail: ({ doc }) => `https://cdn.example.com/${doc.filename}`,
The last option we'll discuss is displayPreview, which you can set to false when you don't want a preview before the upload happens. Handy for documents, less so for images.
Uploads will need their own tutorial, but for now you've got a media collection up and running.
Three more collection options worth knowing
There are three more collection options worth knowing about.
defaultSortsets which field the list view sorts by, and a minus in front reverses it. This makes it easy to change the default sorting behavior in a way that makes sense for you.defaultPopulatelimits which fields come back when this collection gets pulled in through a relationship. Without it, every relationship populates the entire document. Set it to just the slug and the title, and you stop passing whole posts to a page that only needs a link and a label.versions, with drafts turned on, lets you edit documents without publishing the document. We'll discuss this more when we get to live preview and draft mode.
Of course there's more to collection configs than this, and we'll get to some of it in future tutorials, like hooks, custom endpoints, and bulk operations.
What you've built
And that's all there is to it! You've got a real collection, an admin panel you configured, an access rule, and a media collection ready for files.
If you'd like a sequential set of videos covering a full Payload setup, my course Payload Essentials goes further: https://nlvcodes.com/courses/payload-essentials