Let's Checkout... Payload CMS
What I really like about Payload CMS is that everything is done through code, you don't have to go around clicking in the admin UI to setup things like you would do in WordPress, Strapi or even Directus.
What I really like about Payload CMS is that everything is done through code, you don’t have to go around clicking in the admin UI to setup things like you would do in WordPress, Strapi or even Directus.
You just configure everything directly in code and use the Admin UI to add data to your app. Being a developer this is really appealing to me. It has a great developer experience, but the end users don’t need to know anything about coding to add new data to the CMS easily.
Let me show you how this works.
Install MongoDB
First of all you need to setup MongoDB to be able to use Payload, this is very easy and there are a few options.
For this demo I’m going to use a Docker instance of MongoDB - if you want to setup MongoDB that way, you can follow along with this tutorial.
Another way is to visit MongoDB docs and follow instructions there to install it on the system of your choice.
And the third and probably the easiest way is to sign-up for MongoDB Atlas and use their free tier to setup your DB. And then use that during Payload setup.
Install Payload
Once you installed MongoDB, go to your terminal and run npx create-payload-app
, just be sure that you have NodeJS version 10 or above running on your system.
Now give it a name, I will call mine payload-movies
since we are going to create a standard demo that I always use for these types of videos, a kind of movie database.
For project template I’m going to choose a blog
so that we get some collections and fields right away. And then later we are of course going to add our own collections and fields to create a movie database type of site.
Now you need to enter your MongoDB connection, for me it’s going to be mongodb://root:root@localhost:27017
cd since I’m using Docker setup. For you it may be something a bit different.
Wait a bit for project dependencies to be installed and then just cd into payload-movies
directory and run npm run dev
or yarn dev
if you are using Yarn.
You should get an URL to the Payload Admin, which will usually be http://localhost:3000/admin
- go to that address in your browser.
You will be greeted by a welcome screen and be prompted to add a first user. Add your data here and click “Create” button.
Admin interface
Admin interface for payload is very simple. You have access to Collections which were created during Payload installation. These Collections work the same way like in Directus, they are just collections of a specific data items.
Since we opted for a blog site during Payload installation, we get some standard ones like Posts, Categories and Tags.
Of course you also have Users, for user management and Media for media management.
When you click on any collection you can create an item in that collection, and then fill in the data in the fields assigned to that collection. Also all very similar to Directus.
Once you create a new item you can check out API response for it by clicking on the “API URL” link.
Now, this all looks very minimal, but don’t confuse minimal with the lack of options or features. Remember, in Payload you setup everything through code, so you can make it as complex or feature full as you like, because the Admin interface is not for you - the developer, it’s made for editors and non technical users and they need the UI to be as simple as possible for adding content to the site without much friction.
And if you need some custom feature in the Admin UI, you can easily achieve that by adding in your own custom React components, using provided React Hooks and by customising CSS. So even the Admin interface is very extensible. Maybe I will show you how to do that in some other video.
For this video let’s try to cover the basics of creating Collections and Fields, and I’m also going to show you how to create data relations and how to add some custom functionality to your fields.
Creating Actors Collection
Now open your code editor and let’s get to work. Go to the src
directory and then to collections and create a file called Actors.ts
- Payload uses TypeScript which is great because you are going to get a lot of code hints and auto complete options in your editor so that you can work much faster.
First we are going to import CollectionConfig
from payload/types
so that we have typings for our Collection.
import { CollectionConfig } from 'payload/types';
Then we define our Actors
collection with CollectionConfig
type.
const Actors: CollectionConfig = {
...
}
And in it we are going to define slug
for our collection, useAsTitle
which is going to be a title of the item in the collection that is going to be displayed in lists and on the item page. For now I’m going to set it to be first_name
because we are going to create a field called first_name
for Actors
.
After that we are going to set access to read
so that this can be read by anyone. In Payload you can have very granular control over who can read what, but we will not cover that in this video.
I will now add two fields first_name
and last_name
. Defining fields in Payload is very intuitive. You just define name
, type
and label
for the field. For some fields it can be a bit more complex, but not much, I will show you that a bit later.
Lastly, I will just add timestamp
property to be false
. Now you just export your collection and we are done with the Actors.ts
file for now.
const Actors: CollectionConfig = {
slug: 'actors',
admin: {
useAsTitle: 'first_name',
},
access: {
read: () => true,
},
fields: [
{
name: 'first_name',
type: 'text',
label: "First name",
},
{
name: 'last_name',
type: 'text',
label: 'Last name'
}
],
timestamps: false,
}
export default Actors;
One last thing we need to do is to register Actors
in payload.config.ts
file. First we just import Actors
.
import Actors from "./collections/Actors";
Then you just add Actors to the collections
array. And that’s it.
Go to the Admin in your browser and refresh the page. You should see Actors
collection show up in the UI.
Click on it and try adding an Actor. Robert DeNiro for example, and click Save.
Ok, so this works, but what I don’t like is that the title of the Actor is just Robert without the last name. Let’s try to fix that.
Go to Actors.ts
file and import FieldHook
type.
import { FieldHook } from 'payload/types';
Then we are going to create a function that is going to return value of the first_name
and last_name
fields. I’m going to call this function populateFullTitle
.
const populateFullTitle: FieldHook = async ({ data }) => {
return `${data?.first_name} ${data?.last_name}`
}
Now we add a new field called full_name
and hide it in admin UI, and then we use beforeValidate
hook to populate this field automatically with the populateFullName
function that we just created.
{
name: 'full_name',
type: "text",
admin: {
components: {
Field: () => null
}
},
hooks: {
beforeValidate: [
populateFullTitle
]
}
}
```
We must not forget to set `useAsTitle` to be `full_name` instead of `first_name` .
```ts
useAsTitle: 'full_name',
Go to the browser refresh and save Robert DeNiro again.
Also let’s try adding one more actor. Brad Pitt this time. The name won’t be filling up as you type, but it will populate first and last name once you hit save. Great.
Creating Movies Collection.
Now let’s add Movies collection. In the collections
directory add a file called Movies.ts
, and we follow the same pattern like we did for the Actors collection.
import { CollectionConfig } from 'payload/types';
const Movies: CollectionConfig = {
slug: 'movies',
admin: {
useAsTitle: 'title',
},
access: {
read: () => true,
},
fields: [
{
name: 'title',
type: 'text',
label: "Movie title"
},
{
name: 'date',
type: "date",
label: "Release date"
}
],
timestamps: false,
}
export default Movies;
We are going to use title
field for our useAsTitle
property. I’m going to add two fields, title
and date
for now. Take note that the date field has the type
of date
this is going to give us a nice date widget in the Admin UI.
Now I want to add two more fields, actors
for choosing the actors in the movie and also a poster
for the movie poster.
Since we wanna add actors from our Actors collection, actors
field is going to be of type relationship
, for this type of field to work we also need to define what collection this field relates to. This is super easy, just add a property called relationTo
and put actors
as a value. Since the Movie can have many actors, we are going to set hasMany
property to true
. We also want the to create new actors from this field in the Admin UI, so we are going to set allowCreate
property to true
.
{
name: 'actors',
type: "relationship",
label: 'Actors',
relationTo: 'actors',
hasMany: true,
admin: {
allowCreate: true
}
}
We need to set up one more field, for the movie poster. This field is going to be of type
upload
and for Upload fields you also need to set relation, just like for Relationship field type. I’m going to set relationTo
property to be media
. So that we can upload new media, but also use already existing Media.
{
name: 'poster',
type: "upload",
relationTo: 'media'
}
Save this and we are done with Movies collection, only thing left to do is to register it in payload.config.ts
file.
Now let’s test it out in the browser. Refresh the Admin UI, and you should get Movies collection.
Create a new Movie. Movie title is going to be Goodfellas. I’m going to set release date to January, 1st 1990. And now we can select actors.
I’m going to choose Robert DeNiro.
And since we enabled creating Actors from this page, I’m also going to add Joe Pesci, by clicking on the plus button. Add Joe Pesci and click Save.
And for the movie poster I’m going to Upload New Media, and add poster for Goodfellas. Then click Save. And then Save again to save the Movie.
And that is it, we can check out the API response by clicking on the API URL.
Conclusion
I must say - Payload is pretty nice, it has a nice developer experience and is very easy to use for the editors. And since you can do everything in code you can easily share your code through git with your team or other developers you are working with.
This has been only a taste of what Payload can do, and I will for sure make a few more videos about it, since I find it very enjoyable to work with. And as always don’t forget to read the docs if you wanna get your hands dirty with it.