Add a component, fix a bug, improve the docs.
git clone https://github.com/nikhils4/ui-beats.git
cd ui-beats
corepack enable
yarn install
yarn devRequires Node 20.9 or newer and Yarn 4 via Corepack. Before opening a PR, run what CI runs: yarn lint, yarn format:check, yarn typecheck, yarn test, yarn build and yarn test:e2e. A fifth job diffs motion frames against pixel baselines; see below.
It writes four files, edits three registries and leaves a stub that compiles, renders and passes the suite, so your first test run tells you about your component rather than about a wiring mistake. Then replace the TODOs.
yarn new:component --name flip-clock --category card--category is one of animation, background, button, card, component or text. Blocks are hand-authored.
Seven places, three of them registries. The scaffolder edits all of them; this is what it did.
components/demo/<category>/<name>.tsx # the component people install
components/usage/<category>/<name>.usage.tsx # a runnable example, no props
components/playground/<cat>/<name>.playground.tsx # optional studio harness
content/docs/<category>/<name>.content.ts # title, description, props, credits
content/docs/index.ts # one import + one array entry
components/website/component-preview.tsx # "<category>/<name>" preview entry
components/website/playground-harnesses.tsx # the same, if you wrote a harnessEverything else is generated from those: the sidebar, the command menu, the category pages, the docs page and its markdown twin, the sitemap, llms.txt, the OG card and the shadcn registry under public/r/. The MCP server reads the deployed catalogue at runtime, so a new component reaches it on deploy with no release. There is no central list to keep up to date, but miss the preview map and the test suite says so by name.
Four of these fields are enforced by tests rather than by review.
name, category and the filename all have to agree: the route, the sidebar and the registry key off the triple.description is the meta description, the registry entry and the MCP catalogue text, not just page copy. Lead with what the component does.whenToUse is where the component fits and where it does not: over 80 characters, unique across the library, and not a restatement of the description.addedAt is YYYY-MM-DD. The New badge is derived from it and ages out on its own.credits is required. Use kind: "tool" if a model wrote it; crediting one as a person makes the page copy and the structured data both wrong.props needs at least one row, and it is also where the Motion Studio gets its controls, so prop names decide control ranges.any, and no non-null assertions.motion is fine, a new charting library is not. Whatever the component imports becomes a dependency for everyone who installs it, read straight off the imports.bg-background, text-muted-foreground) rather than hardcoded colours. A colour shadcn does not define has to be declared in config/tokens.ts so the registry ships it; otherwise it renders here and breaks on install.Math.random() or Date.now() during render. Use useId() for stable variation.prefers-reduced-motion for anything that moves, and use the value you read. The suite fails a component that ignores the preference, and a second one checks the component is actually visible with motion off.Every component is screenshotted at 0 ms, 300 ms and 1200 ms against a frozen clock, so a regression mid-transition fails a PR instead of shipping.
Baselines are platform-specific and only the Linux set is committed. Locally, yarn test:visual writes your own on first run and gitignores them. On CI, a new component has no baseline yet, so the Motion frames job writes three PNGs and fails. Download the visual-baselines artifact from that run, commit them under tests/visual/__screenshots__/linux/, and push. Look at frame 0 before you do: a component already settled there has lost its entrance animation.
git checkout -b feat/your-component
git commit -m "feat(card): add tilt card"
git push origin feat/your-componentOne component per PR. Include a screenshot or screen recording in the description, and explain why rather than what; the diff already says what. Contributors are credited on their component's docs page.