--- name: design-system description: | Use this skill BEFORE writing or restyling ANY user-facing interface. It drives the WrongStack Design Studio engine: commit to a kit, tune it (radius / density / font / motion), materialize the tokens into a real theme file, build against those tokens, then verify adherence. Trigger it whenever the user asks to build, redesign, restyle, "make it look better", or ship a UI, frontend, landing page, marketing site, dashboard, admin panel, settings screen, onboarding flow, component, modal, form, email template, mobile screen, or design system — and whenever Tailwind, shadcn/ui, React, Next.js, React Native, Flutter, SwiftUI, or Jetpack Compose styling, theming, colors, palette, dark mode, border-radius, spacing, elevation, shadows, typography, or fonts come up. Also trigger on softer phrasings that imply visual work: "clean up the layout", "it looks generic", "match our brand", "add dark mode". Trigger even when the user never says the word "design" — if the output has pixels, this skill runs first. version: 2.2.0 required-capabilities: [filesystem.read, filesystem.write, documentation.author] required-tools: [design] optional-capabilities: [browser.interact] --- # Design System Engine — WrongStack ## The contract Inspect the existing system first. Reuse its components, semantic tokens, framework and supported themes unless the user requests a replacement. The kit loop below applies to greenfield UI or an authorized system migration; an established project does not need a kit pin just to satisfy the scanner. Use the `design-craft` skill for substantial visual decisions and rendered review. Default-framework UI is a failure, not a neutral starting point. Unstyled shadcn, `bg-blue-500`, stock Bootstrap gray, or "I'll pick colors as I go" all produce the same forgettable result and leave the codebase with no source of truth. WrongStack ships a Design Studio: 50+ curated kits, each a complete **design system** — not a palette. Every kit carries its own radius scale, spacing rhythm, type ramp, motion curves, and elevation steps. The job here is to commit to ONE kit *before* any markup exists, push its tokens into a real file the build reads, and then write UI that only ever references those tokens. Tokens in a file beat design intentions in a prompt. That is the whole idea. --- ## The loop (never reorder; skip only explicit exceptions) ``` list → use → tune → materialize → BUILD → verify → fix drift ``` Steps 1–3 are cheap and happen before the first line of JSX/Dart/Swift. `tune` is optional when the chosen kit already fits; otherwise keep the order intact. If new UI lacks a token source, establish one before adding more styling. Existing project tokens are a valid source; do not restyle established UI merely because it has no kit pin. --- ## Step 1 — Commit to a kit ``` design {action:"list"} # browse available kits design {action:"foundations"} # read the stack-agnostic baseline design {action:"use", kit:"", stack:"web|react-native|flutter|swiftui|compose"} ``` `use` loads the kit's **full spec for that stack** — pass the right `stack` or the materialized output will be the wrong shape. | Target | `stack` | |---|---| | Next.js, Vite, Remix, any Tailwind v4 / shadcn web app | `web` | | Expo / bare React Native | `react-native` | | Flutter (any platform) | `flutter` | | iOS native | `swiftui` | | Android native | `compose` | ### Picking the kit If the user pinned one with `/design `, that decision is final — use it and move on. Otherwise: 1. Run `design {action:"list"}` and read the kit descriptions. Do not pick from memory; the roster changes. 2. Match the kit to the **product's tone**, not to personal taste. Useful signals to reason from: audience (consumer vs. operator vs. developer), information density (marketing page vs. data table), emotional register (playful, editorial, clinical, brutalist, corporate-trustworthy), and any brand assets the user already has. 3. If several kits fit, compare their layout, density and type implications; choose the best fit with a short rationale unless the user wants to choose or an unresolved requirement materially changes the outcome. 4. If the user gives zero signal and does not want to choose, pick the kit that best fits the product archetype, **say which one and why in one sentence**, and continue. Silence is not permission to fall back to defaults. To change kits later: `/design swap ` — this drops the old overrides deliberately, so re-apply any tuning that still matters afterward. --- ## Step 2 — Tune (optional, but prefer knobs over raw tokens) ``` design {action:"tune", tune:{ radius:"lg", density:"compact", font:"Space Grotesk", motion:"snappy" }} ``` | Knob | Values | Use it when | |---|---|---| | `radius` | `none` `sm` `md` `lg` `xl` `full`, or a base length like `"1rem"` | The kit's roundness fights the product's tone | | `density` | `compact` `cozy` `comfortable` | Scales the whole spacing rhythm — `compact` for dashboards and data tables, `comfortable` for marketing and mobile | | `font` | any family name | Brand typeface, or the kit's face is unavailable | | `motion` | `snappy` `smooth` `none` | Tool-like UI wants `snappy`; content sites want `smooth` | Knobs rescale the *entire* system coherently. Setting individual tokens by hand does not — a hand-edited radius leaves the other five steps of the scale untouched and the result reads as sloppy rather than intentional. For a genuinely specific color (brand primary, a mandated status color): ``` design {action:"set", set:{ primary:"oklch(62% 0.2 25)", "dark.bg":"#111" }} ``` Use the `design` tool's `set` action for the handful of values the brand actually dictates. Everything else stays on the kit. --- ## Step 3 — Materialize ``` design {action:"materialize"} design {action:"materialize", out:"src/theme/tokens.ts", force:true} ``` This writes the tuned tokens to a real theme file. Omit `out` for the conventional path, pass `out` for a custom project-relative path, and use `force:true` only when intentionally overwriting an existing file. Default paths and output shapes: - **web** → `src/styles/design-tokens.css`; CSS custom properties + a Tailwind v4 `@theme` block, in OKLCH - **react-native** → `src/theme/design-tokens.ts`; TypeScript `lightTheme` / `darkTheme` constants + numeric `scale` - **flutter** → `lib/theme/design_tokens.dart`; `AppColorsLight` / `AppColorsDark` classes + `AppScale` - **swiftui** → `Theme/DesignTokens.swift`; `AppColorsLight` / `AppColorsDark` enums + `AppScale` - **compose** → `ui/theme/DesignTokens.kt`; `AppColorsLight` / `AppColorsDark` objects + `AppScale` Then, without exception: 1. **Import the generated file** into the app entry (global stylesheet / theme provider / `MaterialApp` theme / etc.). Unimported tokens enforce nothing. 2. **Read the generated file before writing UI.** It is the ground truth for which token names exist. Do not guess names from this document or from another project — use the ones actually in the file. 3. Re-run the `design` tool with the `materialize` action after any later `tune` or `set`, or the code and the tokens silently diverge. --- ## Step 4 — Build against the tokens Because `materialize` maps the kit into `@theme`, the ordinary utilities now resolve to the kit. Write plain, semantic utilities: ```html

Title

Body copy.

``` Confirm the exact names against the materialized file — the token vocabulary is per-kit, and semantic slots (surface, muted, accent, destructive, ring…) vary. ### Drift — what it looks like and what to write instead | Don't | Why it breaks | Do | |---|---|---| | `bg-blue-500`, `text-gray-700` | Framework palette, not the kit — and no dark variant | `bg-primary`, `text-muted-fg` | | `#1f2937`, `oklch(...)` inline | Invisible to the theme; can't be re-tuned or swapped | `var(--color-bg)` or the matching semantic token | | `rounded-[7px]`, `p-[13px]` | Off-scale value; breaks the rhythm everywhere it appears | nearest step: `rounded-lg`, `p-3` | | `dark:bg-slate-900` hand-written | Two hardcoded themes instead of one token set | one token that already resolves per mode | | `style={{ boxShadow: '0 2px 8px …' }}` | Bypasses the elevation scale | `shadow-2` | | A one-off `