--- name: add-sona-component description: >- Integrate a new component into the Sona UI library end to end — the full per-component pipeline of writing the component, demo, docs, registry entry, nav link, playground controls, regenerating the registry, and verifying it live. Use this whenever the user wants to add, create, scaffold, register, or "wire up" a new component in this repo (sona-ui), or mentions doing "the steps" / "the pipeline" to bring a component into the library — even if they only hand you the component code or just a name and an idea. Trigger it for phrases like "add a component", "new component", "integrate this into the registry", "scaffold a component", or "set up the docs/playground for X". --- # Add a component to Sona UI This skill captures the complete pipeline for landing a new component in this library so nothing is forgotten. The library is a shadcn-style registry: source components live in `src/registry/`, are described in a hand-authored registry JSON, surfaced in docs (MDX) and a live playground, and then compiled by a build script into generated artifacts that the app and the `shadcn` CLI consume. The golden rule: **you hand-author seven things, then run the build commands that regenerate everything else.** Editing a generated file directly is wasted work — the next build overwrites it. ## The canonical reference `spotlight-card` is the cleanest existing example of every step done correctly. Before writing anything, read these to match the house style exactly: - `src/registry/sonaui/spotlight-card/spotlight-card.tsx` - `src/registry/examples/spotlight-card/spotlight-card-demo.tsx` - `src/content/docs/spotlight-card.mdx` - the `spotlight-card` entries in `src/registry/registry.json`, `src/registry/agent-metadata.ts`, `src/config/components.ts`, and `src/registry/playground/index.tsx` Mirror its structure for the new component rather than inventing a layout. ## Inputs to settle first Pin these down before editing (ask the user only for what you can't infer): - **Slug**: kebab-case, used everywhere as the key (`spotlight-card`). Directory names, registry `name`, doc filename, and every registry key must match it. - **Display title**: Title Case (`Spotlight Card`). - **Category**: which nav group in `components.ts` (`Components`, `Text`, `Effects`, …). The user's pipeline note calls for an **Effects** category — use it if the component is a visual effect, otherwise pick the fitting existing one. - **Props**: name, type, default, one-line description for each — these flow into the generated prop table, so get them right at the source. - **npm dependencies**: runtime packages the component imports (e.g. `motion`). ## The seven hand-authored edits Do these in order. Match formatting, the `cn` import, `"use client"`, and the `export default` convention from the reference. ### 1. Component source — `src/registry/sonaui//.tsx` The real component. Export an interface named `Props` and **JSDoc every prop** — the `@default` tag and the `/** … */` description are parsed verbatim by the prop-types build into the docs table. A missing JSDoc comment means a blank cell in the published props table, so treat the comments as user-facing. Include `@default` on every optional prop. If the component needs extra files (CSS module, sub-component), add them in the same folder — the build picks up every file in the directory. ### 2. Demo — `src/registry/examples//-demo.tsx` The default, prop-less example shown in the docs Preview. File name `-demo.tsx` maps to the `default` variant. For extra variants, add `-.tsx` in the same folder (the build keys them by the suffix after the component name; see `parseFileName` in `scripts/build-registry.ts`). ### 3. Registry entry — `src/registry/registry.json` This is the hand-authored source of truth (a JSON **array**), NOT the root `registry.json` or `public/r/*` — those are generated. Add an object with a real `title`, a real `description` (a sentence about what it does, not "Component for "), the file path(s) under `files`, and `dependencies` listing the npm packages from step 1. Follow the exact shape of the spotlight-card entry. ### 4. Docs — `src/content/docs/.mdx` Copy the spotlight-card MDX skeleton: frontmatter (`title`, `slug`, `tags`), an intro, a `## Features` list, then the standard MDX component blocks in this order — ``, `## Playground` + ``, `## Installation` + ``, `## Usage` + ``, `## Props` + ``. The prop table is **derived** — don't hand-write prop rows in the MDX. ### 5. Nav entry — `src/config/components.ts` Add one object to `componentNavigationLinks`: `name` (Title), `slug`, `href: "/docs/"`, and `type` set to the chosen category. If the category is new (e.g. first **Effects** entry didn't exist yet) just use the string — the nav groups by `type` automatically. ### 6. Playground controls — `src/registry/playground/index.tsx` Import the component at the top, then add one entry to `playgroundRegistry` keyed by slug: a `controls` array (slider / text / toggle / select — see the `Control` union at the top of the file) for the props worth exposing, and a `render` that instantiates the real component with the live values cast to their types. This file is intentionally hand-authored and decoupled from the generated example registry. ### 7. Agent metadata — `src/registry/agent-metadata.ts` Add a `""` entry to the `agentResourceMetadata` object with `useWhen`, `avoidWhen`, `capabilities`, `accessibility`, `motion` (`purpose` + `reducedMotion`), and a `related` array of sibling slugs. Mirror the spotlight-card entry's shape. Without it, `bun run check:agent-resources` rejects the publish — every `registry:ui` item must have a matching entry. ## Then build — regenerate everything else ```bash bun run build:registry bun run build:agent-resources bun run check:registry bun run check:agent-resources ``` `build:registry` runs three scripts in sequence and regenerates: - `src/registry/index.ts` (the example registry + code strings) - root `registry.json` and `public/r/*.json` (shadcn CLI registry) - `src/registry/prop-types.ts` (the props table data, parsed from your JSDoc) `build:agent-resources` regenerates `public/agent/catalog.json`, the per-component detail JSON at `public/agent/components/.json`, and `public/llms.txt` / `public/llms-full.txt` from the `agent-metadata.ts` entry added in step 7. All of these are **generated — never edit them by hand.** If a prop is missing or a description is wrong in the output, fix the JSDoc in step 1 (or the metadata in step 7) and rebuild. Do not treat the component as published until both `check:registry` and `check:agent-resources` pass. After building, sanity-check that the new slug appears in `src/registry/prop-types.ts` with all expected props, and that `public/r/.json` and `public/agent/components/.json` were created. ## Finally — verify live in the preview The component isn't "done" until you've seen it work. Use the preview tools (not a manual hand-off): 1. Start the dev server (`preview_start`) if one isn't running. 2. Navigate to `/docs/` and `preview_snapshot` to confirm the page renders with Preview, Playground, Installation, Usage, and the Props table populated. 3. Exercise the actual interaction (hover, drag, type into a playground control) with `preview_click` / `preview_fill` / `preview_eval`, then re-snapshot or `preview_screenshot` to prove the effect and the playground controls work. 4. Check `preview_console_logs` for errors. Report what you verified with a screenshot or snapshot, and call out anything the user still needs to decide (e.g. extra variants, copy tweaks). ## Quick checklist - [ ] `src/registry/sonaui//.tsx` — component + JSDoc'd `Props` - [ ] `src/registry/examples//-demo.tsx` — default demo (+ variants) - [ ] `src/registry/registry.json` — entry with real title/description/dependencies - [ ] `src/content/docs/.mdx` — Preview · Playground · Installation · Usage · PropTable - [ ] `src/config/components.ts` — nav entry under the right category - [ ] `src/registry/playground/index.tsx` — import + controls/render entry - [ ] `src/registry/agent-metadata.ts` — `` entry with useWhen/avoidWhen/capabilities/accessibility/motion - [ ] `bun run build:registry` — regenerates index.ts, public/r/*.json, prop-types.ts - [ ] `bun run build:agent-resources` — regenerates public/agent/*, public/llms*.txt - [ ] `bun run check:registry` and `bun run check:agent-resources` — both pass - [ ] Verified live in preview (DOM + interaction)