Payload Concepts

Payload is based around a small and intuitive set of concepts. Before starting to work with Payload, it's a good idea to familiarize yourself with the following:

Config

By default, the Payload config lives in the root folder of your code and is named payload.config.js (payload.config.ts if you're using TypeScript), but you can customize its name and where you store it. You can write full functions and even full React components right into your config.

Collections

Collections define the shape of your data as well as all functionalities attached to that data. They will contain or many "documents", all corresponding with the same fields and functionalities that you define.

They can represent anything you can store in a database - for example - pages, posts, users, people, orders, categories, events, customers, transactions, and anything else your app needs.

Globals

Globals are in many ways similar to Collections, but there is only ever one instance of a Global, whereas Collections can contain many documents.

Fields

Payload comes with many different field types that give you a ton of flexibility while designing your API. Each Field type has its own potential properties that allow you to customize how they work.

Hooks

Hooks are an extremely powerful concept and are central to extending and customizing your app. Payload provides a wide variety of hooks which you can utilize. For example, imagine if you'd like to send an email every time a document is created in your Orders collection. To do so, you can add an afterChange hook function to your Orders collection that receives the Order data and allows you to send an email accordingly.

There are many more potential reasons to use Hooks. For more, visit the Hooks documentation.

Access Control

Access Control is extremely powerful but easy and intuitive to manage. You can easily define your own full-blown RBAC (role-based access control) or any other access control pattern that your scenario requires. No conventions or structure is forced on you whatsoever.

For more, visit the Access Control documentation.

Depth

You can specify population depth via query parameter in the REST API and by an option in the local API. Depth has no effect in the GraphQL API, because there, depth is based on the shape of your queries.

For example, let's look the following Collections: departments, users, posts

// type: 'relationship' fields are equal to 1 depth level
{
slug: 'posts',
fields: [
{
name: 'title',
type: 'text',
},
{
name: 'author',
label: 'Post Author',
type: 'relationship',
relationTo: 'users',
}
]
}
{
slug: 'users',
fields: [
{
name: 'email',
type: 'email',
},
{
name: 'department'
type: 'relationship',
relationTo: 'departments'
}
]
}
{
slug: 'departments',
fields: [
{
name: 'name'
type: 'text',
}
]
}

If you were to query the Posts endpoint at, say, http://localhost:3000/api/posts?depth=1, you will retrieve Posts with populations one level deep. A returned result may look like the following:

// ?depth=1
{
id: '5ae8f9bde69e394e717c8832',
title: 'This post sucks',
author: {
id: '5f7dd05cd50d4005f8bcab17',
email: 'spiderman@superheroes.gov',
department: '5e3ca05cd50d4005f8bdab15'
}
}

Notice how the user.author is fully populated, but user.author.department is left as a document ID? That's because the User collection counted as the first level of depth and got populated—but then prevented any further populations from taking place.

To populate user.author.department in it's entirety you could specify ?depth=2 or higher.

// ?depth=2
{
id: '5ae8f9bde69e394e717c8832',
title: 'This post sucks',
author: {
id: '5f7dd05cd50d4005f8bcab17',
email: 'spiderman@superheroes.gov',
department: {
id: '5e3ca05cd50d4005f8bdab15',
name: 'Marvel'
}
}
}
Next

Installation