The backend to build the modern web.

$npx create-payload-app Get a Demo
Press K to search the docs
Collections  /  PostsDraft
Building a headless CMSPublished
Access control in depthDraft
Migrating from v2Published
Local API patternsDraft
Deploying to VercelPublished
Product

Config as code, admin as a Next.js app

TypeScript config

Collections, fields and access control are declared in code and typed end to end.

Local API

Query your own database directly from server components — no HTTP round trip.

Own your data

Postgres, MongoDB or SQLite, self-hosted anywhere you already deploy.

// payload.config.ts export default buildConfig({ collections: [Posts, Media, Users], db: postgresAdapter({ pool: { connectionString: env.DATABASE_URI } }), admin: { user: Users.slug }, })
Controls

No accent — emphasis is inversion

Info Success Warning Error
Search the docs access control npx create-payload-app

The one filled button is 28px at the system’s only meaningful radius, 4px; everything else is square. CTA cells run 68–72px full-width between rails. Status chips are always a matched -bg / -border / -text triple rather than an improvised alpha. A focus recipe was not captured — the focused field above steps its border to #ffffff.

Typography

One family, tracking at -5%

h1 · untitledSans · 64/64 · 500 · -3.2px (-5%)The modern web.
h2 · untitledSans · 48/48 · 500 · -2.4px (-5%)Config as code
h3 · untitledSans · 24/28.8 · 500 · -1.2px (-5%)TypeScript config
Body · untitledSans · 16/22.4 · 400 · normalCollections, fields and access control are declared in code.
Nav link · untitledSans · 16/22.4 · 500 · normalProduct · Why Payload · Developers · Docs
Small / meta · untitledSans · 15/18 · 400 · normalGet Started
Install command · GeistMono · 14/19.6 · 400 · normal$ npx create-payload-app
Palette

A full ramp, mostly held in reserve

Text & rails
elevation-1000 / text#ffffff
text-darkrgba(255,255,255,.50)
railrgba(255,255,255,.13)
rail-softrgba(255,255,255,.05)
tint / hoverrgba(255,255,255,.10)
Neutral ramp — --color-base-* in 5% steps (--theme-elevation-* is this ramp reversed)
1000 / elev-0#000000
950 / elev-50#070707
900 / elev-100#141414
850 / elev-150#222222
800 / elev-200#2f2f2f
750#3c3c3c
700#4a4a4a
650#575757
600#656565
550#727272
500#808080
450#8d8d8d
400#9a9a9a
350#a8a8a8
300#b5b5b5
250#c3c3c3
200#d0d0d0
150#dddddd
100#ebebeb
50#f5f5f5
Hues — blue is the banner and the info/success role; the rest wait for status
blue-100#e5f2f7
blue-500 / success#007fae
blue-900 / banner#001923
blue-bg-light#d1e5ef
purple-50#fef5fe
purple-500#f799f7
purple-900#311f31
error-500#ff876f
error-bg-dark#331b16
error-text-dark#ffd5cc
warning-500#f4ac4f
orange-bg-dark#332d21
orange-text-dark#ffe1a4
Depth & motion

Elevation is a colour, not a shadow

0 · everything structural
3px · 4 uses
4px · the filled button
8px · 2 uses
40px · 2 uses
100% · avatar
0
50
100
150
200
250
bevel · 0 -2px 0 inset + 0 0 1px 1px inset + 0 2px 2px
throw · rgba(0,0,0,.5) 0 48px 64px 16px
contact · rgba(0,0,0,.5) 0 0 4px 0
the rail · how blocks actually separate

The house curve is an expo-out, cubic-bezier(0.165, 0.84, 0.44, 1): 0.15s for hover (85 elements), 0.35s and 0.45s for reveals, with one 0.3s ease-in-out outlier. One backdrop-filter: blur(32px), one background video, no canvas, no gradients, no grain.