What is Payload?
Payload is an open-source backend framework with an admin panel. It's kind of like if Ruby on Rails and Retool got together and had a TypeScript baby. You can pick it up and put it in any Next.js app folder and then instantly get a full admin UI and a full backend architecture, including authentication.
I'm James, I'm the CEO. I still write a lot of code too. Anyway, Payload is truly open source, and that means no free tier, no looming quotas in the background. Build whatever you want and host it wherever you want, including for free on serverless hosts like Vercel or Netlify. You can stay in the loop with the product here on GitHub. If you click the star button, you can follow along with all of our new product updates, feature releases, etc., and it would help us out. But Payload is used by everyone from freelancers all the way up to Fortune 500 enterprises as an app framework, as a CMS, e-commerce, digital asset management, whatever. At the end of the day, it's a backend framework with an admin panel. It takes care of the database, gives you your endpoints, and it gives you the admin panel as well.
I'm currently showing our website template. This is a really good spot to start if you're coming into Payload and you're trying to learn about websites. Now this gives you everything you need for a production-grade React admin panel built on Next.js, and it even includes things like live previews. So I can see what I'm doing as I make these changes here. They just instantly show. This is all server components too. It works with anything, but it comes with more than just live preview. It comes with on-demand revalidation. Everything is statically rendered. It has forms, it has redirects, it has everything that you need, a sitemap, everything for a big website. So it comes with a lot, but if you're building a website and you're trying to learn about Next.js, this is a great place to start. However, this video, let's start with a blank template and I want to show you some of the bigger pieces of payload from scratch.
Scaffolding a New Project
So here we are at the terminal and I'm going to use pnpm for this. You can use npm or yarn or whatever you want, but I like pnpm. I think you will too. But pnpx create-payload-app@latest. Just with that one command, we're going to get steered through building an entire app from scratch. And I'm going to say this is going to be called "what is payload" and we'll choose the blank template. I mentioned there's a website template too. Let's choose blank. I'm going to go with MongoDB. I've already got it running. You could use SQLite, which does not include a database, but that's up to you. I like to just, I've already got it running, I'm just going to stick with MongoDB. But we're going to install the dependencies and once this is done...
Okay, there we are. Now if I ls, I have a new folder, "what is payload", so I can cd what-is-payload and then from here I can open up a code editor and check out the project. So I'm gonna pull that over here, full screen, zoom in a couple of times. The first thing to know about Payload is that it is config-based. It's everything that you do starts with the payload config. And so this, this being a blank template, it's a very small config. It's got two collections: it's got users and media, and that's it. But I can go run this and show you what it looks like in the browser right now.
I just ran pnpm dev to start up the server and it's running on localhost:3000. Go over to /admin here and right away we have a screen that lets us create a new user. So I'm just going to quickly create a new user and then here's those two collections that we have: users and media. And those are the building blocks. I think if you're getting started with Payload, the first docs that you want to read are right here, this basic section, especially the concepts page. There's not a whole lot of concepts in Payload, but they're all pretty important. So if you read through this, you'll be able to understand exactly how payload works and why it works the way that it does. But yeah, two content collections here.
Defining Collections and Fields
Let's go add another one because this is all TypeScript. You're going to get yelled at if you don't do anything right. So it's already yelling at me. I need to say like posts, or let's say cars. And then we got to give it fields. So it's an array and we do name is title, and type is text. And then I'm going to say admin: useAsTitle, we're going to use the title field as the title of a car. So if I save this, already we have a cars collection over here. We use Next.js HMR to instantly reload changes on the back end and the front end. But I can just start creating cars. Well, let's say, Aston Martin Vantage. Cool. That's a nice car.
But right there, and then if I wanted to add a new field for like name is featured image, and type is upload and then relationTo is the media collection, which we already have here, then that's going to give me an upload field and I can go and create a new image. I can choose from existing images, whatever I want to do. But this is pretty simple. Let's jump ahead and I'll show you a couple more fundamental aspects of this.
Relationships and Image Resizing
Okay, I've done a few things here. The first thing is that I've added a couple more fields to cars. So I added a manufacturer field, and I also added a manufacturers collection. So now when I go to cars, I can click on the Tesla Roadster, let's say. I've got a featured image, I've got a manufacturer, and all of this stuff is just additional building blocks of Payload, whatever. But if I go over to manufacturers, let's say I go to Aston Martin, you'll see that I have a bidirectional relationship. This is called the join field. So this all works exactly how you would want it to on the database that performs a join. It's a bidirectional relationship right there, very, very simple. What that looks like is just that right there. I added that field on the manufacturers collection and then we get all this UI. So I could go straight to the Aston Martin Vantage and edit it right here.
I also enabled some features on the media collection. So if we go over here, I've added a couple additional sizes to images. So every time someone uploads an image, it's going to resize to these two sizes. And if I go and show you what that looks like... Let's go to the Tesla Roadster here. I can preview. Here's my new sizes. Oh, that one doesn't look very good. It's cropped in the center. Luckily, Payload gives you controls to be able to crop and set hotspots for photos. So if I drag the hotspot over here and hit apply and save, boom, now it's fixed and that looks a little bit better. But Payload gives you all of this out of the box.
Extending the Rich Text Editor
Now, another thing that I did was I added a Pages collection. And the Pages collection has a few things going on. So it's got versions with drafts, which means that you can save newer versions than what you have published, and it's also got autosave. But I've got a rich text field. So if I show you what the rich text field looks like, this is one of Payload's most powerful aspects, is that the rich text field can be easily extended. So here's my rich text, and I just wrote some garbage, but I have two custom components for my rich text field that really didn't require any custom code at all. So here's like a car highlight. Let's say that your editors need to have custom React blocks that they can use in their rich text. Here's a car highlight and all you do is you select the car and then you set it to an image or gallery, whatever, and then that would render however you want on the front end.
And then we also have inline blocks. So imagine if you wanted to dynamically reference the title or some price of related data, but you don't want to like write it there. Let's say the Tesla Roadster has a price set, but you don't want to go hard-code that price into your text anywhere. Well, you can give your editor inline blocks where they reference the car and they save it, and then you could dynamically populate this. So all of this is very simple in Payload. Lexical is the text editor that we use and we make it extremely extensible in an easy way. So to get that car highlight block, this one, all I did was I used a payload block here. This code says, okay, we have a car highlight, you have to choose the car that you're highlighting and then say what type of highlight you want to render. Done. And then all of this just happens. So that's a very easy way to extend the editor.
And then the inline block is the same thing. It's just the same principle. It's a payload block, you specify which field, and in this case, I've actually added my own custom React component to render the label. And that's really cool. That's how I get, um, the label of the car that was selected here. So you can add your own custom React components anywhere into the Payload admin panel. And so this is that label. All it does is it gets the ID that was selected from the form, goes and caches the full car, and then it returns the car title. And then right there we have a custom, very, very friendly for editors inline block that can reference dynamic cars.
Access Control and the REST API
A couple more things here. The next thing is that Payload comes with significantly extensible access control. And I've shown that on the pages collection here. You can see I've set read access control which is functional. It's all in TypeScript, so my user is actually typed as my user from the user collection. And I'm saying, hey, if there's a user, if someone's logged in, then return true. And if there's no user logged in, then only let them see documents that are published. So just with that, I can go to the REST API, which Payload also mounts for you, and I'm logged in right now so I see two documents, right, one and two. Now, if I do the same thing in an incognito window, I'm only going to see one, because I have two documents here. One is published and one is not. And there you go, just like that.
Extending Logic with Hooks
Another concept that I want to show is called hooks. So if we go over to cars, I've added a hook. Payload hooks are ways that you can inject your own functionality into anything on the back end of what Payload does. And in this case, I've added, "do I like it" as a property for this car. So I said, hey, if this document title includes Vantage, then yeah, I like it. And if it doesn't, then maybe not necessarily. So what we can do is go back over to Pages or let's go to, let's go to cars. And you can see here, if I close some of this, Tesla Roadster, don't like it. I actually do. I think it's beautiful, but that's besides the point. Do I like it? Audi S5, nope. Aston Martin, do I like it? Nope. Oh, Vantage, do I like it? Yep, I do. And that's true. I actually like all these cars, but anyways. So that's pretty cool. You can do a lot of things with hooks in Payload. This is, it's fully extensible. Every single thing that you want to change or do, just do it with hooks. Access control is powerful for preventing people from doing things. Hooks are for extending Payload. But with these building blocks, you can build anything. The database is done, the APIs are done, everything is done.
Using Payload in the Next.js App Router
And the last thing that I want to show you is that because we're built in Next.js, you can add your own functionality into your own app router that uses Payload directly, even authentication. So I've added a route handler here. You can see Payload runs in the app folder right here. And I've added a route handler called my-route, and then this file, what it does is it goes and it gets Payload, and then we get the headers of the user. And just with that, we can run payload.auth(), which will tell us if the user is logged in or not. So if there is a user, then we will send back cars. And of course, this is all typed. Everything here is typed automatically for you. So if there is a logged in user, we're going to send back the cars and the user. If there is no user, we're just going to send back unauthorized. So let's go check out and see what that looks like. And one other thing to keep in mind here is that I've used the select API, which lets me select only the title from the car. I haven't selected anything else. I haven't selected the manufacturer or anything. So here we go. I'm logged in and I see four documents with the title and that hook was injected dynamically, and then I have the user that was logged in. Now, if I go to this in incognito...boom! so with these controls, you can set up an entire authentication pattern just with Payload inside of your Next.js app folder, and it's all open source and it's all just there for you. So this dramatically simplifies the work involved in building anything nowadays.
And let's say I also wanted to say... or let's get rid of this select, actually, and then we go back over here, refresh. Now we get the full cars. If I wanted to get title and manufacturer, let's do that. title, manufacturer true. Just like that, title and manufacturer. And this is all typed as exactly as you would expect. So it's very bulletproof. It happens automatically. Payload types everything for you, and you can import these types and use them yourselves in your own code. I can actually show you really quickly. I think one of those components used the car type... yeah, right here. So when we go to fetch that car, we just type it as Car and then everything is typed end to end. Type safety out of the box, authentication, everything. But I think that's a pretty good overview of Payload. We're going to do more videos, and especially on that website template, we'll go through everything in depth to show you how everything works. But hope you like it, and if you have any feedback for us, we'd love to hear it. See you on GitHub. Thank you.