Like what we’re doing? Star us on GitHub!

Payload's open-source demo is now available on GitHub

James Mikrut

James Mikrut headshot
Payload's open-source demo is now available on GitHub

We just open-sourced the code for Payload's TypeScript headless CMS demo and it's now available on GitHub for you to take a look at and learn from. From form building to custom rich text elements, it demonstrates many best practices for you to use within your own projects.

Payload can power native appswebsitesweb apps, subscription billing engines, and anything else you can think of. Every aspect of the CMS is built so that developers can catapult their efficiency as they build out their backend and Admin UI. From being able to customize the Admin panel through custom scss or React components of your own all the way through to using Payload's Local Node API to seed data, Payload can power whatever you can dream up—all in TypeScript.

To demonstrate some of Payload's most powerful features, we've open-sourced our public demo so that you can take a look at how we at Payload make use of all the functionality that the CMS offers.

The demo can be seen at the following link:

And the code that powers this demo can be found on GitHub:

You can clone down the repo and run it locally on your machine to see how it all works. Instructions are located within the repo's

Features Demonstrated

The demo has a ton of features and functionality for you to check out. Here's a quick list of a few of the most visible.

Collection and Global configs

The demo includes Collections for CategoriesMediaPostsPagesUsersForms, and Form Submissions that all serve specific purposes.

In addition, you can see how Globals work and how they differ from Collections within Payload. Whereas Collections are groups of documents all with the same structure, Globals are "one-off" data types that work well for menus, meta data, and more. To show this, we've built a Main Menu Global directly into the demo that might be used for constructing a navigation structure for a website.

The Local Node API

One massive differentiator that Payload supports (which other headless CMS, especially SaaS options, do not) is a full Local API that allows you to run actions against Payload directly on your server, in your code.

The Local API can be used to:

  • Seed data
  • Migrate data over time from one schema to another
  • Access Payload data from custom Express routes or GraphQL queries / mutations
  • Build dynamic functionality and integrations within Hooks
  • Much, much more

Within the demo, we clear data every time the server starts, and then use the Local API to seed initial demo data so that we can periodically reset the demo back to its original content.

async function seedData() {
const { id: demoUserId } = await payload.create<User>({
collection: 'users',
data: {
name: 'Demo User',
email: '',
password: 'demo',
// Other seed operations continued in file...

A snippet of code taken from the demo's reset / seed script Custom Rich Text elements

Have you ever had to build a CMS that needed some specific typography, or custom Rich Text elements? Even more challenging—have you ever had to extend TinyMCE or some similar rich text editor with custom elements? With other CMS, that can be an absolute nightmare. But with Payload, defining custom rich text elements like a YouTube embed or a specific typography technique is super easy and all done in React. Define a button component to add to the toolbar and build the React component that will be rendered in the editor—and you're done.

The demo shows you how to build a custom Large Body type component as well as a custom Video Embed.

Payload CMS Rich Text Screenshot

Payload's Rich Text Editor, demonstrating how to build your own custom Rich Text elements

Access Control

The demo shows how Access Control can be used to restrict who can do what, in pure TypeScript functions. For example, we've completely disabled editing Media. Payload's Access Control is much more powerful than pre-baked role-based access control which is more common within headless CMS. You can build any type of access control pattern you can think of.

Versions and Drafts

Within the Posts and Pages collections, you'll see how enabling Versions and Drafts creates a true draft mode for your documents, and you can easily limit via access control who can see drafts, and who can only see published posts. You can also see how to restore documents back to earlier states, and view "diffs" of documents as they change over time.

Payload CMS Versions Screenshot

A screenshot showing a diff of two versions of a page

Reusable fields

Often, well-scaffolded Payload projects will feature reusable fields. This demo shows a great pattern for how to write your CMS with highly reusable fields, and then how to import and utilize / re-utilize them throughout your configs. Being that Payload is code-based and just regular TypeScript, the pattern can be extremely powerful and very developer-friendly.

Payload CMS Link Field Screenshot

A reusable and predictable Link field group


Payload supports a powerful Plugin pattern that allows you to abstract commonly used modules into reusable plugins that you can share with the greater Payload community.

Within this demo, we've employed three plugins:

  1. An SEO plugin, which adds meta fields and auto-generates meta titles, descriptions, and images for you
  2. Form Builder plugin, which is an extremely powerful way to allow your editors to publish and utilize extremely flexible forms within the Admin UI
  3. A [Nested Documents plugin]), which allows you to create parent-child hierarchies between documents of any depth, and automatically generate "breadcrumb" data based on these parent / child relationships.

Each of the above plugins are also open source. You can take a look at how the plugins are built to see how you can build your own. It's a super powerful and easy pattern to get the hang of.

Payload CMS Forms Screenshot

Screenshot of the Form Builder plugin

Custom React components

You can inject your own custom React components in place of anything Payload does—be it for a custom field, a custom view, or replacing an existing Payload view in its entirety. The public demo showcases this through a few methods, including injecting custom BeforeLogin and AfterDashboard components. The Payload SEO plugin also uses custom components to be able to render an interactive set of custom fields.

Payload CMS Custom Fields Screenshot

Custom React fields within Payload Admin UI

Auto-generated TypeScript interfaces

Payload can automatically generate strongly typed TypeScript interfaces based on the shape of your configs, and the demo shows you how powerful this can be.

Here's the auto-generated Media interface:

export interface Media {
id: string;
url?: string;
filename?: string;
mimeType?: string;
filesize?: number;
width?: number;
height?: number;
sizes?: {
thumbnail?: {
url?: string;
width?: number;
height?: number;
mimeType?: string;
filesize?: number;
filename?: string;
portrait?: {
url?: string;
width?: number;
height?: number;
mimeType?: string;
filesize?: number;
filename?: string;
hero?: {
url?: string;
width?: number;
height?: number;
mimeType?: string;
filesize?: number;
filename?: string;

Take a look at the rest of the auto-generated interfaces to get a sense of the type safety that you can achieve with Payload and TypeScript.

Field-based Localization

The demo features content designed to be written in three locales - English, German, and Spanish. It's done on a field-by-field basis, which is a very powerful pattern and significantly more flexible than CMS that only allow you to write an entire document in a certain locale. With Payload, you decide what to translate.

Advanced field types

You'll see many of Payload's field types employed within the Admin UI, including a few custom fields that rely on custom React components to render.

Check out the source code

The demo goes far beyond the features discussed above. Log in to the demo and poke around, or take a look at the source code to see more.