Introducing Payload - 2021's Node + React Headless CMS for JavaScript Developers

Published On
Introducing Payload - 2021's Node + React Headless CMS for JavaScript Developers
Introducing Payload - 2021's Node + React Headless CMS for JavaScript Developers

Modern JavaScript developers just got a new headless CMS at their disposal—and it’s one we think they’ll have an absolute blast working with. Payload—a self-hosted Node, Express and React-based headless CMS, is now available.

Hi—my name is James and I’m one of the founders of Payload CMS. After two years of development and thousands of commits, I am extremely excited to announce that Payload CMS is now available to the public. It’s our response to the surprisingly sparse JavaScript CMS market and we hope that its arrival improves the development workflow of engineers all over the world.

Payload has already been put through the test with an array of pilot projects that ranged from video game backend to full e-commerce store development, virtual event platform, and more. Through the projects we’ve released with Payload thus far, our own team’s efficiency has absolutely skyrocketed and we’re confident that it’s only going to get better from here.

Now, we’re finally ready to open up to the community.

We would greatly appreciate if you were to install Payload, give it a shot, and let us know what you think. Any type of feedback is welcome - be it about how we write our docs, about your experience using Payload in your projects, or anything else!

We needed a CMS that didn’t exist

We built Payload because, over the years, my team and I have come to understand exactly what we need out of a CMS to build projects—big or small—for our clients:

1. Self-hosted.

What happens when your hosted CMS doesn’t offer you just that one thing that you need, so you need to end up opening a REST endpoint to build it? Guess it’s time to maintain your own server or Lambda function. Seems like a racket when you could have just used a self-hosted CMS in the first place and had a server set up already. We’ve been there too many times to let that keep happening.

Third-party hosted CMS might work for simple sites where you know you’ll be able to work within their confines for the lifetime of the app, or for strictly delivering content and not ever having to worry about receiving content, but when your needs become any more advanced, a self-hosted CMS that provides you with complete control is the way to go.

Security is also a concern with third-party hosted CMS solutions. My digital design firm TRBL works with many clients that are heavily security-focused and want to maintain complete control over their databases and infrastructure. Many of them deploy their CMS within their own private networks—only accessible via VPN or similar. For these clients, maintaining control over their own code is an absolute necessity, which removes many popular third-party hosted CMS from the equation.

Find out how to install Payload by heading to our Docs.

2. Customizable React admin panel.

We want a CMS’ admin panel to be minimal, understandable, and most of all, completely customizable. If we need to customize a field type, we should be able to swap in our own React field component to take the place of a default text input, for example. We definitely don’t want to jump through any hoops, either, like dealing with messy iFrames or separately developed field type packages.

If we want to add a view, we should be able to build a React component and add it as a view. If we want to be able to customize the CMS’ branding, and completely white-label the CMS, we should be able to.

Payload CMS Admin Laptop screenshot

3. Block-based field editor.

My team and I design entire sites and apps with a component mentality—even down to how page layouts are assembled. Through UX design phases, we identify all the layout building “blocks” that are necessary to build and then we design our CMS to allow for content editors to self-craft their page layouts using the deliberately designed layout blocks that we’ve provided them with. We then map each “block” in the CMS to React components that have props matching 1:1 to the fields within the CMS block. Boom, component-based layout building.

Like so many others, we started off years ago using WP and Advanced Custom Fields. ACF’s Flexible Content field type is great for layout building. But unfortunately, many other CMS have a complete lack of any layout-building workflow, and even when it’s supported, it lacks functionality or is a shoe-horned solution.

Conditional Logic

Another thing my team always took for granted in ACF that’s missing from other CMS completely is field-level conditional logic (show this field if another field has a value equal to true and similar). Our ideal CMS needs to have a built-in way to deliver dynamic interfaces that respond to input accordingly. Such a simple feature makes complex content management so much easier.

4. JavaScript top to bottom.

When’s the last time you worked on a web project without a package.json? Even if you work in PHP, you’re likely going to unavoidably need Node too. The idea of flattening our stack entirely into one language and not having to run a Docker container just to get a local LAMP environment going is a nice one indeed. We want to simplify our stack and keep it all JS. Better yet, TypeScript.

5. Reusable, secure authentication.

One of the toughest parts about content management systems in-general is that they perform a lot of the lifting that a typical application framework would also need, but fall dramatically short of being able to call themselves an app framework through and through because of their lack of support for reusable authentication. For example, if you wanted to build a full SaaS product, you might need to create products, users, licenses, pages, and maybe even blog posts. Any run-of-the-mill CMS might get you close to being able to CRUD all of this stuff within its system, but what about user authentication? What about having control over users’ access? You’d be more often than not left to fend for yourself. Commonly you’d end up with either rolling your own system from scratch or building out a patchwork of separate systems (and separate admin UIs) to manage the product.

We need a CMS that comes with robust and reusable authentication right out of the box, so we can leverage the CMS for all our commonly needed authentication functionality. This way, we can keep all of our logic organized and build fully-featured apps right in our CMS that we’ve become accustomed to.

