Architecture
The repository is split between a Fumadocs site and Payload-targeted component tooling.
Payload Components is two projects living in one repository — and they deliberately never share a Payload runtime.
Site runtime
A Fumadocs + Next.js app: the landing, these docs, and the component catalog. Boots
with no database, no PAYLOAD_SECRET, and no admin.
Component runtime
The Payload block code the CLI installs into your repo. It only ever runs there, against real Payload project shapes.
The two responsibilities are:
- Run a documentation and catalog site.
- Build, validate, and distribute Payload component installs.
Those responsibilities should not share a Payload runtime.
Site runtime
The site runtime is Fumadocs on Next.js. Everything it needs lives in the app tree:
src/appcontains the app router routes.content/docscontains MDX documentation.source.config.tsdefines the Fumadocs MDX collection.src/lib/source.tsexposes the loaded docs source.src/app/api/search/route.tsexposes Fumadocs search.
No Payload admin, collection config, global config, database adapter, or Payload local API is required for the site to boot.
AI-readable surfaces
The site exposes the same docs in browser and machine-readable formats:
/llms.txtpublishes the concise source map for AI crawlers./llms-full.txtpublishes the compiled documentation body./llms.mdx/docs/**/content.mdpublishes each docs page as markdown.- JSON-LD marks the site, CLI, FAQ, component catalog, and docs articles for structured extraction.
Component runtime
The component runtime is external. A component installs into a supported Payload v3 + Next.js project, where the Payload-specific files actually live:
- block configs
- frontend block components
RenderBlocksregistration fragmentsPagescollection layout fragmentsgenerate:typesandgenerate:importmappost-install tasks
Registry source
The shadcn-compatible registry reads source files from payload-components/source and emits public JSON to public/r.
That keeps Payload-specific component source out of the Fumadocs app tree while preserving install targets like ~/src/blocks/HeroBasic/Component.tsx.
Component families and shared code
A component family ships one installable component per structural variant — logo-cloud-grid, logo-cloud-marquee, logo-cloud-inline — each its own registry item and manifest. Variant selection is the catalog and the install command, never an interactive prompt. Content-level variation (optional or extra editor fields) lives in the Payload block config, not a separate component.
Variants that share fields or markup reference a common source file under payload-components/source/blocks/shared, installed once into the consumer repo — for example ~/src/blocks/shared/logoCloudFields.ts — and composed by each variant config as fields: [...logoCloudFields, /* variant-specific */]. Editing the shared file updates every installed variant; re-running an install never overwrites an edited copy. Internal shared modules ship as registry files, not registryDependencies (which resolve only public shadcn components).
Why this split matters
A docs site should build without a database, Payload secret, or admin import map. A Payload component should still be tested against real Payload project shapes. Splitting the app runtime from the install target keeps both jobs honest.