Imported from YuqingNicole/variant-design-skill (
SKILL.md). Install upstream withnpx skills add YuqingNicole/variant-design-skill. Copyright stays with the author.
name: variant-design description: AI-driven interactive design generation, style analysis, and UX evaluation with Impeccable design system. Context-aware output — auto-detects React projects (package.json with react dependency) and generates .tsx components; otherwise generates zero-dependency interactive HTML. Seven modes — (0) Design System: tokens → components → pages workflow: generate a complete token set (palette/type/spacing/motion/elevation/radius), confirm it, then all downstream outputs are visually consistent; (1) Generate: 3 distinct, fully-animated design variations from a prompt — when DS confirmed, variations differ in layout only (visual language locked); (2) Component: isolated UI components with all 8 states and variants — button systems, forms, cards, modals, nav — DS-aware when design system confirmed; (3) Compose: assemble confirmed components into page layouts, 3 structural variations (layout-only, no aesthetic invention); (4) Analyze: audit existing sites, extract design tokens, generate style-matched pages; (5) UX Review: heuristic evaluation (Nielsen's 10), cognitive load analysis, mental model diagnosis, affordance audit, dark pattern detection — grounded in NNG research; (6) Content formats: HTML pitch decks, WeChat article layout with 4 color schemes + 3 structural templates + inline styles + API upload flow; (7) Writing: anti-AI-taste Chinese copywriting across 4 text types (opinion/story/tutorial/product copy) and 3 platforms (公众号/小红书/产品内文案), with banned word list and before/after rewrites. Built-in Wu Xing (五行) color system with 40-tone palette, 26 combos, and cultural brand mapping. 16 domain references (including ux-heuristics, ux-psychology, presentation, wechat, wuxing-colors, voice), full design system (typography, color, spatial, motion, micro-interactions, interaction, responsive, UX writing, style audit), interactive pattern library, and anti-AI-slop quality gates. Triggers on: "create a design system", "define tokens", "ds", "compose", "design options for X", "show me variations", "vary this design", "audit", "analyze my site", "match this style", "extract tokens", "migrate", "add motion", "dramatize", "make interactive", "component button/form/card", "ux review", "heuristic evaluation", "usability audit", "cognitive load", "mental models", "affordances", "dark patterns", "review this design", "export to vue/astro/svelte", "pitch deck", "slides", "幻灯片", "PPT", "公众号", "wechat article", "微信文章", "五行配色", "wu xing", "brand color", "moodboard", "去AI味", "写文案", "copywriting".
Variant Design
Solve the blank canvas problem. Prompt → 3 fully-formed distinct designs → vary → export.
About
Inspired by the Variant design community — a space where designers share divergent takes on the same brief. This skill brings that practice into Claude Code: every prompt yields three designs that feel like they came from different studios, then lets you iterate with one-word actions.
Built on the Impeccable design system — a comprehensive set of design references covering typography, color theory, spatial design, motion, interaction patterns, responsive design, and UX writing. Every design decision is grounded in these principles.
Supports: Context-aware output (HTML default · React .tsx when React project detected) · Framer Motion (when installed) · 10 domain reference libraries · 39 palettes · design system references · micro-interaction library · interactive pattern library · style audit & token extraction · variation actions · Design Declaration → Product Integrity Contract for product-critical UI
CLI Workflow (Claude Code)
This skill runs inside Claude Code — a terminal. Design decisions must account for the fact that the user cannot see the output without opening a browser. Every step of the workflow should minimize friction between "idea" and "eyes on pixels."
Output Format Detection
Before generating any design, detect the output format. Run this detection once per session and cache the result.
Step 1: Read package.json
cat package.json 2>/dev/null
If absent or unreadable → HTML output (fail-safe), print warning if unreadable. Do not traverse parent directories — check cwd only.
Step 2: Walk the decision tree
Parse dependencies / devDependencies / peerDependencies / optionalDependencies. Check for exact keys only — never substring-match (react-scripts ≠ react, @vitejs/plugin-react ≠ vite).
package.json exists?
│
├─ no → HTML (zero-dep default)
│
└─ yes → check keys:
│
├─ "react" present?
│ ├─ yes → React branch:
│ │ ├─ "next" present? → Next.js App Router .tsx
│ │ │ add "use client" on components
│ │ │ using hooks/animations/browser APIs
│ │ ├─ "vite" or → Vite .tsx
│ │ │ "@vitejs/plugin-react" preview: read scripts.dev → npm run dev
│ │ └─ neither → Generic React .tsx
│ │
│ └─ no → non-React branch:
│ ├─ "vue" present? → Vue 3 .vue SFC
│ │ <script setup> + <template> + <style scoped>
│ │ preview: npm run dev (Vite assumed)
│ ├─ "astro" present? → Astro .astro component
│ │ frontmatter + HTML template
│ │ no client-side JS unless :is="client:load"
│ ├─ "svelte" or → Svelte .svelte component
│ │ "@sveltejs/kit" present? <script> + markup + <style>
│ │ SvelteKit if @sveltejs/kit detected
│ └─ none of the above → HTML (zero-dep default)
Step 3: Check for animation library (React branch only)
"framer-motion"or"motion"in deps → use Framer Motion (motion.div,AnimatePresence,useInView)- Not found → CSS animations only — do not import Framer Motion (missing package = runtime error)
Step 4: Apply user override
Explicit user instruction always wins over detection:
| User says | Output |
|---|---|
--react or react [A/B/C] |
Force React (auto-detect Next/Vite sub-type) |
--html |
Force zero-dep HTML |
--vue |
Force Vue 3 SFC |
--astro |
Force Astro component |
--svelte |
Force Svelte component |
export to next/vite/astro/svelte |
Force that framework |
Step 5: Announce the format
Print one line before generating:
✦ Output format: Next.js .tsx — detected next in package.json
✦ Output format: Vue 3 SFC .vue — detected vue in package.json
✦ Output format: Astro .astro — detected astro in package.json
✦ Output format: Svelte .svelte — detected @sveltejs/kit in package.json
✦ Output format: Interactive HTML — no framework detected in cwd
✦ Output format: React .tsx — user requested --react
Edge cases:
.tsxfiles exist but noreactkey → HTML output (Preact/Solid/stale files don't count)- Both
vueandnuxtdetected → treat as Nuxt 3 (same SFC format, noteuseNuxtAppavailable) - Monorepo: check cwd only, never traverse to parent
package.json - Multiple frameworks in same
package.json(unusual) → print ambiguity warning, ask user to pass--[framework]
Framework Output Templates
Each framework has its own file template, preview command, and import note.
Next.js App Router
// variant-output/VariantA.tsx
// Generated by variant-design — move to app/components/ or src/components/
// Preview: npm run dev (then import this component in your page)
"use client"; // include when component uses hooks, animations, or browser APIs
import { useState, useEffect, useRef } from "react";
// import { motion } from "framer-motion"; // only if framer-motion detected
export default function VariantA() {
// ...
}
Preview instruction after writing file:
✦ Written: variant-output/VariantA.tsx
Move to app/components/VariantA.tsx, then import in your page:
import VariantA from "@/components/VariantA"
Preview: npm run dev
Vite React
// variant-output/VariantA.tsx
// Generated by variant-design — move to src/components/
// Preview: npm run dev (Vite), then import this component
import { useState, useEffect, useRef } from "react";
export default function VariantA() {
// ...
}
Preview: read package.json scripts → use npm run dev / pnpm dev / yarn dev based on detected package manager. Fallback: npx vite.
Generic React
Same as Vite template without Vite-specific notes. Preview: npx vite as fallback.
Vue 3 SFC
<!-- variant-output/VariantA.vue -->
<!-- Generated by variant-design — move to src/components/ -->
<!-- Preview: npm run dev -->
<script setup lang="ts">
import { ref, onMounted } from "vue";
// animations: use CSS transitions/animations (no framer-motion in Vue)
// for complex motion: @vueuse/motion or vanilla CSS
</script>
<template>
<div class="variant-a">
<!-- ... -->
</div>
</template>
<style scoped>
/* OKLCH colors as CSS custom properties */
.variant-a {
--color-primary: oklch(65% 0.2 250);
/* ... */
}
</style>
Vue rules:
<script setup>always — no Options APIlang="ts"unless project has no TypeScript- Animations via CSS transitions +
v-enter-active/v-leave-activetransition classes - No Framer Motion — Vue has its own
<Transition>and<TransitionGroup> - Reactivity:
ref()for primitives,reactive()for objects,computed()for derived state
Astro Component
---
// variant-output/VariantA.astro
// Generated by variant-design — move to src/components/ or src/pages/
// Preview: npm run dev
// Astro components have no client-side reactivity by default
// Use client:load / client:visible for interactive islands
interface Props {
title?: string;
}
const { title = "Default Title" } = Astro.props;
---
<section class="variant-a">
<!-- ... -->
</section>
<style>
/* Scoped by default in Astro */
.variant-a {
--color-primary: oklch(65% 0.2 250);
}
</style>
<!-- Add client:load only for interactive sections -->
<!-- <InteractiveIsland client:load /> -->
Astro rules:
- Frontmatter (
---) for server-side logic only — nouseState, nouseEffect - Styles scoped by default — no need for CSS modules
- Interactive sections: extract to a separate
.tsx/.vue/.svelteisland, import withclient:loadorclient:visible - No JavaScript in
<script>unless truly necessary — Astro ships zero JS by default
Svelte / SvelteKit
<!-- variant-output/VariantA.svelte -->
<!-- Generated by variant-design — move to src/lib/components/ -->
<!-- Preview: npm run dev -->
<script lang="ts">
import { onMount } from "svelte";
// animations: svelte/transition and svelte/animate built-in
import { fade, fly, slide } from "svelte/transition";
import { tweened } from "svelte/motion";
let visible = false;
onMount(() => { visible = true; });
</script>
<div class="variant-a">
{#if visible}
<section transition:fly={{ y: 20, duration: 400 }}>
<!-- ... -->
</section>
{/if}
</div>
<style>
.variant-a {
--color-primary: oklch(65% 0.2 250);
}
</style>
Svelte rules:
- Use built-in
svelte/transitionandsvelte/animate— no Framer Motion tweened()andspring()fromsvelte/motionfor number animations (counters, progress bars){#if}/{#each}/{#await}blocks — no JSX- Reactivity is assignment-based:
count += 1triggers re-render automatically - SvelteKit: routes in
src/routes/, components insrc/lib/components/
Output Convention
File naming: variant-[scenario]-[variation].html (e.g., variant-dashboard-A.html)
Output directory: Write to ./variant-output/ in the current working directory. Create the directory if it doesn't exist. This keeps design files separate from project source code.
variant-output/
├── variant-dashboard-A.html
├── variant-dashboard-B.html
├── variant-dashboard-C.html
└── tokens/
└── dashboard-A-tokens.css (when user extracts tokens)
Iteration files: On variation actions, overwrite the same file (e.g., variant-dashboard-A.html) rather than creating variant-dashboard-A-v2.html. The user is iterating on one design, not collecting versions. Git handles history.
Auto-Preview
After every file write, immediately open it in the user's default browser:
# macOS
open variant-output/variant-dashboard-A.html
# Linux
xdg-open variant-output/variant-dashboard-A.html
This is non-negotiable. The user should never have to manually find and open the file. When iterating (Vary subtle, Remix colors, etc.), the browser tab auto-refreshes because the file is overwritten — just re-run open to bring it to focus.
Live Preview Server (Optional)
If the user asks for live preview or says "watch mode", start a lightweight file server with auto-reload:
# Using Python (available on most systems)
cd variant-output && python3 -c "
import http.server, socketserver, os, time, threading
class ReloadHandler(http.server.SimpleHTTPRequestHandler):
def end_headers(self):
self.send_header('Cache-Control', 'no-store')
super().end_headers()
def do_GET(self):
if self.path == '/_poll':
self.send_response(200)
self.send_header('Content-type', 'text/plain')
self.end_headers()
self.wfile.write(str(os.path.getmtime('.')).encode())
return
super().do_GET()
with socketserver.TCPServer(('', 3333), ReloadHandler) as httpd:
print('Preview: http://localhost:3333')
httpd.serve_forever()
" &
Then inject a tiny auto-reload script at the bottom of every generated HTML:
<script>
// Auto-reload in dev (remove for production)
(async function poll() {
try {
const r = await fetch('/_poll');
const t = await r.text();
if (window._lastMod && t !== window._lastMod) location.reload();
window._lastMod = t;
} catch(e) {}
setTimeout(poll, 800);
})();
</script>
Only include this script when the preview server is running. Remove it on export.
Compact CLI Output
Terminal space is precious. Keep text responses short and structured:
On initial generation (3 variations):
✦ Detected: coffee brand landing page → loading food-beverage.md + micro-interactions.md
A — Terroir Warm Fraunces + Instrument Sans Minimal/Editorial
B — Espresso Dark DM Serif Display + DM Sans Dark/Premium
C — Fresh Market Crimson Pro + Plus Jakarta Warm/Human
Interactions: scroll reveal, counter animation, card lift, filter chips, lightbox
Files written:
variant-output/variant-coffee-A.html ← opened in browser
variant-output/variant-coffee-B.html
variant-output/variant-coffee-C.html
Pick a variation to iterate, or an action:
Reshape — Vary strong · Distill · Shuffle layout · Change style
Tune — Vary subtle · Remix colors · Mix (A+B)
Animate — Add motion · Dramatize · Make interactive
Refine — Polish · Critique · See other views
Export — Extract tokens · react A · react B · react C
After initial generation, write context with detected scenario, the chosen palettes, and fonts for all 3 variations. Do not write picked yet — user hasn't chosen.
On iteration:
✦ Variation A — Vary subtle · iteration 2 [Terroir Warm · Editorial]
Changed: tightened spacing to 4pt grid, added tabular-nums on stats,
hover now lifts 4px→6px with shadow, scroll stagger 60ms→80ms
variant-output/variant-coffee-A.html ← updated & opened
Next action? (react A to export as React component)
After each iteration, update context: increment iterations, update picked if the user is iterating on a specific variation (implies selection).
Never dump the full HTML in the chat. Write to file, open in browser, show a 2-3 line summary of what changed. The user reads code in their editor, not in the terminal.
Quick Triggers
Support shorthand prompts for fast iteration in the terminal:
| User types | Expands to |
|---|---|
A vary strong |
Apply "Vary strong" to Variation A |
B remix colors |
Apply "Remix colors" to Variation B |
C → mobile |
Show Variation C as mobile viewport |
pick A |
Select Variation A as the winner, archive B and C |
A + B colors |
Mix: A's layout with B's color palette |
tokens A |
Extract design tokens from Variation A to CSS file |
open B |
Re-open Variation B in browser |
dark mode A |
Generate dark ↔ light toggle variant of A |
compare |
Open all 3 variations side-by-side (writes a comparison HTML) |
react A |
Export Variation A as React .tsx component (alias for export to react, Variation A) |
react B |
Export Variation B as React .tsx component |
react C |
Export Variation C as React .tsx component |
reset context |
Delete .variant-context.json and start fresh — next generation ignores all persisted preferences |
show context |
Print the current .variant-context.json contents in the terminal |
A vary strong — hero |
Zone-level: vary strong on hero section only, rest unchanged |
B remix colors — card |
Zone-level: remix colors on card zone only |
zones A |
List all data-zone sections found in Variation A |
component button |
Component mode: button system with all variants and states |
component form |
Component mode: form components |
component card |
Component mode: card variants |
ds |
Design System mode: generate tokens → preview |
ds confirm |
Lock design system — constrains all future outputs |
ds show |
Print design system summary |
ds edit palette |
Regenerate palette section only |
ds reset |
Unlock design system — allow aesthetic invention again |
compose [page] |
Assemble page from registered components, 3 layout variations |
registry |
Print which components have been built |
Context Commands
show context — Print the current context:
cat ./variant-output/.variant-context.json 2>/dev/null || echo "(no context saved yet)"
Display as a formatted single-line summary, e.g.:
✦ Context: Amber Warm · Editorial · Instrument Serif + Instrument Sans · picked B · 4 iterations
Framework: next · Scenario: landing-page
Notes: user prefers high contrast, no dark mode
reset context — Delete the context file and confirm:
rm -f ./variant-output/.variant-context.json
Print: ✦ Context cleared — next generation starts fresh.
Comparison View
When the user says "compare" or wants to see all variations together, generate a single variant-output/_compare.html that displays all 3 side-by-side in iframes:
<style>
body { margin:0; display:grid; grid-template-columns:1fr 1fr 1fr; height:100vh; gap:2px; background:#111; }
iframe { width:100%; height:100%; border:none; }
.label { position:absolute; top:8px; left:12px; background:#111; color:#fff; padding:4px 12px;
font:12px/1 monospace; border-radius:4px; z-index:10; }
.frame { position:relative; }
</style>
<div class="frame"><span class="label">A</span><iframe src="variant-coffee-A.html"></iframe></div>
<div class="frame"><span class="label">B</span><iframe src="variant-coffee-B.html"></iframe></div>
<div class="frame"><span class="label">C</span><iframe src="variant-coffee-C.html"></iframe></div>
Framework Export
When the user says "export to [framework]" or react [A/B/C], transform the winning variation into the target structure:
| Target | Action |
|---|---|
export to next |
Next.js App Router .tsx — "use client" where needed, tokens in CSS file |
export to vite |
Vite React .tsx — src/App.tsx structure, preview via npm run dev |
export to vue |
Vue 3 SFC .vue — <script setup lang="ts"> + scoped styles + svelte/transition equivalents via CSS |
export to astro |
Astro .astro — frontmatter + template + scoped styles, interactive parts as client:load islands |
export to svelte |
Svelte .svelte — svelte/transition animations, tweened() for counters, no Framer Motion |
export to static |
Clean HTML — remove dev scripts, inline critical CSS |
react [A/B/C] |
Shorthand for export to react — auto-detects Next vs Vite vs generic from cwd |
vue [A/B/C] |
Shorthand for export to vue on the specified variation |
astro [A/B/C] |
Shorthand for export to astro on the specified variation |
svelte [A/B/C] |
Shorthand for export to svelte on the specified variation |
Always ask which variation to export if the user hasn't picked one yet.
Preview after React export: Do not run vite --open directly — it may bypass project config. Instead, read package.json.scripts and print the correct dev command:
- If scripts contains
"dev"→ printnpm run dev(orpnpm dev/yarn dev/bun devbased on detected package manager) - If scripts contains
"start"→ printnpm start - If no scripts found → print
npx viteas fallback, with a note
Example output after React export:
✦ Exported: variant-output/VariantA.tsx
Move to src/components/ to include in your project's build.
Preview: npm run dev (then open the page that imports this component)
Clipboard Mode
If the user says "copy" or "clipboard", copy the HTML to system clipboard instead of (or in addition to) writing the file:
# macOS
cat variant-output/variant-coffee-A.html | pbcopy
Useful for pasting into CodePen, Claude.ai artifacts, or other tools.
Mode 0 — Design Declaration (product-critical UI)
Use this layer before visual generation for a new product, a workflow redesign, or any page involving user trust, money, privacy, irreversible actions, or AI-generated conclusions. It is not a PRD and does not replace the existing Design Read: Design Read confirms the prompt; this declaration locks the human product judgments that the skill must not invent.
Skip only for an explicitly exploratory visual exercise (surprise me, poster, moodboard, or brand exploration). Label that output: exploratory — no product decision locked.
Minimal declaration
Ask at most two questions total; first infer from the README, product copy, flows, and existing UI. Mark unconfirmed fields as assumption, never as research fact.
design_declaration:
user_context: [who, in what moment]
primary_job: [the one task this page/flow must complete]
success_moment: [when the user has clearly received value]
trust_boundary: [uncertain data, payment, deletion, privacy, financial/medical risk]
hierarchy: [one must-see item, then at most three secondary items]
chosen_tension: [e.g. evidence > delight; speed > exploration]
non_negotiables: [maximum three]
evidence_status: [real | mock-clearly-labeled | unknown]
Read references/design-declaration.md whenever this mode applies.
Product Integrity Contract
When a design system is confirmed, compile the declaration into variant-output/design-contract.md; read it before every Generate, Component, Compose, Analyze, or UX Review action. The contract has priority over aesthetic defaults.
Must: make the primary job and one primary CTA legible in the first view; make trust boundaries explicit through source/state/confirmation/undo/limits; include loading, empty, error, and success behavior; use confirmed tokens.
Must not: mix real, mock, and AI-inferred data without labels; conceal price, risk, source, recovery, or irreversible consequences; create competing primary CTAs; add decoration that contradicts hierarchy.
After ds confirm, the declaration is frozen alongside the system. Variations may change layout and information organization, but must not silently change primary_job, trust_boundary, or non_negotiables.
Project Context Initialization
Session Start: Read Persisted Context
Before doing anything else, check for a context file in the output directory:
cat ./variant-output/.variant-context.json 2>/dev/null
If the file exists and is valid JSON, load it silently and print one line:
✦ Resuming context: [palette] · [direction] · picked [variation] · iteration [n]
(reset context to start fresh)
Use all fields as constraints for the current session — the user should not need to re-specify preferences they've already confirmed.
If the file does not exist, proceed to the first-use questions below.
First Use: Gather Context
On first use in a project, gather design context to ground all future generations. Ask the user:
- Users & Purpose — Who uses this? What problem does it solve? What's the core task?
- Brand & Personality — Existing brand colors? Tone (playful / serious / technical / warm)? Any sites you admire?
- Aesthetic Preferences — Light or dark? Minimal or dense? Any direction from the aesthetic table you're drawn to?
- Constraints — Framework requirements? Accessibility standards beyond baseline? Target devices?
If the user can't answer, infer from their codebase: scan for existing color variables, font imports, component patterns, and README/brand docs. Confirm inferences before proceeding.
Persist Context After Each Decision
Write ./variant-output/.variant-context.json whenever the user makes a meaningful choice. Create variant-output/ first if it doesn't exist.
Schema:
{
"palette": "Amber Warm",
"fonts": ["Instrument Serif", "Instrument Sans"],
"direction": "Editorial",
"scenario": "landing-page",
"picked": "B",
"iterations": 3,
"framework": "next",
"notes": "user prefers high contrast, no dark mode",
"designDeclaration": {
"user_context": "...",
"primary_job": "...",
"success_moment": "...",
"trust_boundary": "...",
"hierarchy": ["..."],
"chosen_tension": "evidence > delight",
"non_negotiables": ["..."],
"evidence_status": "mock-clearly-labeled",
"frozenAt": "2026-08-13T10:00:00Z"
},
"designSystem": {
"confirmed": true,
"file": "variant-output/design-system.css",
"palette": "Amber Warm",
"fonts": ["DM Sans", "Newsreader"],
"confirmedAt": "2026-05-27T10:00:00Z"
},
"components": {
"button": "variant-output/component-button.html",
"card": "variant-output/component-card.html",
"form": "variant-output/component-form.html"
}
}
designSystem.confirmed: true is the gating flag. When true, all Generate/Component/Compose outputs read variant-output/design-system.css and must not introduce tokens outside it. When absent or false, full aesthetic invention is allowed.
When to update:
- After user picks a palette or confirms a direction → update
palette,direction,fonts - After user says
pick A/B/C→ updatepicked - After each variation action (vary, remix, shuffle) → increment
iterations - After scenario is detected and confirmed → update
scenario - After framework is detected → update
framework - After user gives a preference constraint → append to
notes - After Design Declaration is confirmed → write
designDeclaration; afterds confirm, addfrozenAtand generatevariant-output/design-contract.md - After
ds confirm→ writedesignSystemobject withconfirmed: true,file,palette,fonts,confirmedAt - After each
component [name]build → add entry tocomponentsmap - After
ds reset→ setdesignSystem.confirmed: false, clearcomponents
Fields are optional — write only what's known. Do not guess or fill in defaults.
Write the file silently (no terminal output). If write fails (e.g. no write permission), continue silently — context persistence is best-effort, never blocking.
Site Analysis Mode
When the user points to existing code (file paths, a directory, or says "analyze/audit/check my site"), switch from generation mode to analysis mode. Load references/design-system/style-audit.md for the full methodology.
Triggers
| User says | Action |
|---|---|
| "analyze my site" / "audit this" / "check consistency" | Full style audit → report |
| "match this style" / "follow existing design" / "extend my site" | Extract tokens → generate matching pages |
| "extract tokens" (on existing files, not a generated variation) | Token extraction → CSS custom properties file |
| "what's wrong with this design" / "review my CSS" | Style consistency check → findings list |
| "migrate" / "consolidate" / "clean up" | Audit → token generation → migration plan |
| "add a [page] to my site" / "new page matching my existing design" | Extract → match → generate |
Analysis Workflow
Step 1: Scan — Read the files the user points to. If no specific files given, scan for:
# Auto-detect entry points
find . -name "*.html" -o -name "*.css" -o -name "*.tsx" -o -name "*.jsx" \
-o -name "*.vue" -o -name "*.svelte" | head -20
# Also check for:
# - tailwind.config.* (Tailwind projects)
# - globals.css / index.css / app.css (common entry CSS)
# - tokens.css / variables.css / theme.* (existing token files)
Step 2: Extract — Pull all design primitives following the Token Extraction schema in style-audit.md: colors, typography, spacing, components, transitions. Group by semantic role.
Step 3: Detect — Run all consistency checks from style-audit.md Section 2. For each finding, record severity (error/warning/info), the specific values, file locations, and a concrete fix.
Step 3.5: Visual Quality Audit — In addition to consistency checks from style-audit.md, run this anti-slop checklist. Flag any item that fails with severity warning or error:
Typography
- Display font is NOT Inter/Roboto/Arial/Open Sans — use something with character
- Headlines have presence: tight tracking, compressed line-height, strong weight contrast
- Body text max-width ~65ch; line-height ≥ 1.5
- Weight range uses at least 3 stops (e.g. 400 / 500 / 700) — not just Regular + Bold
- Numbers in data contexts use
font-variant-numeric: tabular-numsor monospace - No orphaned single words on last line — use
text-wrap: balance/text-wrap: pretty - Headers use sentence case — not Title Case On Every Word
Color & Surfaces
- No pure
#000000background — use off-black / dark charcoal / tinted dark - Accent saturation below 80% — no neon or screaming accents
- Only one accent color — remove all others
- Grays are from one family — no mixing warm and cool grays
- No purple-to-blue "AI gradient" aesthetic
- Shadows are tinted to match background hue — not pure black at low opacity
- No random isolated dark section in a light-mode page (or vice versa)
Layout
- Not everything centered and symmetrical — break with offset, left-align, or asymmetry
- No 3 equal-column feature card row — use zig-zag, asymmetric grid, or horizontal scroll
- Uses
min-height: 100dvhnotheight: 100vh(iOS Safari viewport jump) - Has
max-widthcontainer constraint — content doesn't stretch edge-to-edge - Cards vary in size or weight — not uniformly identical
- Card group CTAs pin to bottom so buttons align across variable-length cards
Interactivity & States
- All buttons/links/cards have hover state (not just
opacity: 0.8) - Active/pressed feedback:
scale(0.98)ortranslateY(1px) - Transitions have non-zero duration (200-300ms)
- Visible
:focus-visiblering — neveroutline: nonealone - Loading state exists — skeleton loaders, not generic spinners
- Empty state has content: acknowledge → explain value → CTA
- Error state has inline message — no
window.alert()
Content
- No generic names: John Doe, Acme Corp, Nexus, SmartFlow
- No fake round numbers:
99.99%,$100.00,50,000 users - No AI clichés: Elevate, Seamless, Unleash, Next-Gen, Game-changer, Delve
- No Lorem Ipsum
- No exclamation marks in success/confirmation messages
- No passive voice in errors
Iconography
- Not using only Lucide/Feather icons — consider Phosphor or Radix UI Icons
- Consistent stroke width across all icons
- Favicon exists
Code Quality
- Semantic HTML:
<nav>,<main>,<article>,<section>— not div soup - No arbitrary z-index values (
9999) - All
<img>have meaningfulalttext - Animations use only
transformandopacity— notop/left/width/height
Score: subtract 2 points per failed item from 100. Present as Quality Score: XX/100.
Step 4: Report — Present findings using the compact terminal format from style-audit.md Section 3. Score out of 100. List priority fixes.
Step 5: Act — Based on what the user wants:
- Audit only: Stop after the report. Offer to generate a token file or migration plan.
- Extract tokens: Generate a
tokens.cssfile consolidating all values (seestyle-audit.mdSection 4). - Generate matching page: Lock extracted tokens as constraints, generate new pages that match (see below).
- Migration plan: Generate phased checklist for consolidating the codebase (see
style-audit.mdSection 6).
Style-Matched Generation
When generating new pages for an existing project, the workflow changes:
- Extract first — Always analyze existing code before generating. Never guess the style.
- Lock tokens — All generated code must use
var(--*)referencing the existing token system. If no token system exists, generate one first and get user approval. - Match patterns — Study existing component shapes (card radius, shadow, padding), interaction patterns (transition durations, hover effects), layout patterns (container width, grid), and naming conventions (BEM, Tailwind, CSS modules).
- Show diff from existing — In the Summary Card, note which tokens/patterns are being reused vs. which are new additions.
- Flag deviations — If the design system principles (from Impeccable) conflict with the existing style, flag it: "Your existing buttons have no hover state — I've added one following your color palette. OK?"
Summary Card for style-matched generation:
✦ New page: /pricing — matching existing site style
Reusing: --bg, --surface, --card, --border, --text, --muted, --accent
Reusing: Plus Jakarta Sans 400/600, 4 font sizes, 8px grid
Reusing: .card (24px padding, 8px radius, 1px border)
Reusing: .btn (100px radius, 200ms transition)
New additions:
+ Pricing toggle (monthly/annual) — uses existing .btn style
+ FAQ accordion — uses existing .card + new grid height animation
+ Comparison table — new component, follows existing spacing/color
File: variant-output/pricing-matched.html ← opened in browser
Quick Triggers for Analysis
| User types | Action |
|---|---|
audit |
Full style audit on current project |
audit src/styles/ |
Audit specific directory |
tokens |
Extract tokens from existing code → CSS file |
match |
Enter style-matched generation mode |
new page pricing |
Generate /pricing page matching existing style |
migrate |
Generate migration plan for token consolidation |
compare old new |
Side-by-side: existing page vs. redesigned version |
UX Review Mode
When the user wants to evaluate usability rather than generate visuals, switch to UX Review mode. Load references/ux-heuristics.md and references/ux-psychology.md. Load additional references as the review scope demands (see "When to Load Which Reference" below).
Triggers
| User says | Action | Load |
|---|---|---|
| "ux review" / "heuristic review" / "usability audit" | Full heuristic evaluation against Nielsen's 10 | ux-heuristics.md + ux-psychology.md |
| "review this design" / "what's wrong with this UI" | Heuristic scan → findings list with severity | ux-heuristics.md |
| "check usability" / "is this good UX" | Walk through flow, flag violations | ux-heuristics.md + ux-psychology.md |
| "cognitive load" / "too complex?" | Cognitive load analysis → reduction suggestions | ux-psychology.md |
| "why do users get confused here" | Mental model analysis → mismatch diagnosis | ux-psychology.md |
| "affordances" / "does this look clickable" | Affordance/signifier audit | ux-psychology.md |
| "dark patterns" / "is this ethical" | Dark pattern scan | ux-psychology.md |
| "navigation" / "can't find" / "information architecture" / "IA" | IA audit — labels, hierarchy, findability | ux-information-architecture.md |
| "site structure" / "how to organize" / "card sort" / "tree test" | IA design or validation | ux-information-architecture.md |
| "accessibility" / "a11y" / "screen reader" / "keyboard navigation" | Accessibility audit against WCAG 2.1 AA | ux-accessibility.md |
| "WCAG" / "alt text" / "aria" / "focus" | Specific accessibility check | ux-accessibility.md |
| "user testing" / "how to test this" / "usability test" | Research method recommendation + test plan | ux-research-methods.md |
| "what do users think" / "how do I get feedback" | Research method selection | ux-research-methods.md |
| "NPS" / "SUS" / "survey" / "interview users" | Measurement framework or interview guidance | ux-research-methods.md |
| "transition feels wrong" / "animation timing" / "state choreography" / "loading feels laggy" | Component transition audit | ux-interaction-transitions.md |
| "touch target" / "thumb zone" / "mobile gesture" / "iOS vs Android" | Mobile interaction audit | ux-mobile-patterns.md |
| "onboarding" / "empty state" / "first use" / "aha moment" / "activation" | Onboarding flow review | ux-onboarding.md |
| "chart" / "dashboard" / "data viz" / "KPI card" / "which chart" | Data visualization audit or recommendation | ux-data-visualization.md |
| "content model" / "taxonomy" / "multilingual" / "RTL" / "localization" | Content structure review | ux-content-strategy.md |
| "design tokens" / "token naming" / "theming" / "dark mode architecture" | Token architecture review | ux-design-tokens.md |
| "component spec" / "button states" / "modal behavior" / "ARIA" | Component spec review | ux-component-specs.md |
| "design critique" / "feedback on design" / "design review meeting" | Critique framework guidance | ux-design-critique.md |
| "conversion" / "landing page" / "trust signals" / "CTA copy" / "pricing page" | Conversion UX audit | ux-conversion-patterns.md |
| "error message" / "error state" / "form error" / "validation" / "recovery path" / "prevent errors" | Error design audit — classification, messaging, prevention | ux-error-design.md |
| "empty state" / "no data" / "blank state" / "nothing here" / "zero state" | Empty state design — all 4 types | ux-empty-states.md |
| "notification" / "toast" / "banner" / "badge" / "push notification" / "alert priority" | Notification system design and priority rules | ux-notifications.md |
| "table" / "data table" / "sorting" / "filtering" / "pagination" / "bulk select" / "row actions" | Table and list interaction design | ux-tables-lists.md |
| "search" / "autocomplete" / "search results" / "search bar" / "faceted search" / "command palette" | Search pattern design — input, suggestions, results | ux-search-patterns.md |
UX Review Workflow
Two paths depending on what's available:
- Code in cwd → run Code Scan (Steps 1a–1b) first, then layer conceptual analysis
- No code / screenshots / description only → skip to Step 2
Step 1a: Auto-detect project files
# Find component files in cwd (skip node_modules, .git, dist)
find . \( -name "*.tsx" -o -name "*.jsx" -o -name "*.vue" -o -name "*.svelte" -o -name "*.html" \) \
-not -path "*/node_modules/*" -not -path "*/.git/*" -not -path "*/dist/*" | head -30
If files found, proceed to Step 1b. Otherwise skip to Step 2.
Step 1b: Code-level heuristic scan
Run these greps against the found files. Each maps to a specific heuristic:
# H9 — Generic error messages (critical pattern)
grep -rn "error occurred\|something went wrong\|invalid input\|please try again\|An error\|Unknown error" \
--include="*.tsx" --include="*.jsx" --include="*.vue" --include="*.html" \
--exclude-dir=node_modules --exclude-dir=dist . 2>/dev/null
# H1 — Missing loading states: async handlers without loading flag
grep -rn "onClick\|onSubmit\|handleSubmit" \
--include="*.tsx" --include="*.jsx" --exclude-dir=node_modules . 2>/dev/null | head -20
# (then read those files to check if loading/disabled state is managed)
# H3 — Destructive actions: delete/remove calls without confirmation guard
grep -rn "delete\|remove\|destroy\|clearAll\|reset" \
--include="*.tsx" --include="*.jsx" -i --exclude-dir=node_modules . 2>/dev/null | \
grep -iv "confirm\|modal\|dialog\|undo\|trash\|soft" | head -20
# H4 — Terminology inconsistency: mixed action words for same concept
grep -rn '"Delete"\|"Remove"\|"Erase"\|"Discard"\|"Clear"' \
--include="*.tsx" --include="*.jsx" --exclude-dir=node_modules . 2>/dev/null
# Flag if multiple terms coexist in same codebase
# H6 — Icon-only buttons missing accessible label
grep -rn "<button\|<Button\|<IconButton" \
--include="*.tsx" --include="*.jsx" --exclude-dir=node_modules . 2>/dev/null | \
grep -v "aria-label\|title=\|children\|tooltip" | head -20
# H5 — Forms missing inline validation
grep -rn "<form\|<Form\|onSubmit" \
--include="*.tsx" --include="*.jsx" --exclude-dir=node_modules . 2>/dev/null | head -10
# (then read those files to check for inline validation vs. submit-only)
# H10 — Empty states: no empty state handling
grep -rn "\.length === 0\|\.length == 0\|items\.length\|data\.length" \
--include="*.tsx" --include="*.jsx" --exclude-dir=node_modules . 2>/dev/null | \
grep -v "EmptyState\|empty\|nothing\|no items\|no results" | head -15
# A11y — Images missing alt text
grep -rn "<img " \
--include="*.tsx" --include="*.jsx" --include="*.html" \
--exclude-dir=node_modules . 2>/dev/null | grep -v "alt=" | head -10
# A11y — Buttons missing accessible name (icon-only)
grep -rn "<button\|<Button\|<IconButton" \
--include="*.tsx" --include="*.jsx" --exclude-dir=node_modules . 2>/dev/null | \
grep -v "aria-label\|aria-labelledby\|title=" | head -15
# A11y — onClick on non-interactive elements (no keyboard access)
grep -rn "onClick" \
--include="*.tsx" --include="*.jsx" --exclude-dir=node_modules . 2>/dev/null | \
grep -E "<div|<span|<p" | head -15
# A11y — outline:none removing focus indicators
grep -rn "outline:\s*none\|outline:\s*0" \
--include="*.css" --include="*.scss" --include="*.tsx" --include="*.jsx" \
--exclude-dir=node_modules . 2>/dev/null | head -10
# A11y — Inputs missing associated label
grep -rn "<input" \
--include="*.tsx" --include="*.jsx" --include="*.html" \
--exclude-dir=node_modules . 2>/dev/null | \
grep -v "type=\"hidden\"\|aria-label\|aria-labelledby\|id=" | head -10
For each grep that returns results: read the flagged files at the relevant lines to confirm whether it's a real violation or a false positive. Report only confirmed violations.
Step 2: Define scope — What task(s) is the user trying to complete? What screens/flows are in scope?
Step 3: Walk the flow — Step through each screen as a first-time user would. For each screen, check:
- What is the user trying to do here? (H1: visibility of goal)
- Can they figure out how to do it? (affordances, signifiers)
- Will they know when it worked? (feedback, system status)
- What could go wrong? (error prevention)
- Is anything adding unnecessary mental work? (cognitive load)
Step 4: Log violations — For each violation found (from code scan or conceptual walk):
File: [path:line] or Screen: [name]
Heuristic: [H1–H10, or cognitive load / mental model / affordance]
Violation: [specific description — quote actual code or UI text where possible]
Severity: [1=cosmetic / 2=minor / 3=major / 4=critical]
Fix: [concrete recommendation with code example if applicable]
Step 5: Report — Present as a prioritized list, critical issues first. Group by heuristic to surface systemic problems.
Step 6: Offer next step — After the report, offer:
fix [H9]→ Generate corrected error messages as a code snippet or new componentgenerate fix→ Generate redesigned version of worst-offending screen as HTML/TSXcompare→ Side-by-side: current vs. fixed version opened in browserchecklist→ Generate a dev-ready fix checklist (markdown, copy-pasteable to GitHub Issues)
UX Review Output Format
✦ UX Review: [screen/flow name]
Scanned: 23 components · 4 violations found
Critical (fix before launch)
────────────────────────────
[H9] src/components/LoginForm.tsx:47
catch(e) { setError("An error occurred") }
Fix: setError(`Login failed: ${e.message}. Check your email and password.`)
[H1] src/components/UploadButton.tsx:23
onClick={handleUpload} — no loading/disabled state managed
Fix: setLoading(true) on click; disabled={loading}; show <Spinner /> inside button
Major (high priority)
─────────────────────
[H3] src/pages/ProjectList.tsx:89
onClick={() => deleteProject(id)} — no confirmation, immediate delete
Fix: Move to trash: softDelete(id) + undo toast for 5s, or confirm dialog
Minor (low priority)
────────────────────
[H4] "Remove" (src/components/MemberList.tsx:34) vs "Delete" (src/pages/Settings.tsx:102)
Same destructive action, two different words
Fix: Standardize to "Remove" for members, "Delete" for owned resources
Summary: 2 critical · 1 major · 1 minor
Next: fix H9 · fix H1 · generate fix · checklist
Quick Triggers for UX Review
| User types | Action |
|---|---|
ux scan |
Code scan only — run all heuristic greps, report file:line violations, no conceptual walk |
ux review |
Full review — code scan + conceptual walk + report |
ux review src/components/ |
Scope scan to specific directory |
fix H9 |
Generate corrected error message patterns as a code snippet |
fix H1 |
Generate loading state pattern for flagged component |
fix H3 |
Generate soft-delete / confirmation dialog pattern |
generate fix |
Generate redesigned screen that resolves all critical violations |
checklist |
Output dev-ready markdown checklist of all violations (copy to GitHub Issues) |
compare ux |
Side-by-side: current vs. UX-fixed version in browser |
Cross-Mode Bridges
From Site Analysis → UX Review:
After audit extracts tokens and consistency issues, you can continue with ux scan — the two modes complement each other. Style audit catches visual/token issues; UX scan catches behavioral/interaction issues.
From UX Review → Generate: After flagging violations, offer to generate a fixed version:
generate fix→ generate corrected screen as HTML/TSX, written tovariant-output/ux-fix-[screen].html, opened in browsercompare ux→ write both current (screenshot or recreation) and fixed version, open side-by-side invariant-output/_ux-compare.html
From Generate → UX Review: Every generated design silently runs the heuristic checklist before being presented (part of the AI Slop Test gate). If any H1–H10 critical violations are found in the generated code, fix before writing the file — don't present broken UX as a variation.
When to Load Which Reference
| Question | Load |
|---|---|
| Nielsen heuristics evaluation | references/ux-heuristics.md |
| Mental models, cognitive load, Gestalt, affordances | references/ux-psychology.md |
| Navigation, findability, IA structure, labeling, search | references/ux-information-architecture.md |
| Accessibility, WCAG, keyboard nav, screen readers, a11y | references/ux-accessibility.md |
| User research methods, usability testing, interviews, surveys | references/ux-research-methods.md |
| Component state transitions, timing, easing, choreography | references/ux-interaction-transitions.md |
| Mobile gestures, thumb zones, iOS/Android conventions, touch targets | references/ux-mobile-patterns.md |
| Onboarding, empty states, Aha moment, first-use experience | references/ux-onboarding.md |
| Charts, dashboards, data visualization, chart selection | references/ux-data-visualization.md |
| Content models, taxonomy, multilingual UX, content lifecycle | references/ux-content-strategy.md |
| Design tokens, token architecture, theming, dark mode | references/ux-design-tokens.md |
| Component specs, button/form/modal states, ARIA patterns | references/ux-component-specs.md |
| Design critique, feedback frameworks, design review | references/ux-design-critique.md |
| Conversion, landing pages, trust signals, pricing UX, CTAs | references/ux-conversion-patterns.md |
| Error messages, validation, recovery paths, prevention layers | references/ux-error-design.md |
| Empty states (first use / cleared / no results / error) | references/ux-empty-states.md |
| Notifications — Toast, Banner, Badge, Push, priority management | references/ux-notifications.md |
| Tables, lists, sorting, filtering, pagination, bulk selection | references/ux-tables-lists.md |
| Search patterns — autocomplete, facets, results page, command palette | references/ux-search-patterns.md |
| Full UX review | Load all relevant references above |
For generation tasks: Load ux-heuristics.md and ux-psychology.md as silent quality constraints. Every generated design should pass the heuristic checklist before being presented — this is part of the quality gate, same as the AI Slop Test.
Smart Prompt Handling
Before generating, apply these three rules in order:
-
Confirm scenario detection. Before generating, output a one-line Design Read summary, then ask the user to confirm:
Format:
Design Read: [page kind] for [audience] — [vibe keywords] · [constraints if any]Example:
Design Read: SaaS landing page for dev-tools B2B — minimal, Linear-style · dark mode preferredThen ask: "Correct? Or redirect me before I generate."
Read these signals to build the Design Read:
- Page kind: landing / portfolio / dashboard / editorial / app screen / redesign
- Vibe words: adjectives the user used or implied ("clean", "brutalist", "premium", "editorial", "agency-y")
- Audience: B2B procurement vs design-conscious consumer vs recruiter vs general public
- Reference signals: URLs, product names, competitor brands mentioned
- Quiet constraints: accessibility-first, regulated industry, kids' product, trust-first commerce — these OVERRIDE aesthetic preference
-
Resolve vague prompts — max 2 questions. If the prompt lacks enough signal to differentiate 3 variations (e.g. "design something cool"), ask at most 2 clarifying questions. Focus on: (a) what it's for / who uses it, (b) any aesthetic leaning. If the user says "surprise me," pick 3 maximally divergent directions and proceed.
-
Never generate blind. Do not produce code until you have either (a) user confirmation of the scenario, or (b) answers to your clarifying questions, or (c) an explicit "surprise me."
-
Lock product judgment when it matters. For product-critical UI, complete Mode 0 after Design Read and before generation. For exploratory work, state that no product decision is locked.
Scenario Detection → Load Reference
Identify the scenario and load the corresponding reference file before designing:
| User asks about... | Also matches | Load |
|---|---|---|
| Dashboard, analytics, metrics, monitoring, data viz | 后台, admin panel, management system, backoffice, CRM, internal tool | references/dashboard.md |
| Editorial, magazine, journalism, news, article | blog post, report, white paper, newsletter | references/editorial.md |
| Landing page, SaaS, product page, startup, B2B | website, 官网, corporate site, personal site, portfolio, agency | references/saas.md |
| E-commerce, shopping, product, fintech card, consumer | store, shop, marketplace, cart, checkout | references/ecommerce.md |
| Education, learning app, quiz, language, science | lesson, flashcard, tutorial, training, course | references/education.md |
| Generative art, music tool, 3D, creative tool, synthesizer | tool, studio, editor, canvas, sequencer, DAW | references/creative.md |
| Mobile app, iOS, Android, onboarding, home screen | app, 应用, 界面, UI screen | references/mobile.md |
| Portfolio, personal site, showcase, case study | designer portfolio, developer site, freelancer, agency, 作品集 | references/portfolio.md |
| Restaurant, recipe, food, coffee, bakery, menu | café, bar, cocktail, wine, tea, meal planning, 餐厅, 菜单 | references/food-beverage.md |
| Fashion, clothing, beauty, lookbook, interior design | streetwear, luxury brand, skincare, cosmetics, furniture, 时尚, 服装 | references/fashion.md |
| Pitch deck, slides, presentation, keynote, investor deck | 幻灯片, PPT, 演讲稿, deck | references/presentation.md |
| WeChat article, 公众号, wechat post, 微信文章 | 公号排版, 推文, 内容排版 | references/wechat.md |
| Brand color, moodboard, 五行, wu xing, chinese color, 品牌配色 | 东方美学, 传统配色, 文化品牌 | references/wuxing-colors.md |
| Writing, 文案, copywriting, 去AI味, anti-AI writing | 公众号, 小红书, 产品文案, 观点文, 故事文, 教程文, voice | references/voice.md |
| UX review, heuristic evaluation, usability audit, cognitive load, mental models | "is this good UX", affordances, dark patterns | references/ux-heuristics.md + references/ux-psychology.md |
| Information architecture, navigation, findability, site structure | "can't find", IA audit, card sort, tree test, nav labels, search design | references/ux-information-architecture.md |
| Accessibility, a11y, WCAG, screen reader, keyboard navigation | alt text, focus indicator, ARIA, color contrast, inclusive design | references/ux-accessibility.md |
| User research, usability testing, user interviews, surveys, A/B test | "how do I test this", NPS, SUS, research methods, "what do users think" | references/ux-research-methods.md |
| Component transitions, animation timing, state choreography, easing | "feels laggy", "transition wrong", button loading, modal enter/exit, skeleton | references/ux-interaction-transitions.md |
| Mobile interactions, touch targets, gestures, thumb zone, iOS vs Android | swipe, bottom sheet, tap, safe area, mobile form | references/ux-mobile-patterns.md |
| Onboarding, first-use, empty states, Aha moment, sign-up flow | new user experience, activation, "blank slate", progressive disclosure | references/ux-onboarding.md |
| Charts, data viz, dashboard design, KPIs, data tables | bar chart, line chart, color encoding, tooltip, filter | references/ux-data-visualization.md |
| Content model, taxonomy, multilingual, RTL, content lifecycle | structured content, metadata, localization, i18n, translation | references/ux-content-strategy.md |
| Design tokens, token naming, theming, dark mode architecture | CSS variables, semantic tokens, primitive tokens, brand theming | references/ux-design-tokens.md |
| Component specs, button states, modal behavior, form input | component library, ARIA, state machine, variant, anatomy | references/ux-component-specs.md |
| Design critique, design review, feedback frameworks | "how to give feedback", "review this design", design review meeting | references/ux-design-critique.md |
| Conversion, landing pages, pricing design, trust signals, CTA | "increase conversions", "improve signup rate", checkout UX, CRO | references/ux-conversion-patterns.md |
| Unsure / general | Use aesthetic directions table below + references/palettes.md |
Always also load the relevant design system references from references/design-system/ based on what matters most for the design:
| Design challenge | Load |
|---|---|
| Font selection, type scale, hierarchy | references/design-system/typography.md |
| Color palette, dark mode, contrast | references/design-system/color-and-contrast.md |
| Layout, spacing, grids, visual hierarchy | references/design-system/spatial-design.md |
| Animations, transitions, loading states | references/design-system/motion-design.md |
| Micro-interactions, scroll reveals, hover effects | references/design-system/micro-interactions.md |
| Functional interactions (filter, drag, charts, forms) | references/interactive-patterns.md |
| Forms, states, focus, keyboard nav | references/design-system/interaction-design.md |
| Style audit, token extraction, consistency checks | references/design-system/style-audit.md |
| Mobile-first, breakpoints, fluid design | references/design-system/responsive-design.md |
| Labels, errors, empty states, microcopy | references/design-system/ux-writing.md |
For initial generation, load at minimum: typography, color-and-contrast, spatial-design, and micro-interactions. Load interactive-patterns when the design involves filtering, forms, charts, galleries, or drag-and-drop. Load others as the design demands.
Design System Mode
The canonical workflow for production-quality work. Define once, generate consistently.
ds → confirm → component [name] → compose [page]
↑ ↑ ↑
Token foundation Atomic pieces Assembled layouts
Triggers
| User says | Action |
|---|---|
ds / "create a design system" / "define tokens" / "set up tokens" |
Generate design system → preview → confirm |
ds confirm |
Lock current design system and Design Declaration as constraints; generate design-contract.md |
ds edit [section] |
Edit one section of the design system (palette / type / spacing / motion) without regenerating all |
ds show |
Print current design system token summary in terminal |
component [name] (after DS confirmed) |
Generate component using locked DS tokens, all 8 states |
compose [page name] |
Assemble confirmed components into a page, 3 layout variations |
compose [page] using A B C |
Compose page from specific named components |
Step 1 — Generate Design System (ds)
Before generating, ask 3 focused questions (can be answered in one message):
- Brand personality — 2–3 adjectives that describe the feel (e.g. "precise, warm, understated")
- Color direction — existing brand color, or a reference (hex / site URL / mood word)
- Typeface preference — existing fonts, or a direction ("editorial serif", "clean geometric sans", "monospace-forward")
If user says "surprise me" or has no preferences, infer from their codebase (README, existing CSS, component names) or pick a strongly opinionated direction and state it.
Generate variant-output/design-system.css — a complete, self-documenting token file:
/* ═══════════════════════════════════════════════════
DESIGN SYSTEM — [Project Name]
Generated by variant-design · [date]
Confirm with: ds confirm
Edit with: ds edit [palette | type | spacing | motion | elevation | radius]
═══════════════════════════════════════════════════ */
/* ── Primitives ─────────────────────────────────── */
:root {
/* Color primitives — OKLCH */
--p-brand-50: oklch(97% 0.02 [H]);
--p-brand-100: oklch(93% 0.04 [H]);
--p-brand-200: oklch(86% 0.08 [H]);
--p-brand-300: oklch(76%
*Truncated - read the full file at https://github.com/YuqingNicole/variant-design-skill/blob/f6ca943b356b52c4fe2e9b8c1cef230a23aaca81/SKILL.md.*