New design system component

Add a component to the Fly Studio design system: the four files, two registrations, generators and checks. Use when a component doesn't exist yet, especially described in design terms.

Sby Skills Guide Bot
DevelopmentAdvanced
109/2/2026
Claude CodeCursorWindsurfCopilotCodex
#design-system#new-component#component-creation#typescript

Recommended for


name: new-component description: Add a new component to the Fly Studio design system — the four files, the two registrations, the generators and the checks. Use when someone wants a component that does not exist yet, especially when they describe it in design terms rather than as code. Gates on the rule sentence and usedIn before writing anything.

Add a component to the design system

You are landing a new component in maestro-ui. The person asking may be a designer who does not write TypeScript — they own the three decisions below, you own everything else.

The procedure is .archcore/guides/add-a-component.guide.md (mechanics) and .archcore/guides/author-a-component-as-a-designer.guide.md (what to decide). Read whichever you need; do not re-derive them here.

Before writing a single file

Three things must be settled. Ask for any that is missing — do not invent them.

  1. The rule sentence. One sentence stating the system decision this component carries and that is not negotiable when you use it. A constraint, not a description.

    This is a hard gate. If the answer is a paraphrase of the component's name, say so plainly and propose the alternative: a variant prop on the component it resembles. docs/rules.md is the page this sentence goes on, in the company of 18 others — read it if you need the calibration.

  2. At least one usedIn: { area, route }. area is one of exactly ten: All, Cinema, Playgrounds, Music Generation, Dubbing, Scripts, Libraries, Analytics, Settings, Trash. All means genuinely cross-cutting, not "I did not check". An empty list is a compile error, so this cannot be deferred.

  3. category — exactly one of Action, Input, Navigation, Generation, Data, Feedback.

Then check it does not already exist: read docs/rules.md and src/index.ts. If something close exists, say so and let them decide before you write files.

Tokens

Every value comes from src/styles/index.css. Read the existing token names before concluding one is missing — docs/foundation/ explains the scales.

If a token genuinely has to be added: add it to both the :root, [data-theme="dark"] block and the [data-theme="light"] block, then run pnpm gen:tokens before writing the meta, or tokens will not typecheck. A token in one theme only is a dark: in disguise, and this system does not allow dark:.

Flag a token addition explicitly in your summary. It is a bigger change than the component: a new word in the vocabulary every screen can now use.

If the new token belongs to a prefixed namespace (--text-fly-*, --radius-fly-*, --shadow-fly-*, --blur-fly-*, --leading-fly-*, --tracking-fly-*, --font-fly-*, --ease-fly*), register the generated utility name in src/lib/cn.ts too. Check 12 fails on it, and the symptom if it slips through is a component whose colour is silently deleted.

Write it

Four files in src/components/<id>/, <id> in kebab-case:

  • v1/<id>.tsxcva + cn, forwardRef, exports Props, accepts className merged last with cn(). No hex, no rgb(), no dark:, no arbitrary values. 'use client' only if it holds state or an effect — today only three components do, and PromptBox is the shape to copy for a controlled component.
  • v1/<id>.meta.tsdefineMeta({ ..., version: 1 }). Copy the shape from a neighbour; src/components/metric-delta/v1/metric-delta.meta.ts is a compact one. props must describe the real signature. Include do and dont.
  • versions.ts — data only, never imports the component.
  • index.ts — re-exports the component, its Props, and the versions.

Then register twice: src/index.ts (component + Props) and src/meta.ts (the meta in COMPONENTS, the array in ALL_VERSIONS, importing from ./components/<id>/versionsnever from the component's index.ts, because @fly-media/maestro-ui/meta has to stay React-free for Server Components).

Examples

At least one, and it must run. The explorer's preview is examples[].code compiled in the browser — the example is simultaneously the documentation, the test and the screenshot. It may only reference names in playground/src/live/scope.tsx; anything else it needs, it declares in a prelude. Check 9 executes every example, so a bad one fails the build rather than rendering blank.

Finish

pnpm gen && pnpm check

Then pnpm shoot <id> and tell them to look at both themes in .shots/. A component that only works in Dark is the most common thing caught late here.

pnpm check must be green — 12 checks. If git status shows no generated files changed, pnpm gen never saw the meta and a registration is missing.

Report: the rule sentence as it will appear in docs/rules.md, any token added, and the two screenshot paths. Do not commit or push unless asked.

Related skills