You’ve got Payload running, and the admin panel works. It shows the Payload logo, every collection looks the same, and the dashboard is a grid of cards. Your editors want their own logo and colours, a screen for the job they do every day, and numbers on the first page they see.
As of 4 November 2026, the latest stable release of Payload is 3.92.1, and Payload 4.0 is in public beta, with a redesigned admin panel (Payload’s 3.92.1 release, Payload’s releases). This guide covers branding, styling, custom screens and the dashboard, each in Payload 3 and in the 4.0 beta, and what moving an existing admin panel to 4.0 involves.
- How the Payload admin panel works
- What changes in the admin panel in Payload 4.0
- How to brand the admin panel
- How to style the admin panel: CSS, Tailwind and shadcn
- How to add your own screens: custom components and views
- How to build a dashboard with widgets
- Should you start on Payload 4.0 or the latest stable release?
- What moving an existing admin panel to 4.0 touches
- Frequently asked questions
- What to do next
How the Payload admin panel works
Payload generates the admin panel from your config. Every collection and global you define gets a list view and an edit form without any interface code, with drafts, versions and access rules where you turn them on (Payload’s admin panel docs). You change it in two ways, with options in the admin block of your config, and with your own React components that replace or add to the built-in ones.
Components are referenced by file path as strings, such as '/components/Logo#Logo', and Payload resolves them through an import map it generates for you (Payload’s custom components docs). They’re React Server Components by default, so a component can query your data directly through the Local API before it renders. Payload regenerates the map at startup and on hot reload, and payload generate:importmap rebuilds it by hand.
In Payload 3, the admin panel is a Next.js route group inside your app, under (payload), which keeps its layouts and styles apart from the rest of your site (Payload’s admin panel docs). Payload 4.0 separates the admin from Next.js behind an adapter, so the same admin can also run on TanStack Start, with Payload’s adapter for it in beta alongside (Payload’s 4.0 migration guide). Our guide to Payload and Next.js covers where the admin sits in each setup.
For example, take a property management company. Its agents edit listings in the admin panel, its office manager tracks maintenance requests, and its owner wants the company’s logo and colours, a dashboard of open requests per building, and a screen for lease renewals. We’ll use this company throughout. If you’re new to collections and globals, our guide to Payload covers the content model first.
What changes in the admin panel in Payload 4.0
Payload 4.0 redesigns the admin panel, moves its styles from Sass to plain CSS, and stops the admin depending on Next.js. The first beta shipped on 9 October 2026, and its release notes list the admin UI redesign, TanStack support, dashboard components, accessibility, hierarchies, tags, a grid view and an improved upload interface among the new features (Payload’s 4.0.0-beta.0 release), and the v4 migration guide sets out what each change means for an existing project (Payload’s 4.0 migration guide).
| Area | Payload 3 | Payload 4.0 beta |
|---|---|---|
| Look | The current admin design | Redesigned admin, with list, edit and upload views reworked |
| Styling | Sass, with --theme-* CSS variables and a root custom.scss | Plain CSS, with semantic --color-* tokens and a --ramp-* palette |
| Runs on | Next.js only | Next.js or TanStack Start, each through its own adapter |
| Routing in your components | next/navigation and next/link | Router hooks and PayloadLink from @payloadcms/ui |
| Dashboard widgets | Experimental, shipped inside the Next.js package | Experimental, moved into the UI package, plus a new recents widget |
| Globals | A smaller set of component slots than collections | The same slots and custom views as collections |
| Versions | Off unless you turn them on | On by default for every collection and global except auth collections |
| Authorship | Not tracked | createdBy and updatedBy on by default |
| Local API in your components | Skips access rules unless you pass overrideAccess: false | Enforces access rules unless you pass overrideAccess: true |
| Minimum versions | Node.js 22 or 24, Next.js 15 or 16 (as of 3.92.1) | Node.js 24.22.1, Next.js 16.4.0, TypeScript 6.0.3 |
The published packages confirm the move away from Sass. The UI package in 3.92.1 carries 250 .scss files, and the 4.0.0-beta.6 package carries none (@payloadcms/ui on jsDelivr).
Payload described its plans for 4.0 in June, including the redesign, Tailwind compatibility, better theming and an enhanced contrast mode (Payload’s 4.0 preview).
How to brand the admin panel
You brand the Payload admin panel with four settings, the logo and icon components, the page title and favicon, the colour variables and the theme. Each takes a few lines of config, and none of them changes your data.
- Swap the logo and icon
- Set the browser title and favicon
- Set your colours
- Choose light mode, dark mode or both
1. Swap the logo and icon
Payload shows two graphics, a full Logo on the login screen and a small square Icon in the navigation (Payload’s root components docs). You replace each with a React component under admin.components.graphics.
export default buildConfig({
admin: {
components: {
graphics: {
Logo: '/components/graphics/Logo#Logo',
Icon: '/components/graphics/Icon#Icon',
},
},
},
})Each component can return an <img> of your logo file or an inline SVG. For example, the property company’s Logo returns its wordmark for the login screen, and Icon returns the square mark from its letterhead.
2. Set the browser title and favicon
The browser tab shows each admin page’s title followed by “- Payload”, until you set your own suffix (Payload’s metadata docs). admin.meta holds the suffix, the favicon and the Open Graph image used when someone shares an admin link.
admin: {
meta: {
titleSuffix: '- Lettings Admin',
icons: [{ rel: 'icon', type: 'image/png', url: '/favicon.png' }],
},
},The icons array takes the same entries as Next.js metadata icons, so you can add an apple-touch-icon for staff who save the admin to a phone’s home screen.
3. Set your colours
Payload’s colours are CSS variables, and you override them in your admin stylesheet (Payload’s CSS docs). In Payload 3, the variables are named --theme-*, such as --theme-elevation-0, and the stylesheet is custom.scss in the (payload) folder.
Payload 4.0 retires the --theme-* variables. Its colours are semantic tokens such as --color-bg, --color-text and --color-border, plus a raw --ramp-* palette, all defined on :root (Payload’s 4.0 CSS docs). Any colour override you write for Payload 3 has to be renamed when you upgrade, so keep them in one file.
4. Choose light mode, dark mode or both
Each user picks light or dark mode on their account page, and Payload falls back to the operating system’s setting (Payload’s admin panel docs). Set admin.theme to 'light' or 'dark' to lock it to one. In Payload 4.0, every --color-* token is redefined for dark mode, so colour overrides on the semantic tokens adapt to both themes, and the beta adds contrast improvements for accessibility (Payload’s 4.0.0-beta.4 release).
How to style the admin panel: CSS, Tailwind and shadcn
Global styles go in your admin stylesheet, and styles for your own components go in files those components import. Payload wraps its own CSS in a cascade layer, @layer payload-default, so any style you write outside that layer wins without a specificity fight (Payload’s CSS docs). If you’d rather your styles sit inside Payload’s order, write them in the payload layer.
@layer payload {
.dashboard {
background-color: var(--color-bg);
}
}Payload’s built-in classes follow BEM naming, such as .dashboard or .nav__link, so you can target any part of the interface from one file. In Payload 3, that file is Sass. In 4.0 it’s plain CSS, and the migration guide asks you to rename any .scss files you wrote to .css, because Payload no longer ships a Sass toolchain (Payload’s 4.0 migration guide).
Payload’s docs don’t cover Tailwind CSS or shadcn/ui in the admin panel, in either version. Your site’s Tailwind setup stays outside the admin, because the (payload) route group scopes the admin’s layouts and styles. To use Tailwind classes or shadcn/ui components on an admin screen, import their styles into that screen’s own component, which is where Payload’s CSS docs ask custom components to keep their stylesheets (Payload’s CSS docs). Check the screen in light and dark mode, because the admin’s own colours change with the theme. Payload’s June preview named better Tailwind compatibility as a 4.0 goal (Payload’s 4.0 preview).
How to add your own screens: custom components and views
You add your own screens by replacing a built-in component, adding one into a slot, or registering a whole view at its own address. All three use the same file-path references and the same import map.
Field components replace how one field looks in the edit form or the list. For example, the property company shows a lease’s end date in red in the list once it’s within 60 days.
List and edit view slots let you add buttons, panels and tabs to a collection’s screens, such as a “Send renewal” button beside Save on a lease (Payload’s edit view docs).
Root components go around the whole admin, such as beforeDashboard, beforeNavLinks, afterNavLinks, the header actions, and providers that wrap every screen in a React context (Payload’s root components docs).
Custom views are whole screens at their own route inside the admin.
admin: {
components: {
views: {
leaseRenewals: {
Component: '/views/LeaseRenewals#LeaseRenewals',
path: '/lease-renewals',
},
},
},
},The lease-renewals view lists every lease ending in the next 90 days, grouped by building, with the tenant’s contact and the agent responsible. Routes cascade, so set exact: true if another view’s path starts the same way (Payload’s custom views docs).
Payload doesn’t check the login for a custom view. Custom views are public by default, so start each one by checking the user in initPageResult.req.user, which the docs name for access checks, and send away anyone who isn’t signed in as a user of the collection named in admin.user (Payload’s custom views docs). Our guide to Payload authentication covers restricting that collection by role. If you run several companies or brands from one admin, our multi-tenant guide covers the tenant selector the multi-tenant plugin adds.
Payload 4.0 changes two things here. Router hooks and the Link component now come from @payloadcms/ui instead of next/navigation and next/link, so the same component runs on Next.js or TanStack Start. Globals also get the same component slots and custom views as collections, with the elements key renamed to edit (Payload’s 4.0 migration guide).
A delivery dashboard built from custom views
For example, we built a delivery dashboard inside the Payload admin for a frozen meal brand in the UAE. Until then, the team ran every delivery day from a 13-tab Google Sheet that someone copied by hand each week, working out how many meals to cook, how many boxes to pack, how much dry ice to order and which file to send the courier.
The dashboard is seven custom views with their own link in the navigation, added through beforeNavLinks, so there’s no separate app and no second login. Staff pick a delivery date and move between a run overview with box counts and dry ice, a production list for the kitchen, a printable packing list, the courier’s 12-column CSV, coupon usage, notes and past runs. The box sizes and dry ice rules sit in a global, so the team changes them in the admin without a developer. The views read orders and never edit them.
Notes come from a widget in the header’s actions slot, on every screen, and save to their own collection along with the page they were written on. Each order also gained an area field, a relationship filtered by the order’s emirate across a 658-entry list of the courier’s delivery areas, with a read-only map of the customer’s pin beside it. Staff used to look up each pin in Google Maps and type the area by hand, and now they pick it from the list on the same screen.
Every one of those views checks the user before it renders anything. This store’s users collection holds shoppers as well as staff, so an unguarded view would have shown the delivery run to anyone with a customer account.
How to build a dashboard with widgets
The dashboard is the first page your users see after login, and widgets let you put live data on it. A widget is a Server Component you register under admin.dashboard.widgets, with a slug, a component path, optional settings fields, and a minimum and maximum width (Payload’s dashboard docs). Payload marks the modular dashboard as experimental, in Payload 3 and in the 4.0 beta.
admin: {
dashboard: {
widgets: [
{
slug: 'open-requests',
Component: '/widgets/OpenRequests#OpenRequests',
minWidth: 'small',
maxWidth: 'large',
},
],
},
},For example, the property company’s OpenRequests widget counts maintenance requests with the status “open”, grouped by building, through the Local API. Passing the user’s request with overrideAccess: false, as Payload’s own widget example does, makes the count respect the same access rules as the rest of the admin, so an agent sees only their own buildings if the rules say so. In Payload 4.0, the Local API enforces access rules by default, so a call without the flag behaves the same way (Payload’s 4.0 migration guide). A defaultLayout function sets the starting arrangement per user, such as a wider requests widget for the office manager.
A dashboard can also be a set of custom views, like the frozen meal brand’s delivery dashboard above. Views suit work that needs its own date picker, tabs and printouts, and widgets suit the few numbers your team wants on the first page after login.
The dashboard code moved between packages for 4.0. In 3.92.1 it ships inside @payloadcms/next, and in the 4.0 beta it lives in @payloadcms/ui, so it no longer depends on Next.js (@payloadcms/next on jsDelivr). The beta also adds a recents widget that opens on recently viewed documents when nothing is pinned (Payload’s 4.0.0-beta.4 release). Our guide to what you can build with Payload shows the kinds of internal tools these dashboards front.
Should you start on Payload 4.0 or the latest stable release?
Build anything going to production on the latest stable release, and try 4.0 in a branch. As of 4 November 2026, 4.0 is a beta, with seven beta releases between 9 and 29 October, and Payload labels its dashboard widgets experimental in both lines (Payload’s GitHub releases).
For a new build that won’t launch for a while, starting on the beta can save an upgrade later, as long as your team can absorb breaking changes between betas. npx create-payload-app@beta starts a 4.0 project. For a live site, wait for the stable release, run Payload’s codemod, then work through the cases the migration guide says it leaves behind (Payload’s 4.0 migration guide).
Either way, write new admin customisations so they move easily. Keep colour overrides in one stylesheet, import router hooks through one file of your own, and avoid importing Payload’s internal components by deep paths.
What moving an existing admin panel to 4.0 touches
We checked our own monorepo template against Payload’s v4 migration guide on 4 November 2026. The template runs Payload 3.90.1 on Next.js 15.4.11, with an admin panel close to the default, a custom title suffix, a provider that loads the code editor for JSON and code fields from the app itself, and a stylesheet in custom.scss.
Six items in the migration guide touch it.
| What changes in 4.0 | What it means in the template |
|---|---|
| Node.js 24.22.1 and Next.js 16.4.0 minimums | Upgrade Node.js and Next.js first, before Payload |
Sass removed, --theme-* retired | Rename custom.scss to custom.css and rewrite any variable it references |
Admin elements moved from @payloadcms/next to @payloadcms/ui | The generated import map points at @payloadcms/next/rsc#CollectionCards, so regenerate it after upgrading |
| Versions on by default | Only the pages collection sets versions today, so every other non-auth collection, in the template and in plugins that don’t set their own, would gain a version table |
| Authorship on by default | Collections gain createdBy and updatedBy, except those from plugins that opt out, such as search and ecommerce |
| Local API enforces access by default | Every Local API call in the template’s hooks, routes and views that doesn’t set overrideAccess starts applying access rules, so each one needs a decision |
The last two change the database, so they need a migration. In development, Payload pushes the schema for you, and in production you generate a migration with payload migrate:create and run payload migrate (Payload’s 4.0 migration guide). If a collection shouldn’t keep history, such as the template’s log of WhatsApp messages or its workflow run logs, set versions: false on it before you upgrade.
For your own project, the checklist runs in this order.
- Upgrade Node.js and Next.js to the new minimums.
- Run
npx @payloadcms/codemod@betaon a branch, ornpx @payloadcms/codemod@beta upgradefor the agent-assisted run. - Rename your
.scssfiles and update colour variables. - Replace
next/navigationandnext/linkimports in admin components. - Decide
versionsandauthorshipper collection, then create and run the migration. - Review the Local API calls where the codemod set
overrideAccess: true, and remove it wherever the call acts for a signed-in user. - Run
payload generate:importmapand open every custom view.
If your admin panel has grown into a set of internal tools, our Payload development team can scope the upgrade with you.
