Payload Components is an MIT, community-first registry and CLI for
installing typed Payload CMS blocks into Payload v3 + Next.js projects.
It copies the files, wires Payload config, regenerates generated artifacts,
and leaves the whole install as a reviewable git diff.
A plain shadcn add copies files. payload-components add goes further:
copies component source through the shadcn-compatible registry;
registers the block in the Pages collection;
maps the frontend renderer;
regenerates Payload types and the admin import map;
records install state so reruns converge instead of duplicating wiring.
This repository has two jobs:
the Fumadocs-powered Next.js site for the landing page, docs, component
catalog, search, Open Graph images, and AI-readable text surfaces;
the payload-components registry and CLI that install blocks into consumer
Payload projects.
This repository is not a Payload CMS runtime app. The docs site does not need
Payload admin routes, collections, globals, a database adapter, or
PAYLOAD_SECRET.
(back to top)
Why It Exists
Payload blocks are not live when their files land.
They have to be registered, rendered, typed, and added to the admin import map.
That wiring is repetitive, easy to drift, and usually rediscovered project by
project.
Payload Components packages the block source and the wiring contract together.
The goal is a catalog that grows from real installs and pull requests: MIT,
open source, no pricing tiers, no license keys, no gated component access.
(back to top)
What Makes This Different
MIT end to end: registry, CLI, components, and docs site.
No license keys, gated components, or paid component tiers.
Community-driven requests and pull requests decide what ships next.
One command installs source files plus the Payload wiring that makes them live.
(back to top)
Built With
Next.js
React
Fumadocs
Payload CMS
shadcn Registry
TypeScript
Tailwind CSS
Playwright
Vitest
(back to top)
What Lives Here
Path
Purpose
src/app
Next.js routes, homepage, catalog, docs, search, and OG
src/components/site
Site UI, landing sections, install replay, cards, and demos
src/lib/site.ts
Shared site copy, component entries, FAQ, and demo data
content/docs
Fumadocs MDX documentation
payload-components/registry.json
Source shadcn registry definition
payload-components/source
Payload target source files shipped into consumer repos
There are two workflows: installing components into a Payload project, and
working on this repository.
Use A Component
Run the CLI from the root of a supported Payload v3 + Next.js project:
sh
npx payload-components add hero-basic
Preview the same validation and install plan without changing files, installing
dependencies, running generation commands, or updating install state:
sh
npx payload-components add hero-basic --dry-run
The preview lists the component files, RenderBlocks.tsx renderer mapping,
Pages/index.ts block registration, package dependencies, and post-install
commands the real install would use.
To also write a prefilled demo script after the install succeeds, opt in with
--demo, then run the generated TypeScript through your project's Payload CLI:
sh
npx payload-components add hero-basic --demopnpm exec payload run payload-components/seed-hero-basic.ts
For a component that is already installed, the standalone command writes the
same script:
sh
npx payload-components seed hero-basicpnpm exec payload run payload-components/seed-hero-basic.ts
seed requires a healthy installed-state record, compatible dependencies, every
manifest and registry-dependency file, and all Payload wiring fragments. It
writes the reviewable script plus a private ownership record under
.payload-components/demo-state/. The generated script requires Pages drafts
before querying or changing content, then creates a component-specific draft
Page at /payload-components-demo-hero-basic; it never publishes the demo. A
rerun updates only the exact Page ID recorded locally after verifying its
tokenized block marker. Placeholder media is reused only by its recorded ID and
is never deduplicated or deleted automatically. Before each create, the script
atomically journals a unique operation token; after an interruption it can
adopt only the single Page or Media carrying that exact private token and record
its returned ID before continuing. Any collision or missing,
mismatched, or unreadable ownership record stops before unsafe mutation. The CLI
atomically replaces only its version-marked generated script and refuses unowned
files or pre-existing symlinks. The operator-run script deliberately uses
overrideAccess: true, with overrideLock: false for updates, so review it in
git and run it only against the intended database.
Good first installs:
Component
Use it for
hero-basic
A headline-led page hero
feature-grid-basic
A repeatable feature grid
feature-split
A two-column feature section
content-columns
Editorial content columns
logo-cloud-grid
A trust-logo wall
integration-grid
Integration cards
Browse the full, current set in the component catalog.
All components
Every installable registry item, in catalog order. This table and the CLI's
Current components help output are both verified against
payload-components/registry.json by a focused test, so neither can silently
drift from the registry.
add-template installs and wires the whole block set and prints which blocks
each page uses. Add --demo to also write one seed script per page, each
creating a draft Page from the blocks that page composes. Seeded content is each
block's own sample content, not the curated copy shown on the site.
Mark a block's text fields as localized for Payload localization:
sh
npx payload-components add hero-basic --localized
This also installs src/blocks/shared/localizeFields.ts and wraps the block
config's field list in it, so the shared family base is covered too. Enable
localization in your Payload config for it to take effect, and migrate existing
data before adopting it on a populated collection.
Maintain an install
Recorded installs have a full lifecycle, not just a first run:
sh
npx payload-components list # catalog vs what this project recordednpx payload-components diff # version, file, and wiring driftnpx payload-components update # re-install anything behind this CLInpx payload-components remove hero-basic # delete owned files and unwire the block
diff exits non-zero when anything has drifted, so CI can gate on it. update
never overwrites a file you have edited — it skips that component and exits
non-zero until you pass --force. remove deletes only the files no other
installed component ships, so a shared family base survives while a sibling
variant is still installed; package dependencies are always left in place.
list and diff accept --json, and update and remove accept --dry-run.
Starting from a bare create-payload-app project? Lay down the base an install
needs — the Pages and Media collections, the blocks renderer, and the cn /
CMSLink / Media / linkGroup primitives every block imports:
sh
npx payload-components init --scaffold
Nothing is overwritten: files you already have are kept, and a re-run creates
nothing. The result is the official starter's shape, so the project then detects
as payload-website-starter.
Check a target project without changing files:
sh
npx payload-components doctor
doctor validates the supported project shape, resolves which files carry the
wiring, and checks required post-install scripts and any recorded
.payload-components/state.json installs.
Use it from a coding agent
payload-components mcp runs a Model Context Protocol server over stdio so an
agent can browse the registry, read a component's install contract, and preview
what an install would change:
Every tool is read-only by design. The server answers which block and what will
it change; installing stays an explicit payload-components add run in your
shell, where the diff is visible and approvable.
(back to top)
Run This Repo Locally
Use these steps to run the docs site and registry tooling.
Prerequisites:
Node.js ^20.19.0 || >=22.12.0
pnpm ^9 || ^10
Install and start:
sh
git clone https://github.com/Ducksss/payload-components.gitcd payload-componentspnpm install --frozen-lockfile --ignore-workspacepnpm source:buildpnpm dev
Open http://localhost:3000.
Useful local routes:
Route
Purpose
/
Product and docs homepage
/docs
Fumadocs documentation
/components
Component catalog
/api/search
Fumadocs search endpoint
/llms.txt, /llms-full.txt
AI-readable project summaries
/r/registry.json
Generated public registry
(back to top)
Usage
The installer runs five idempotent stages:
Build or resolve the public registry item.
Add component files through the shadcn registry.
Install required dependencies.
Apply Payload fragments for collection registration and renderer mapping.
Run post-install scripts for generated types and the admin import map.
Install state is written to .payload-components/state.json inside the
consumer project, so partial installs are visible and retries can converge.
Demo scripts are separate and opt-in. add <component> --demo writes one only
after those install stages and installed-state recording succeed;
seed <component> rejects recorded partial installs and verifies the installed
state, dependencies, manifest and registry-dependency files, and Payload
fragments again. Its separate private demo-state file records the IDs the
operator-run script may update.
Neither command opens a database. The CLI prints the package-manager-specific
payload run command that performs the database work in your project.
Recovering an interrupted install
If a stage fails, the component is recorded as partial and payload-components add
prints the failed stage, the last error, and the safest retry command. Fix the
reported cause, then rerun the same command from the project root:
sh
npx payload-components add hero-basicnpx payload-components doctor
Review the git diff before editing anything by hand. The CLI distinguishes two
kinds of files: owned component files (listed from the manifest, such as the
files under src/blocks/HeroBasic/) are safe to re-create by retrying, while
patched host files are project files the installer edited and may hold your own
work — normally src/blocks/RenderBlocks.tsx, src/collections/Pages/index.ts,
package.json, and the package manager lockfile.
Prefer forward fixes over deletion. Do not delete patched host files to recover.
Use payload-components doctor to see the failed stage, missing files, missing
Payload fragments, and the owned/patched file breakdown before and after retrying.
Useful checks while changing this repo:
Check
When to run
pnpm lint
After code changes to catch lint errors.
pnpm source:build
After docs/frontmatter changes, or before type-checking a fresh checkout; compiles Fumadocs content.
pnpm exec tsc --noEmit
After TypeScript changes, to type-check without writing build output.
pnpm test:registry
After registry changes; checks schema validity and generated-output reproducibility.
pnpm run test:int
After installer, manifest, docs, or source changes; covers those contracts.
E2E_PORT=3100 pnpm run test:e2e
After changes to site or browser behavior.
pnpm build
Before shipping, to validate the production build.
Run the full local release gate before shipping:
sh
pnpm test:release
(back to top)
Package Releases
Public installs use the npm package:
sh
npx payload-components add hero-basic
GitHub releases publish payload-components to npm and mirror
@ducksss/payload-components to GitHub Packages. Prerelease versions publish
under the next dist tag; stable versions publish under latest.
(back to top)
Roadmap
Payload Components stays open-source and community-first. The roadmap is about
improving the install contract, expanding useful blocks, and making real
contribution paths obvious.
Read ROADMAP.md for the current direction, or use
open issues for active work and component requests.
(back to top)
Community Examples
Sites and projects built with Payload Components. If you shipped something with
these blocks, add it here: open a pull request into dev
that appends one row to the table.
Site
Author
Tags
Source
Nothing listed yet, so the first row is available. Copy this, fill it in, and add
it to the end of the table:
Site: a public, working URL, linked from the bare domain.
Author: your GitHub handle, linked to your profile.
Tags: a few words on what the site is, or the component families it leans on.
Source: [↗](repository-url) when the code is public, - when it is not.
There is no minimum size and one installed block counts. Real installs are the
clearest signal about what to build next, so say in the pull request which
components you used and what you had to change.
(back to top)
Contributing
Contributions are welcome. The useful shape is a complete change: source,
manifest, docs, demo twin, and installer coverage together when adding or
changing a component.
Looking for a first issue? Both searches list currently open work, so they stay
accurate as issues land:
Good first issues - small, self-contained tasks that do
not assume prior context on the registry or CLI.
Help wanted - open work of any size where a contributor
would be welcome.
Community docs:
CONTRIBUTING.md - setup, branches, tests, and PR shape.
CODE_OF_CONDUCT.md - how we keep discussion useful.
SECURITY.md - how to report vulnerabilities privately.
ROADMAP.md - what is planned, and what is not.
Basic flow:
Fork the project.
Create a feature branch from dev.
Make the change with focused tests.
Run the relevant checks and note them in the pull request.
Open a pull request into dev.
(back to top)
License
Distributed under the MIT License. See LICENSE for more
information.