Contributing
Work on the Atomic Payload monorepo: its workspace layout, local development commands, and the standard plugin shape.
Atomic Payload is a pnpm workspace: the publishable @pro-laico/* packages, a full starter template, minimal example apps, release tooling, and these docs all live in one repo. This page is the map for contributors and maintainers.
Monorepo structure
atomic-payload/
├── packages/
│ ├── create-atomic-payload/ # CLI that scaffolds new projects
│ ├── core/ # Kernel (PayloadAugment, Get<>, ExtractOrDefault), revalidate hooks, cache helpers, APF runtime, plugin
│ ├── zap/ # zod + AtomicRegistry helper
│ ├── atomic/ # actions, hook (createAtomicHook + cssProcessor), forms, children — runtime + admin UI
│ ├── site/ # sitePlugin: Pages, Header, Footer, SiteMetaData, Settings, Storage globals
│ ├── styles/ # stylesPlugin: designSet + shortcutSet collections, className field, CSS storage globals, token fields, cssProcessor + cssHook + processDesignSet (all CSS handling)
│ ├── icons/ # iconsPlugin: Icon + iconSet collections, formatSVG, AtomicIcon
│ ├── images/ # Images + Favicons collections + FaviconField + blur integration
│ ├── fonts/ # fontsPlugin + Font collection + font download CLI
│ ├── mux-video/ # MuxVideo wrapper plugin
│ ├── tracking/ # trackingPlugin: Tracking global + GTM/PostHog/Vercel providers
│ ├── richtext/ # RichTextChild block + default Lexical editor + JSX renderer
│ └── seed/ # seedPlugin: opinionated seed data + /api/seed endpoint
├── templates/
│ └── atomic-payload/ # Full Atomic Payload starter (Payload + Next.js + Tailwind)
├── examples/ # Minimal single-plugin demo apps (not full templates)
│ ├── fonts-only/ # Exercises @pro-laico/fonts in isolation
│ ├── icons-only/ # Exercises @pro-laico/icons in isolation
│ └── styles-only/ # Exercises @pro-laico/styles in isolation
├── tools/
│ └── releaser/ # @tools/releaser — lockstep versioning + npm publish (private)
└── package.json # Workspace rootThe publishable packages live in packages/*. templates/*, examples/*, and tools/* are never published. They exist for local dev, regression testing, and release automation.
Local development
All commands run from the monorepo root.
# Install all workspace deps
pnpm install
# Freeze the committed (empty) font definition stubs — run once per clone
git update-index --skip-worktree examples/fonts-only/src/app/definition.ts templates/atomic-payload/src/app/definition.tsThe font src/app/definition.ts files are committed empty so pnpm dev works in a fresh clone, then rewritten locally by generate:fonts / setup:fonts. They're tracked but frozen with git update-index --skip-worktree, so regenerating fonts never shows up as a diff. Because skip-worktree is a local, per-clone setting (it isn't stored in the repo), run the command above once after cloning. To intentionally edit a stub, unfreeze it with git update-index --no-skip-worktree <path>.
# Typecheck every package, template, and example (stops at first failure)
pnpm typecheck
# Keep going on failure so you see every package's errors in one run
pnpm -r --no-bail typecheck
# Run all typechecks concurrently (faster, interleaved output)
pnpm -r --parallel typecheck
# Lint every workspace project
pnpm lint# Typecheck a single package by name
pnpm --filter @pro-laico/core typecheck
# Typecheck only the @pro-laico/* packages
pnpm --filter "@pro-laico/*" typecheck
# Typecheck only the templates / examples (path globs)
pnpm --filter "./templates/*" typecheck
pnpm --filter "./examples/*" typecheck
# Build a single package (the ones that emit a dist/)
pnpm --filter @pro-laico/core build# next dev in templates/atomic-payload (the main reference template)
pnpm dev
# next build (includes the prebuild font download)
pnpm build
# Regenerate payload-types.ts + the augment .d.ts
pnpm generate:types
# Regenerate the admin importmap
pnpm generate:importmapThe template at templates/atomic-payload wires up every plugin, so running pnpm dev is the fastest way to see a change end-to-end against a real Payload + Next.js app.
Adding a plugin
New plugins live in packages/ and follow one standard shape, the same one every existing package uses, so the cleanest reference is any sibling package.
- The package can be used independently (
pnpm add @pro-laico/<name>) or via the template, referenced withworkspace:*for local dev. The CLI'sprepackstep rewrites thoseworkspace:*deps to caret-pinned versions when it bundles the scaffold tarball. - The standard shape: a
(opts) => (config) => configplugin factory exported as both the default and a named export, with the raw collections / hooks / fields / components also exported as named imports for advanced consumers. - A
schemasubpath exportspayload-augmenttypes sozapknows about the package's block shapes, and theindex.tsbarrel stays safe to import frompayload.config.ts(no client-only code). Client components and server-only utilities sit behind subpaths.
For how these pieces fit together at runtime, see the architecture guide.