Documentation

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:

  1. Run a documentation and catalog site.
  2. 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:

api/search/route.ts
*.mdx
source.config.ts
src/lib/source.ts
  • src/app contains the app router routes.
  • content/docs contains MDX documentation.
  • source.config.ts defines the Fumadocs MDX collection.
  • src/lib/source.ts exposes the loaded docs source.
  • src/app/api/search/route.ts exposes 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.txt publishes the concise source map for AI crawlers.
  • /llms-full.txt publishes compiled documentation and blog bodies.
  • /llms.mdx/docs/**/content.md publishes each docs page as markdown.
  • /feed.xml publishes source-dated blog updates as RSS.
  • JSON-LD marks the site, CLI, FAQ, component catalog, blog, posts, and docs articles for structured extraction.

AI discovery and verification documents the evidence model, ownership, validation commands, and external maintainer checks for these surfaces.

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
  • RenderBlocks registration fragments
  • Pages collection layout fragments
  • generate:types and generate:importmap post-install tasks

CLI and database boundary

payload-components add <component> owns five idempotent install stages in the consumer project: registry build, registry add, dependency install, Payload fragment application, and post-install generation. It records installed or partial state under .payload-components/state.json so an interrupted install can be inspected and retried safely.

Optional demo seeding stays outside that pipeline's trust boundary. The seed <component> command, and the final --demo step after a successful add, validate the recorded install, dependencies, registry dependencies, installed files, and fragments. They atomically write payload-components/seed-<component>.ts and initialize a private high-entropy ownership record under .payload-components/demo-state/. The CLI does not import Payload, open a database, or make a network request during seed generation.

The operator reviews that generated source and explicitly runs it with the consumer project's Payload CLI. Only then does the script use the Local API. It requires Pages drafts and refuses database-visible markers as ownership proof. It creates a draft only when the slug is free, then records the new Page and Media IDs locally. Reruns require those exact IDs and the private tokenized markers; updates set overrideLock: false, and generated code never deletes media. This keeps elevated overrideAccess calls visible in operator-run target code instead of hiding them inside the distribution CLI.

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.

On this page