MKT UI

Contributing

How to add a section without breaking the distribution rules.

The full contributor guide lives in CONTRIBUTING.md at the repository root. This page covers the rules that are easy to break by accident.

The dependency direction

app/ · components/site/ · components/docs/ · examples/   ───▶   registry/
registry/                                                 ───▶   (nothing here)

Everything installable lives in registry/. Those files are copied verbatim into other people's projects, so they may not import:

  • @/components/site/* or @/components/docs/*
  • @/lib/source, @/lib/catalog, @/app/*, @/examples/*
  • any fumadocs-* package
  • next or next/* — a consumer might be on Vite, React Router, or Astro
  • server-only / client-only

This is enforced by ESLint, not just by convention. pnpm lint fails if a registry file reaches outside its layer.

Adding a section

  1. Write a spec in planning/specs/<name>.md. Ten headings, listed in CONTRIBUTING.md — identity, purpose, content, composition, behavior, accessibility, integration, distribution, verification, documentation.
  2. Build it in registry/blocks/<name>.tsx, composing existing foundations rather than adding new padding and width values.
  3. Register it in registry.json with explicit dependencies and registryDependencies.
  4. Add a preview to the allow-list in components/docs/previews.tsx.
  5. Document it in content/docs/sections/<name>.mdx and add it to content/docs/sections/meta.json.
  6. Use it in an example recipe. A section that has never been used in a real page composition has not been tested.
  7. Update planning/roadmap.md.
  8. Verify with pnpm check, then install it into the consumer fixture.

Checks before opening a pull request

pnpm check          # lint, typecheck, unit tests, registry validation
pnpm test:e2e       # page, keyboard, and accessibility checks

Requirements that are not optional

  • Responsive. Works at 375px, 768px, and 1440px with no horizontal overflow.
  • Keyboard. Every interactive element reachable, visible focus, dialogs return focus to their trigger.
  • Headings. Heading level is a prop, never hard-coded to h2 with no way out.
  • Long copy. Test with a headline twice as long as your example.
  • Missing media. Optional images can be absent without the layout collapsing.
  • Reduced motion. Honored globally; do not opt out of it.
  • Forms cover every state in Forms & booking.
  • Fictional proof is labeled. Invented testimonials, results, and credentials must be identified as invented on any page that shows them.

On this page