Skill v1.0.2
currentAutomated scan100/1003 files
metadata: version: "1.0.2"
<!-- Sub-workflow of the variant-design skill, reached through the route table in ../../SKILL.md. It has no skill frontmatter on purpose: agents that scan folders recursively (Codex, npx skills) must not register it as a standalone skill, because its paths are relative to the skill root. -->
variant-design-system: Design System mode — tokens → components → pages three-layer workflow. Generate a complete token set (palette/type/spacing/motion/elevation/radius), confirm it, then all downstream outputs are visually consistent. Triggers on: ds, design system, tokens, create token set, define palette, define tokens, set up tokens, ds confirm, compose
Before generating code, loadskills/shared/code-output.md,references/workflow/project-context.md, andreferences/workflow/quality-baseline.md.
For product-critical work, also read references/workflow/design-declaration.md and references/workflow/product-integrity-gate.md. A confirmed design system locks the declaration's product constraints as well as visual tokens.
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 the current design system and any product-critical Design Declaration for future outputs | |
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, infer these dimensions from the brief and repository. Ask at most two material unanswered questions across the entire request; no mandatory intake:
- 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 confirmEdit 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% 0.13 [H]);--p-brand-400: oklch(66% 0.18 [H]);--p-brand-500: oklch(56% 0.20 [H]); /* primary */--p-brand-600: oklch(46% 0.18 [H]);--p-brand-700: oklch(36% 0.15 [H]);--p-brand-800: oklch(26% 0.10 [H]);--p-brand-900: oklch(16% 0.06 [H]);--p-neutral-50: oklch(98% 0.005 [H]);--p-neutral-100: oklch(95% 0.008 [H]);--p-neutral-200: oklch(90% 0.010 [H]);--p-neutral-300: oklch(82% 0.012 [H]);--p-neutral-400: oklch(68% 0.010 [H]);--p-neutral-500: oklch(55% 0.008 [H]);--p-neutral-600: oklch(42% 0.008 [H]);--p-neutral-700: oklch(30% 0.006 [H]);--p-neutral-800: oklch(20% 0.005 [H]);--p-neutral-900: oklch(12% 0.004 [H]);--p-success: oklch(55% 0.18 145);--p-warning: oklch(60% 0.18 80);--p-error: oklch(55% 0.22 25);--p-info: oklch(55% 0.18 250);}/* ── Semantic tokens ─────────────────────────────── */:root {/* Surfaces */--color-bg: var(--p-neutral-50);--color-surface: #ffffff;--color-surface-2: var(--p-neutral-100);--color-surface-3: var(--p-neutral-200);/* Borders */--color-border: var(--p-neutral-200);--color-border-strong: var(--p-neutral-300);/* Text */--color-text-primary: var(--p-neutral-900);--color-text-secondary: var(--p-neutral-600);--color-text-tertiary: var(--p-neutral-400);--color-text-on-accent: #ffffff;/* Brand */--color-accent: var(--p-brand-500);--color-accent-hover: var(--p-brand-600);--color-accent-subtle: var(--p-brand-50);--color-accent-border: var(--p-brand-200);/* Semantic */--color-success: var(--p-success);--color-success-subtle: oklch(97% 0.03 145);--color-warning: var(--p-warning);--color-warning-subtle: oklch(98% 0.03 80);--color-error: var(--p-error);--color-error-subtle: oklch(97% 0.03 25);}/* ── Typography ─────────────────────────────────── */:root {--font-display: '[Display Font]', serif; /* or sans-serif */--font-body: '[Body Font]', sans-serif;--font-mono: 'IBM Plex Mono', monospace;/* Scale — ratio [ratio] */--text-xs: clamp(0.69rem, 0.65rem + 0.2vw, 0.75rem);--text-sm: clamp(0.8rem, 0.77rem + 0.2vw, 0.875rem);--text-base: clamp(0.95rem, 0.9rem + 0.25vw, 1.0625rem);--text-lg: clamp(1.1rem, 1rem + 0.5vw, 1.25rem);--text-xl: clamp(1.3rem, 1.1rem + 1vw, 1.75rem);--text-2xl: clamp(1.6rem, 1.2rem + 2vw, 2.5rem);--text-3xl: clamp(2rem, 1.4rem + 3vw, 3.5rem);--text-4xl: clamp(2.5rem, 1.6rem + 5vw, 5.5rem);/* Weights */--font-weight-normal: 400;--font-weight-medium: 500;--font-weight-semibold: 600;--font-weight-bold: 700;/* Line heights */--leading-tight: 1.2;--leading-snug: 1.35;--leading-normal: 1.5;--leading-relaxed: 1.7;/* Tracking */--tracking-tight: -0.04em;--tracking-snug: -0.02em;--tracking-normal: 0;--tracking-wide: 0.04em;--tracking-caps: 0.08em;}/* ── Spacing ─────────────────────────────────────── */:root {/* 4pt base grid */--space-1: 4px;--space-2: 8px;--space-3: 12px;--space-4: 16px;--space-5: 20px;--space-6: 24px;--space-8: 32px;--space-10: 40px;--space-12: 48px;--space-16: 64px;--space-20: 80px;--space-24: 96px;/* Layout */--container-sm: 640px;--container-md: 768px;--container-lg: 1024px;--container-xl: 1280px;--container-2xl: 1440px;}/* ── Radius ──────────────────────────────────────── */:root {--radius-xs: 2px;--radius-sm: 4px;--radius-md: 6px;--radius-lg: 10px;--radius-xl: 16px;--radius-2xl: 24px;--radius-full: 9999px;}/* ── Elevation (shadow) ──────────────────────────── */:root {--shadow-xs: 0 1px 2px rgba(0,0,0,0.05);--shadow-sm: 0 1px 4px rgba(0,0,0,0.07), 0 0 0 1px rgba(0,0,0,0.04);--shadow-md: 0 4px 12px rgba(0,0,0,0.08), 0 0 0 1px rgba(0,0,0,0.04);--shadow-lg: 0 8px 24px rgba(0,0,0,0.10), 0 0 0 1px rgba(0,0,0,0.04);--shadow-xl: 0 16px 48px rgba(0,0,0,0.12), 0 0 0 1px rgba(0,0,0,0.05);/* Focus ring */--ring-width: 2px;--ring-offset: 2px;--ring-color: var(--color-accent);}/* ── Motion ──────────────────────────────────────── */:root {/* Durations */--duration-instant: 80ms;--duration-fast: 150ms;--duration-normal: 250ms;--duration-slow: 400ms;--duration-slower: 600ms;/* Easings */--ease-out: cubic-bezier(0.0, 0.0, 0.2, 1);--ease-in: cubic-bezier(0.4, 0.0, 1, 1);--ease-in-out: cubic-bezier(0.4, 0.0, 0.2, 1);--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);--ease-spring: cubic-bezier(0.175, 0.885, 0.32, 1.275);/* Common transitions */--transition-fast: all var(--duration-fast) var(--ease-out);--transition-normal: all var(--duration-normal) var(--ease-out);--transition-colors: color var(--duration-fast) var(--ease-out),background-color var(--duration-fast) var(--ease-out),border-color var(--duration-fast) var(--ease-out);}/* ── Z-index ─────────────────────────────────────── */:root {--z-base: 0;--z-raised: 10;--z-dropdown: 100;--z-sticky: 200;--z-overlay: 300;--z-modal: 400;--z-toast: 500;}
Also generate `variant-output/design-system-preview.html` — a visual token preview showing:
- Color palette swatches (brand scale + neutrals + semantic)
- Typography specimens at each size step with sample text
- Spacing scale as a visual bar chart
- Shadow/elevation showcase
- Motion demo (hover cards to see transition, animated duration reference)
- Border radius examples
Open the preview immediately in browser.
Step 2 — Confirm Design System (ds confirm)
When the user approves (says ds confirm, "looks good", "confirm this", "ship it"):
- Write the confirmed status to
.variant-context.json:
{"designSystem": {"confirmed": true,"file": "variant-output/design-system.css","palette": "[palette name]","fonts": ["[Display]", "[Body]"],"confirmedAt": "[ISO date]"}}
- Print confirmation:
✦ Design system confirmed — locked as visual foundationFile: variant-output/design-system.cssPalette: [name] · [hue]° OKLCHType: [Display font] + [Body font]Next steps:component [name] → build atomic components on this foundationcompose [page] → assemble components into page layoutsds edit palette → refine colors before building
- From this point forward, all Generate, Component, and Compose outputs must
<link rel="stylesheet" href="design-system.css">(or inline the tokens) — no aesthetic invention allowed outside the locked token system.
- For product-critical work, compile the confirmed declaration into
variant-output/design-contract.mdand run the Product Integrity Gate separately from the visual quality gate.
Step 3 — Build Components (component [name])
When design system is confirmed, Component Mode runs on a tighter brief:
- All colors from
design-system.csssemantic tokens — no new colors - All spacing from
design-system.cssspacing scale — no new values - Typography from
design-system.csstype tokens - Add to component registry in
.variant-context.json:
{"components": {"button": "variant-output/component-button.html","card": "variant-output/component-card.html","form": "variant-output/component-form.html"}}
Terminal output:
✦ Component: Button System [DS: confirmed · Amber Warm · DM Sans]Tokens used: --color-accent, --color-surface, --space-2/3/4, --radius-mdNew tokens added: nonevariant-output/component-button.html ← opened in browserRegistry: button · (no other components yet)Next: component card · component form · compose [page] using button
Step 4 — Compose Pages (compose [page name])
Assembles registered components into page layouts. 3 structural variations — layout and composition differ; visual language does not.
Process:
- Read
.variant-context.jsonto get component registry - Read
design-system.cssfor tokens - For each variation, invent a different structural arrangement:
- Variation A: canonical / expected layout for this page type
- Variation B: unconventional hierarchy (e.g. sidebar-dominant, reversed stack)
- Variation C: density variant (compact/information-dense vs. spacious/editorial)
- All three use identical tokens and components — the only differences are grid, order, proportion, and density
- Write
variant-output/compose-[page]-A.html,-B.html,-C.html
What changes across compose variations:
| Dimension | Can vary | Cannot vary | |
|---|---|---|---|
| Grid structure | ✓ | ||
| Section order / hierarchy | ✓ | ||
| Column count / proportion | ✓ | ||
| Density (padding, gap) | ✓ — within spacing scale | ||
| Which components are prominent | ✓ | ||
| Colors | ✗ — all from DS | ||
| Typography | ✗ — all from DS | ||
| Component visual design | ✗ — use as-built | ||
| New spacing values | ✗ — DS scale only |
Terminal output:
✦ Compose: Dashboard page [DS confirmed · 3 components registered]Components used: button · card · data-tableLayout variations:A — Standard: left sidebar + main content gridB — Topbar: horizontal nav + full-width zonesC — Focused: single column, task-driven, no sidebarFiles:variant-output/compose-dashboard-A.html ← opened in browservariant-output/compose-dashboard-B.htmlvariant-output/compose-dashboard-C.htmlNext: pick A/B/C · compose [another page] · tokens A
DS Quick Triggers
| User types | Action | |
|---|---|---|
ds | Start design system generation workflow | |
ds confirm | Lock design system — constrains all future outputs | |
ds show | Print current DS summary (palette, fonts, status) | |
ds edit palette | Regenerate color section only, keep everything else | |
ds edit type | Regenerate typography section only | |
ds edit spacing | Regenerate spacing/radius section only | |
ds edit motion | Regenerate motion/animation section only | |
ds preview | Re-open design-system-preview.html in browser | |
ds reset | Remove DS lock, allow aesthetic invention again | |
compose [page] | Assemble page from registered components | |
compose [page] using A B C | Compose using only specified components | |
registry | Print component registry (which components are built) |
When DS is NOT Confirmed
Standard Generate mode — full aesthetic invention per the normal workflow. Each variation picks its own palette, fonts, and direction.
When DS IS Confirmed
Visual language is locked. The freedom space narrows to:
- Layout composition (grid, order, proportion)
- Content hierarchy (what's prominent, what's secondary)
- Interaction specifics (animation choreography within motion tokens)
- Copywriting and content strategy
Print a one-line reminder on every generation:
✦ DS locked: Amber Warm · DM Sans + Newsreader · variations differ in layout only