This way, if a client of ours comes to us asking for a simple app or a marketing site, but in the future, decides that they need to add full e-commerce support, we won’t end up with a messy disconnected set of admin UIs for them to manage their single product within. It can all be done in Payload.

Payload's Authentication Operations

In addition to just being able to log in and log out, Payload ships with everything a fully-featured app needs when it comes to authentication:

  • Self-registration
  • Login
  • Logout
  • Refresh token functionality
  • Forgot Password / Reset Password
  • Automatic locking of accounts on X number of failed password attempts
  • Email verification on new account creation

Payload supports as many authentication-ready collections as you need—meaning you could easily maintain a collection of Admins as well as a collection of Customers—each storing separate information and having separate access control to your documents.

Payload's Access Control

One of the best parts about Payload is its function-based Access Control. Right in your configs, you define who can access what documents via extremely simple and straightforward Access Control functions.

Here’s an example of an Orders collection with fine-tuned Access Control:

1
const Orders = {
2
// ...
3
access: {
4
create: () => true, // Everyone can create
5
read: ({ req: { user } }) => {
6
if (user) {
7
return {
8
// Users can only read their own
9
owner: { equals: user.id },
10
};
11
}
12
return false; // Not logged in? Can't read any
13
},
14
update: ({ req: { user } }) => {
15
// Only Admins can update Orders
16
if (user.roles.includes("admin")) return true;
17
return false;
18
},
19
delete: () => false, // No one can delete
20
},
21
};

6. Uploads with local storage.

Other existing CMS provide integrations to third-party file storage solutions, but those come with an additional cost, and one more third-party dependency to maintain. We want to be able to store our own file uploads, in our own contexts. If we want to ship them off to AWS S3 or similar after they’re uploaded locally—then so be it. They should be our files first though. And uploading should be simple to configure.

7. Code-based.

We used the ACF GUI for a while, but then realized we could be much more deliberate if we stored our ACF configs right in the PHP of our site. It was super nice to have written them, understood the code, and have them checked in directly to our repositories. Having our schemas so close to our code made referencing them significantly easier. Nowadays, we don’t find value from GUI schema designers and would rather just write them in code, pending the syntax is concise enough.

8. Maintain your own Express server.

We want a CMS with the right level of abstraction. That means giving us the functionality we know we won’t ever need to change, like auth and file upload, while also giving us the freedom to do what we need to do unhindered by a big lumbering framework whose docs are written for people that have Ph.Ds in Computer Science. If we could keep our hands on our own Express server, then we could do whatever we need to do however we need to do it, outside of the CMS. Plus, if we could keep our own Express server, we could combine a CMS with a SSR framework like NextJS if we wanted to. One command, spin up Next and the CMS at once.

Here’s an example for how Payload ties in to your existing Express server:

1
const payload = require("payload");
2
const express = require("express");
3
const app = express();
4
5
// Do whatever you want with your app.
6
// Just pass it to Payload and everything
7
// will be scoped to Payload routers.
8
9
payload.init({
10
secret: "XXXXXXXXXXXXXXXXXXXXXXXXX",
11
mongoURL: "mongodb://localhost/payload",
12
express: app,
13
});
14
15
app.listen(process.env.PORT, () => {
16
console.log(`Application listening on ${3000}...`);
17
});

9. Localization support.

If you’ve ever tried to use WordPress for localized content, by either using it in a multi-site capacity or by using one of the many outdated plugins that are available, you know just how painful it is. If not, here’s a tip: don’t do it. If you’re building a site or app that requires its content to be translated in multiple locales, run away from WP. Look for a CMS that supports localization intrinsically—bonus points if the localization is field-level.

Payload packages up everything we’ve needed for so long into one CMS and does so with flying colors.

You shouldn’t need to learn your CMS

To us, and maybe even more important than our list of CMS requirements above, we believe that you should not have to learn a CMS. That’s a passing investment of your time. You should learn to write the language that you’re working in—that’s a permanent investment.

While building Payload, we’ve taken great strides to ensure that any learning you need to do to get up and running with Payload is kept to the absolute minimum. Instead, you should be learning or practicing JavaScript. Our abstractions are as simple as possible so that you’ll understand how your CMS works, because you will have written it.

You shouldn’t need to fight your CMS

Ever have that feeling about how when you use a CMS, it gives you 70% of what you need in about five minutes, but then for the last 30%, you end up fighting against it for weeks, if not months?

Payload aims to fix that. It has a massive emphasis placed on the developer experience. We strive to give you what you need and nothing more. It’s a code-based CMS. That means your code—not ours. We give you the structure and the openendedness that you need to write your apps, but we don’t impose anything on what you need to do.

Get up and running with one line

Getting started is easy—and free. Just fire up a new terminal window and run the following command:

1
npx create-payload-app
Check out our docs

Take a look through our documentation for more information about how Payload works and how to use it.

Let us know what you think

Reach out to us on Twitter to give us your take.

Thank you!

We honestly want Payload to become the best JavaScript CMS that it possibly can be, and we look forward to continuing to strive to make that happen.