Files
pbakaus_impeccable/site/public/docs/document.html
T
Paul BakausandClaude Fable 5 90f9eeb99b Split service layer into private impeccable-site repo
The public repo keeps the OSS promise surface: skill, CLI, extension,
tests, and the provider build. The site, labs, concept/composition
catalogs, image pipeline, Cloudflare functions, and authoring guide move
to pbakaus/impeccable-site.

concept-seed tests run against a synthetic fixture catalog; the plugin
icon and skill categories moved in-repo; build validation narrows to
README prose and non-site counts; release notes read from a sibling
impeccable-site checkout.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 22:41:53 -07:00

948 lines
62 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>/impeccable document | Impeccable</title>
<meta name="description" content="Generate a spec-compliant DESIGN.md that captures your visual system so every AI agent stays on-brand.">
<meta name="theme-color" content="#fafafa">
<link rel="canonical" href="https://impeccable.style/docs/document">
<link rel="icon" type="image/svg+xml" href="../favicon.svg">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,600;1,400&family=Instrument+Sans:wght@400;500;600;700&family=Space+Grotesk:wght@400;500;600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../css/sub-pages.css">
</head>
<body class="sub-page skills-layout-page">
<a href="#main" class="skip-link">Skip to content</a>
<!-- site-header v1 -->
<header class="site-header" data-site-header>
<a href="/" class="site-header-brand" aria-label="Impeccable home">
<svg class="site-header-brand-logo" viewBox="0 0 32 32" aria-hidden="true"><rect width="32" height="32" rx="6" fill="#1a1a1a"/><text x="16" y="24" font-family="system-ui, -apple-system, sans-serif" font-size="22" font-weight="500" fill="#f5f3ef" text-anchor="middle">/</text></svg>
<span class="site-header-brand-name">Impeccable</span>
</a>
<div class="site-header-right">
<nav class="site-header-nav" aria-label="Primary">
<a href="/" data-nav="home">Home</a>
<a href="/designing" data-nav="designing">Designing</a>
<a href="/docs" data-nav="docs" aria-current="page">Docs</a>
<a href="/slop" data-nav="slop">Slop</a>
<a href="/live-mode" data-nav="live">Live</a>
</nav>
<a href="https://github.com/pbakaus/impeccable" class="site-header-github" target="_blank" rel="noopener" aria-label="Impeccable on GitHub, 21k stars">
<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"/></svg>
<span class="site-header-github-label">21k</span>
<svg class="site-header-github-star" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 2l2.76 6.36L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l7.24-.91L12 2z"/></svg>
</a>
</div>
</header>
<main id="main">
<div class="skills-layout">
<aside class="skills-sidebar" aria-label="Documentation">
<button class="skills-sidebar-toggle" type="button" aria-expanded="false" aria-controls="skills-sidebar-inner">
<span class="skills-sidebar-toggle-label">/document</span>
<svg class="skills-sidebar-toggle-chevron" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>
</button>
<div class="skills-sidebar-inner" id="skills-sidebar-inner">
<p class="skills-sidebar-label">Docs</p>
<div class="skills-sidebar-group" data-category="tutorials">
<p class="skills-sidebar-group-title">Tutorials</p>
<ul class="skills-sidebar-list">
<li><a href="/tutorials/getting-started">Getting started</a></li>
<li><a href="/tutorials/iterate-live">Iterate on UI with Live Mode</a></li>
<li><a href="/tutorials/brand-vs-product">Brand vs product, pick a register</a></li>
<li><a href="/tutorials/critique-with-overlay">Critique with the visual overlay</a></li>
</ul>
</div>
<hr class="skills-sidebar-divider">
<div class="skills-sidebar-group" data-category="create">
<p class="skills-sidebar-group-title">Create</p>
<ul class="skills-sidebar-list">
<li><a href="/docs/impeccable">/impeccable</a></li>
<li><a href="/docs/craft">craft</a></li>
<li><a href="/docs/shape">shape</a></li>
</ul>
</div>
<div class="skills-sidebar-group" data-category="evaluate">
<p class="skills-sidebar-group-title">Evaluate</p>
<ul class="skills-sidebar-list">
<li><a href="/docs/audit">audit</a></li>
<li><a href="/docs/critique">critique</a></li>
</ul>
</div>
<div class="skills-sidebar-group" data-category="refine">
<p class="skills-sidebar-group-title">Refine</p>
<ul class="skills-sidebar-list">
<li><a href="/docs/animate">animate</a></li>
<li><a href="/docs/bolder">bolder</a></li>
<li><a href="/docs/colorize">colorize</a></li>
<li><a href="/docs/delight">delight</a></li>
<li><a href="/docs/layout">layout</a></li>
<li><a href="/docs/overdrive">overdrive</a></li>
<li><a href="/docs/quieter">quieter</a></li>
<li><a href="/docs/typeset">typeset</a></li>
</ul>
</div>
<div class="skills-sidebar-group" data-category="simplify">
<p class="skills-sidebar-group-title">Simplify</p>
<ul class="skills-sidebar-list">
<li><a href="/docs/adapt">adapt</a></li>
<li><a href="/docs/clarify">clarify</a></li>
<li><a href="/docs/distill">distill</a></li>
</ul>
</div>
<div class="skills-sidebar-group" data-category="harden">
<p class="skills-sidebar-group-title">Harden</p>
<ul class="skills-sidebar-list">
<li><a href="/docs/harden">harden</a></li>
<li><a href="/docs/onboard">onboard</a></li>
<li><a href="/docs/optimize">optimize</a></li>
<li><a href="/docs/polish">polish</a></li>
</ul>
</div>
<div class="skills-sidebar-group" data-category="system">
<p class="skills-sidebar-group-title">System</p>
<ul class="skills-sidebar-list">
<li><a href="/docs/document" aria-current="page">document</a></li>
<li><a href="/docs/extract">extract</a></li>
<li><a href="/docs/live">live</a></li>
<li><a href="/docs/teach">teach</a></li>
</ul>
</div>
</div>
</aside>
<div class="skills-main">
<article class="skill-detail">
<div class="skill-detail-hero">
<header class="skill-detail-header">
<p class="skill-detail-eyebrow"><a href="/docs">Docs</a> / System</p>
<h1 class="skill-detail-title"><span class="skill-detail-title-namespace"><span class="skill-detail-title-slash">/</span>impeccable</span>document</h1>
<p class="skill-detail-tagline">Generate a spec-compliant DESIGN.md that captures your visual system so every AI agent stays on-brand.</p>
<div class="skill-meta-strip">
<span class="skill-meta-chip skill-meta-category" data-category="system">System</span>
<span class="skill-meta-chip">User-invocable</span>
</div>
</header>
</div>
<section class="skill-detail-editorial prose">
<div class="docs-viz-hero">
<div class="docs-viz-file">
<div class="docs-viz-file-header">
<span class="docs-viz-file-name">DESIGN.md</span>
<span class="docs-viz-file-status">Google Stitch format</span>
</div>
<div class="docs-viz-designmd-section">
<div class="docs-viz-designmd-head">
<span class="docs-viz-designmd-num">01</span>
<span class="docs-viz-designmd-title">Overview</span>
</div>
<p class="docs-viz-designmd-note">Creative North Star: <em>"The Editorial Sanctuary."</em> Quiet type, generous air, one committed accent.</p>
</div>
<div class="docs-viz-designmd-section">
<div class="docs-viz-designmd-head">
<span class="docs-viz-designmd-num">02</span>
<span class="docs-viz-designmd-title">Colors</span>
</div>
<div class="docs-viz-designmd-swatches" aria-hidden="true">
<span class="docs-viz-designmd-swatch" style="background:#1a1a1a"></span>
<span class="docs-viz-designmd-swatch" style="background:#f5f3ef"></span>
<span class="docs-viz-designmd-swatch" style="background:oklch(60% 0.22 30)"></span>
<span class="docs-viz-designmd-swatch" style="background:oklch(90% 0.02 30)"></span>
</div>
</div>
<div class="docs-viz-designmd-section">
<div class="docs-viz-designmd-head">
<span class="docs-viz-designmd-num">03</span>
<span class="docs-viz-designmd-title">Typography</span>
</div>
<div class="docs-viz-designmd-type">
<span class="docs-viz-designmd-type-display">Aa</span>
<span class="docs-viz-designmd-type-body">Cormorant Garamond &middot; Instrument Sans</span>
</div>
</div>
<div class="docs-viz-designmd-section">
<div class="docs-viz-designmd-head">
<span class="docs-viz-designmd-num">04</span>
<span class="docs-viz-designmd-title">Elevation</span>
</div>
<p class="docs-viz-designmd-note">Flat by default. Shadows appear only as a response to state.</p>
</div>
<div class="docs-viz-designmd-section">
<div class="docs-viz-designmd-head">
<span class="docs-viz-designmd-num">05</span>
<span class="docs-viz-designmd-title">Components</span>
</div>
<div class="docs-viz-designmd-comps" aria-hidden="true">
<span class="docs-viz-designmd-btn">Subscribe</span>
<span class="docs-viz-designmd-chip">filter</span>
<span class="docs-viz-designmd-card">card</span>
</div>
</div>
<div class="docs-viz-designmd-section">
<div class="docs-viz-designmd-head">
<span class="docs-viz-designmd-num">06</span>
<span class="docs-viz-designmd-title">Do's and Don'ts</span>
</div>
<div class="docs-viz-designmd-rules">
<span class="docs-viz-designmd-do">Tint neutrals toward the accent hue.</span>
<span class="docs-viz-designmd-dont">Gradient text for emphasis.</span>
</div>
</div>
</div>
<p class="docs-viz-caption">The six sections are fixed, in a fixed order, with fixed names. Alongside, <code>DESIGN.json</code> ships as a machine-readable sidecar for the Live Mode design panel.</p>
</div>
<h2 id="when-to-use-it">When to use it</h2>
<p>Run <code>/impeccable document</code> once you have enough of a visual system to document: colors, typography, at least a button and a card. The command scans your codebase, extracts the tokens and component patterns it finds, and writes a <code>DESIGN.md</code> at the project root that follows the <a href="https://stitch.withgoogle.com/docs/design-md/format/" target="_blank" rel="noopener">Google Stitch DESIGN.md format</a>, six sections in a fixed order, interoperable with every other DESIGN.md-aware tool.</p>
<p>Reach for it when:</p>
<ul>
<li><strong>You just ran <code>/impeccable teach</code></strong> and <code>PRODUCT.md</code> now exists. Document is the matching visual-side file.</li>
<li><strong>A command nudged you toward it.</strong> Live, craft, and polish all read DESIGN.md. If it is missing, the skill suggests running document first.</li>
<li><strong>The design has drifted</strong> from an older DESIGN.md and the file no longer describes the live system.</li>
<li><strong>Before a large redesign</strong>, to capture current state as a reference for the next direction.</li>
</ul>
<p>For projects with no code yet (fresh <code>teach</code> run, nothing built), there is a seed mode: <code>/impeccable document --seed</code> asks five quick strategic questions (color strategy, type direction, motion energy, references, anti-references) and writes a scaffold. Re-run in scan mode once there is code.</p>
<h2 id="how-it-works">How it works</h2>
<p>The scan pass finds design assets in priority order: CSS custom properties, Tailwind config, CSS-in-JS themes, design token files, component source, the global stylesheet, and finally computed styles from the live rendered output if a browser is available. It auto-extracts everything it can, then asks one grouped question for the parts that need creative input: the <strong>Creative North Star</strong> (a single named metaphor for the whole system, like &quot;The Editorial Sanctuary&quot;), descriptive color names, the elevation philosophy, and the component character.</p>
<p>Output is a DESIGN.md with exactly six sections: Overview, Colors, Typography, Elevation, Components, Do&#39;s and Don&#39;ts. Headers are fixed character-for-character so the file is parseable by other tools. Alongside it, <code>DESIGN.json</code> is written as a machine-readable sidecar. That sidecar is what the live-mode design panel uses to render <em>this project&#39;s</em> actual button, input, nav, and card tiles instead of a generic approximation.</p>
<p>Every other command reads DESIGN.md on invocation. Variants, polishes, audits, and new features inherit the visual system without being told.</p>
<h2 id="try-it">Try it</h2>
<div class="code-block-wrap"><pre class="code-block"><code>/impeccable document</code></pre><button class="code-block-copy" type="button" data-copy="/impeccable document" aria-label="Copy to clipboard"></button></div>
<p>On a project with tokens already defined, this takes about two minutes: the scan finds your palette and type stack, you pick a North Star from 2 or 3 options, confirm descriptive color names (&quot;Deep Muted Teal-Navy&quot;, not &quot;blue-800&quot;), and the file lands at the project root.</p>
<p>On a fresh project:</p>
<div class="code-block-wrap"><pre class="code-block"><code>/impeccable document --seed</code></pre><button class="code-block-copy" type="button" data-copy="/impeccable document --seed" aria-label="Copy to clipboard"></button></div>
<p>Five questions, about five minutes. The file is a scaffold, marked with a <code>&lt;!-- SEED --&gt;</code> comment so it is honest about what it is. Re-run without the flag once you have implemented tokens.</p>
<h2 id="pitfalls">Pitfalls</h2>
<ul>
<li><strong>Running it too early.</strong> On a project with no implemented tokens, seed mode is right. Do not fabricate a full spec the code cannot back up. A fake DESIGN.md is worse than no DESIGN.md.</li>
<li><strong>Treating DESIGN.md as documentation for humans only.</strong> It is primarily for the AI. Every other command reads it. The format&#39;s forcefulness (&quot;never&quot;, &quot;always&quot;, Named Rules) is intentional.</li>
<li><strong>Adding a Layout / Motion / Responsive top-level section.</strong> The spec has six sections, in a fixed order, with fixed names. Fold layout or motion content into Overview (philosophy-level rules) or Components (per-component behavior).</li>
<li><strong>Overwriting an existing DESIGN.md silently.</strong> Document always confirms first. If you want to start fresh, rename the existing file out of the way or explicitly tell the skill to overwrite.</li>
</ul>
</section>
<section class="skill-source-card">
<header class="skill-source-card-header">
<span class="skill-source-card-label">reference/document.md</span>
<span class="skill-source-card-subtitle">Loaded when the impeccable skill routes to this command.</span>
</header>
<div class="skill-source-card-body prose">
<p>Generate a <code>DESIGN.md</code> file at the project root that captures the current visual design system, so AI agents generating new screens stay on-brand.</p>
<p>DESIGN.md follows the <a href="https://stitch.withgoogle.com/docs/design-md/format/" target="_blank" rel="noopener">official Google Stitch DESIGN.md format</a>: YAML frontmatter carrying machine-readable design tokens, followed by a markdown body with exactly six sections in a fixed order. <strong>Tokens are normative; prose provides context for how to apply them.</strong> Sections may be omitted when not relevant, but <strong>do not reorder them and do not rename them</strong>. Section headers must match the spec character-for-character so the file stays parseable by other DESIGN.md-aware tools (Stitch itself, awesome-design-md, skill-rest, etc.).</p>
<h2 id="the-frontmatter-token-schema">The frontmatter: token schema</h2>
<p>The YAML frontmatter is the machine-readable layer. It&#39;s what Stitch&#39;s linter validates and what the live panel renders tiles from. Keep it tight; every entry should correspond to a token the project actually uses.</p>
<div class="code-block-wrap"><pre class="code-block code-block--yaml"><code>---
name: &lt;project title&gt;
description: &lt;one-line tagline&gt;
colors:
primary: &quot;#b8422e&quot;
neutral-bg: &quot;#faf7f2&quot;
# ...one entry per extracted color; key = descriptive slug
typography:
display:
fontFamily: &quot;Cormorant Garamond, Georgia, serif&quot;
fontSize: &quot;clamp(2.5rem, 7vw, 4.5rem)&quot;
fontWeight: 300
lineHeight: 1
letterSpacing: &quot;normal&quot;
body:
# ...
rounded:
sm: &quot;4px&quot;
md: &quot;8px&quot;
spacing:
sm: &quot;8px&quot;
md: &quot;16px&quot;
components:
button-primary:
backgroundColor: &quot;{colors.primary}&quot;
textColor: &quot;{colors.neutral-bg}&quot;
rounded: &quot;{rounded.sm}&quot;
padding: &quot;16px 48px&quot;
button-primary-hover:
backgroundColor: &quot;{colors.primary-deep}&quot;
---</code></pre><button class="code-block-copy" type="button" data-copy="---
name: <project title>
description: <one-line tagline>
colors:
primary: &quot;#b8422e&quot;
neutral-bg: &quot;#faf7f2&quot;
# ...one entry per extracted color; key = descriptive slug
typography:
display:
fontFamily: &quot;Cormorant Garamond, Georgia, serif&quot;
fontSize: &quot;clamp(2.5rem, 7vw, 4.5rem)&quot;
fontWeight: 300
lineHeight: 1
letterSpacing: &quot;normal&quot;
body:
# ...
rounded:
sm: &quot;4px&quot;
md: &quot;8px&quot;
spacing:
sm: &quot;8px&quot;
md: &quot;16px&quot;
components:
button-primary:
backgroundColor: &quot;{colors.primary}&quot;
textColor: &quot;{colors.neutral-bg}&quot;
rounded: &quot;{rounded.sm}&quot;
padding: &quot;16px 48px&quot;
button-primary-hover:
backgroundColor: &quot;{colors.primary-deep}&quot;
---" aria-label="Copy to clipboard"></button></div>
<p>Rules that matter:</p>
<ul>
<li><strong>Token refs</strong> use <code>{path.to.token}</code> (e.g. <code>{colors.primary}</code>, <code>{rounded.md}</code>). Components may reference primitives; primitives may not reference each other.</li>
<li><strong>Stitch validates colors as hex sRGB only</strong> (<code>#RGB</code> / <code>#RGBA</code> / <code>#RRGGBB</code> / <code>#RRGGBBAA</code>); OKLCH/HSL/P3 trigger a linter warning, not a hard error. YAML accepts the string either way and our own parser is format-agnostic. Choose based on project posture: (a) if the project has an &quot;OKLCH-only&quot; doctrine or uses Display-P3 values that don&#39;t round-trip through sRGB, put OKLCH directly in the frontmatter and accept the Stitch linter warning; (b) if the project wants strict Stitch compliance or plans to use their Tailwind/DTCG export pipeline, put hex in the frontmatter and keep OKLCH in prose as the canonical reference. Never split the source of truth without explicit reason.</li>
<li><strong>Component sub-tokens</strong> are limited to 8 props: <code>backgroundColor</code>, <code>textColor</code>, <code>typography</code>, <code>rounded</code>, <code>padding</code>, <code>size</code>, <code>height</code>, <code>width</code>. Shadows, motion, focus rings, backdrop-filter — none of those fit. Carry them in the sidecar (Step 4b).</li>
<li><strong>Scale keys are open-ended.</strong> Use whatever names the project already uses (<code>warm-ash-cream</code>, <code>surface-container-low</code>). Don&#39;t rename to Material defaults.</li>
<li><strong>Variants are naming convention, not schema.</strong> <code>button-primary</code> / <code>button-primary-hover</code> / <code>button-primary-active</code> as sibling keys.</li>
</ul>
<h2 id="the-markdown-body-six-sections-exact-order">The markdown body: six sections (exact order)</h2>
<ol>
<li><code>## Overview</code></li>
<li><code>## Colors</code></li>
<li><code>## Typography</code></li>
<li><code>## Elevation</code></li>
<li><code>## Components</code></li>
<li><code>## Do&#39;s and Don&#39;ts</code></li>
</ol>
<p>Optional evocative subtitles are allowed in the form <code>## 2. Colors: The [Name] Palette</code> — Stitch&#39;s own outputs do this — but the literal word in each header (Overview, Colors, Typography, Elevation, Components, Do&#39;s and Don&#39;ts) must be present. Do NOT add extra top-level sections (Layout Principles, Responsive Behavior, Motion, Agent Prompt Guide). Fold that content into the six spec sections where it naturally belongs.</p>
<h2 id="when-to-run">When to run</h2>
<ul>
<li>The user just ran <code>/impeccable teach</code> and needs the visual side documented.</li>
<li>The skill noticed no <code>DESIGN.md</code> exists and nudged the user to create one.</li>
<li>An existing <code>DESIGN.md</code> is stale (the design has drifted).</li>
<li>Before a large redesign, to capture the current state as a reference.</li>
</ul>
<p>If a <code>DESIGN.md</code> already exists, <strong>do not silently overwrite it</strong>. Show the user the existing file and STOP and call the AskUserQuestion tool to clarify. whether to refresh, overwrite, or merge.</p>
<h2 id="two-paths">Two paths</h2>
<ul>
<li><strong>Scan mode</strong> (default): the project has design tokens, components, or rendered output. Extract, then confirm descriptive language. Use when there&#39;s code to analyze.</li>
<li><strong>Seed mode</strong>: the project is pre-implementation (fresh teach, nothing built yet). Interview for five high-level answers, write a minimal DESIGN.md marked <code>&lt;!-- SEED --&gt;</code>. Re-run in scan mode once there&#39;s code.</li>
</ul>
<p>Decide by scanning first (Scan mode Step 1). If the scan finds no tokens, no component files, and no rendered site, offer seed mode — don&#39;t silently switch. <code>/impeccable document --seed</code> forces seed mode regardless of code presence.</p>
<h2 id="scan-mode-approach-c-auto-extract-then-confirm-descriptive-language">Scan mode (approach C: auto-extract, then confirm descriptive language)</h2>
<h3 id="step-1-find-the-design-assets">Step 1: Find the design assets</h3>
<p>Search the codebase in priority order:</p>
<ol>
<li><strong>CSS custom properties</strong> — grep for <code>--color-</code>, <code>--font-</code>, <code>--spacing-</code>, <code>--radius-</code>, <code>--shadow-</code>, <code>--ease-</code>, <code>--duration-</code> declarations in CSS files (usually <code>src/styles/</code>, <code>public/css/</code>, <code>app/globals.css</code>, etc.). Record name, value, and the file it&#39;s defined in.</li>
<li><strong>Tailwind config</strong> — if <code>tailwind.config.{js,ts,mjs}</code> exists, read the <code>theme.extend</code> block for colors, fontFamily, spacing, borderRadius, boxShadow.</li>
<li><strong>CSS-in-JS theme files</strong> — styled-components, emotion, vanilla-extract, stitches: look for <code>theme.ts</code>, <code>tokens.ts</code>, or equivalent.</li>
<li><strong>Design token files</strong><code>tokens.json</code>, <code>design-tokens.json</code>, Style Dictionary output, W3C token community group format.</li>
<li><strong>Component library</strong> — scan the main button, card, input, navigation, dialog components. Note their variant APIs and default styles.</li>
<li><strong>Global stylesheet</strong> — the root CSS file usually has the base typography and color assignments.</li>
<li><strong>Visible rendered output</strong> — if browser automation tools are available, load the live site and sample computed styles from key elements (body, h1, a, button, .card). This catches values that tokens miss.</li>
</ol>
<h3 id="step-2-auto-extract-what-can-be-auto-extracted">Step 2: Auto-extract what can be auto-extracted</h3>
<p>Build a structured draft from the discovered tokens. For each token class:</p>
<ul>
<li><strong>Colors</strong>: Group into Primary / Secondary / Tertiary / Neutral (the Material-derived roles Stitch uses). If the project only has one accent, express it as Primary + Neutral — omit Secondary and Tertiary rather than inventing them.</li>
<li><strong>Typography</strong>: Map observed sizes and weights to the Material hierarchy (display / headline / title / body / label). Note font-family stacks and the scale ratio.</li>
<li><strong>Elevation</strong>: Catalogue the shadow vocabulary. If the project is flat and uses tonal layering instead, that&#39;s a valid answer — state it explicitly.</li>
<li><strong>Components</strong>: For each common component (button, card, input, chip, list item, tooltip, nav), extract shape (radius), color assignment, hover/focus treatment, internal padding.</li>
<li><strong>Spacing + layout</strong>: Fold into Overview or relevant Components. The spec does NOT have a Layout section.</li>
</ul>
<h3 id="step-2b-stage-the-frontmatter">Step 2b: Stage the frontmatter</h3>
<p>From the auto-extracted tokens, draft the YAML frontmatter now (you&#39;ll write it at the top of DESIGN.md in Step 4). This is the machine-readable layer — what the live panel and Stitch&#39;s linter consume.</p>
<ul>
<li><strong>Colors</strong>: one entry per extracted color. Key = descriptive slug (<code>warm-ash-cream</code>, <code>editorial-magenta</code>, not <code>blue-800</code>). Value = whichever format the project treats as canonical (OKLCH or hex — see the frontmatter rules above). Don&#39;t split the source of truth: one format in the frontmatter, don&#39;t redefine the same token in prose with a different value.</li>
<li><strong>Typography</strong>: one entry per role (<code>display</code>, <code>headline</code>, <code>title</code>, <code>body</code>, <code>label</code>). Typography is an object; include only the props that are real for the project (<code>fontFamily</code>, <code>fontSize</code>, <code>fontWeight</code>, <code>lineHeight</code>, <code>letterSpacing</code>, <code>fontFeature</code>, <code>fontVariation</code>).</li>
<li><strong>Rounded / Spacing</strong>: whatever scale steps the project actually uses, keyed by whatever scale name the project uses (<code>sm</code> / <code>md</code> / <code>lg</code>, or <code>surface-sm</code>, or numeric steps).</li>
<li><strong>Components</strong>: one entry per variant (<code>button-primary</code>, <code>button-primary-hover</code>, <code>button-ghost</code>). Reference primitives via <code>{colors.X}</code>, <code>{rounded.Y}</code>. If a variant needs a property Stitch&#39;s 8-prop set doesn&#39;t cover (shadow, focus ring, backdrop-filter), carry the full snippet in the sidecar instead.</li>
</ul>
<p>Skip anything the project doesn&#39;t have. Empty scale keys or fabricated tokens pollute the spec.</p>
<h3 id="step-3-ask-the-user-for-qualitative-language">Step 3: Ask the user for qualitative language</h3>
<p>The following require creative input that cannot be auto-extracted. Group them into one <code>AskUserQuestion</code> interaction:</p>
<ul>
<li><strong>Creative North Star</strong>: a single named metaphor for the whole system (&quot;The Editorial Sanctuary&quot;, &quot;The Golden State Curator&quot;, &quot;The Lab Notebook&quot;). Offer 2-3 options that honor PRODUCT.md&#39;s brand personality.</li>
<li><strong>Overview voice</strong>: mood adjectives, aesthetic philosophy in 2-3 sentences, anti-references (what the system should not feel like).</li>
<li><strong>Color character</strong> (for auto-extracted colors): descriptive names (&quot;Deep Muted Teal-Navy&quot;, not &quot;blue-800&quot;). Suggest 2-3 options per key color based on hue/saturation.</li>
<li><strong>Elevation philosophy</strong>: flat/layered/lifted. If shadows exist, is their role ambient or structural?</li>
<li><strong>Component philosophy</strong>: the feel of buttons, cards, inputs in one phrase (&quot;tactile and confident&quot; vs. &quot;refined and restrained&quot;).</li>
</ul>
<p>Quote a line from PRODUCT.md when possible so the user sees their own strategic language carry forward.</p>
<h3 id="step-4-write-designmd">Step 4: Write DESIGN.md</h3>
<p>The file opens with the YAML frontmatter staged in Step 2b (schema documented at the top of this reference), then the markdown body using the structure below. Headers must match character-for-character. Optional evocative subtitles (e.g. <code>## 2. Colors: The Coastal Palette</code>) are allowed.</p>
<div class="code-block-wrap"><pre class="code-block code-block--markdown"><code>---
name: [Project Title]
description: [one-line tagline]
colors:
# ... staged frontmatter from Step 2b
---
# Design System: [Project Title]
## 1. Overview
**Creative North Star: &quot;[Named metaphor in quotes]&quot;**
[2-3 paragraph holistic description: personality, density, aesthetic philosophy. Start from the North Star and work outward. State what this system explicitly rejects (pulled from PRODUCT.md&#39;s anti-references). End with a short **Key Characteristics:** bullet list.]
## 2. Colors
[Describe the palette character in one sentence.]
### Primary
- **[Descriptive Name]** (#HEX / oklch(...)): [Where and why this color is used. Be specific about context, not just role.]
### Secondary (optional — omit if the project has only one accent)
- **[Descriptive Name]** (#HEX): [Role.]
### Tertiary (optional)
- **[Descriptive Name]** (#HEX): [Role.]
### Neutral
- **[Descriptive Name]** (#HEX): [Text / background / border / divider role.]
- [...]
### Named Rules (optional, powerful)
**The [Rule Name] Rule.** [Short, forceful prohibition or doctrine — e.g. &quot;The One Voice Rule. The primary accent is used on ≤10% of any given screen. Its rarity is the point.&quot;]
## 3. Typography
**Display Font:** [Family] (with [fallback])
**Body Font:** [Family] (with [fallback])
**Label/Mono Font:** [Family, if distinct]
**Character:** [1-2 sentence personality description of the pairing.]
### Hierarchy
- **Display** ([weight], [size/clamp], [line-height]): [Purpose — where it appears.]
- **Headline** ([weight], [size], [line-height]): [Purpose.]
- **Title** ([weight], [size], [line-height]): [Purpose.]
- **Body** ([weight], [size], [line-height]): [Purpose. Include max line length like 6575ch if relevant.]
- **Label** ([weight], [size], [letter-spacing], [case if uppercase]): [Purpose.]
### Named Rules (optional)
**The [Rule Name] Rule.** [Short doctrine about type use.]
## 4. Elevation
[One paragraph: does this system use shadows, tonal layering, or a hybrid? If &quot;no shadows&quot;, say so explicitly and describe how depth is conveyed instead.]
### Shadow Vocabulary (if applicable)
- **[Role name]** (`box-shadow: [exact value]`): [When to use it.]
- [...]
### Named Rules (optional)
**The [Rule Name] Rule.** [e.g. &quot;The Flat-By-Default Rule. Surfaces are flat at rest. Shadows appear only as a response to state (hover, elevation, focus).&quot;]
## 5. Components
For each component, lead with a short character line, then specify shape, color assignment, states, and any distinctive behavior.
### Buttons
- **Shape:** [radius described, exact value in parens]
- **Primary:** [color assignment + padding, in semantic + exact terms]
- **Hover / Focus:** [transitions, treatments]
- **Secondary / Ghost / Tertiary (if applicable):** [brief description]
### Chips (if used)
- **Style:** [background, text color, border treatment]
- **State:** [selected / unselected, filter / action variants]
### Cards / Containers
- **Corner Style:** [radius]
- **Background:** [colors used]
- **Shadow Strategy:** [reference Elevation section]
- **Border:** [if any]
- **Internal Padding:** [scale]
### Inputs / Fields
- **Style:** [stroke, background, radius]
- **Focus:** [treatment — glow, border shift, etc.]
- **Error / Disabled:** [if applicable]
### Navigation
- **Style, typography, default/hover/active states, mobile treatment.**
### [Signature Component] (optional — if the project has a distinctive custom component worth documenting)
[Description.]
## 6. Do&#39;s and Don&#39;ts
Concrete, forceful guardrails. Lead each with &quot;Do&quot; or &quot;Don&#39;t&quot;. Be specific — include exact colors, pixel values, and named anti-patterns the user mentioned in PRODUCT.md. **Every anti-reference in PRODUCT.md should show up here as a &quot;Don&#39;t&quot; with the same language**, so the visual spec carries the strategic line through. Quote PRODUCT.md directly where possible: if PRODUCT.md says *&quot;avoid dark mode with purple gradients, neon accents, glassmorphism&quot;*, the Don&#39;ts here should repeat that by name.
### Do:
- **Do** [specific prescription with exact values / named rule].
- **Do** [...]
### Don&#39;t:
- **Don&#39;t** [specific prohibition — e.g. &quot;use border-left greater than 1px as a colored stripe&quot;].
- **Don&#39;t** [...]
- **Don&#39;t** [...]</code></pre><button class="code-block-copy" type="button" data-copy="---
name: [Project Title]
description: [one-line tagline]
colors:
# ... staged frontmatter from Step 2b
---
# Design System: [Project Title]
## 1. Overview
**Creative North Star: &quot;[Named metaphor in quotes]&quot;**
[2-3 paragraph holistic description: personality, density, aesthetic philosophy. Start from the North Star and work outward. State what this system explicitly rejects (pulled from PRODUCT.md's anti-references). End with a short **Key Characteristics:** bullet list.]
## 2. Colors
[Describe the palette character in one sentence.]
### Primary
- **[Descriptive Name]** (#HEX / oklch(...)): [Where and why this color is used. Be specific about context, not just role.]
### Secondary (optional — omit if the project has only one accent)
- **[Descriptive Name]** (#HEX): [Role.]
### Tertiary (optional)
- **[Descriptive Name]** (#HEX): [Role.]
### Neutral
- **[Descriptive Name]** (#HEX): [Text / background / border / divider role.]
- [...]
### Named Rules (optional, powerful)
**The [Rule Name] Rule.** [Short, forceful prohibition or doctrine — e.g. &quot;The One Voice Rule. The primary accent is used on ≤10% of any given screen. Its rarity is the point.&quot;]
## 3. Typography
**Display Font:** [Family] (with [fallback])
**Body Font:** [Family] (with [fallback])
**Label/Mono Font:** [Family, if distinct]
**Character:** [1-2 sentence personality description of the pairing.]
### Hierarchy
- **Display** ([weight], [size/clamp], [line-height]): [Purpose — where it appears.]
- **Headline** ([weight], [size], [line-height]): [Purpose.]
- **Title** ([weight], [size], [line-height]): [Purpose.]
- **Body** ([weight], [size], [line-height]): [Purpose. Include max line length like 6575ch if relevant.]
- **Label** ([weight], [size], [letter-spacing], [case if uppercase]): [Purpose.]
### Named Rules (optional)
**The [Rule Name] Rule.** [Short doctrine about type use.]
## 4. Elevation
[One paragraph: does this system use shadows, tonal layering, or a hybrid? If &quot;no shadows&quot;, say so explicitly and describe how depth is conveyed instead.]
### Shadow Vocabulary (if applicable)
- **[Role name]** (`box-shadow: [exact value]`): [When to use it.]
- [...]
### Named Rules (optional)
**The [Rule Name] Rule.** [e.g. &quot;The Flat-By-Default Rule. Surfaces are flat at rest. Shadows appear only as a response to state (hover, elevation, focus).&quot;]
## 5. Components
For each component, lead with a short character line, then specify shape, color assignment, states, and any distinctive behavior.
### Buttons
- **Shape:** [radius described, exact value in parens]
- **Primary:** [color assignment + padding, in semantic + exact terms]
- **Hover / Focus:** [transitions, treatments]
- **Secondary / Ghost / Tertiary (if applicable):** [brief description]
### Chips (if used)
- **Style:** [background, text color, border treatment]
- **State:** [selected / unselected, filter / action variants]
### Cards / Containers
- **Corner Style:** [radius]
- **Background:** [colors used]
- **Shadow Strategy:** [reference Elevation section]
- **Border:** [if any]
- **Internal Padding:** [scale]
### Inputs / Fields
- **Style:** [stroke, background, radius]
- **Focus:** [treatment — glow, border shift, etc.]
- **Error / Disabled:** [if applicable]
### Navigation
- **Style, typography, default/hover/active states, mobile treatment.**
### [Signature Component] (optional — if the project has a distinctive custom component worth documenting)
[Description.]
## 6. Do's and Don'ts
Concrete, forceful guardrails. Lead each with &quot;Do&quot; or &quot;Don't&quot;. Be specific — include exact colors, pixel values, and named anti-patterns the user mentioned in PRODUCT.md. **Every anti-reference in PRODUCT.md should show up here as a &quot;Don't&quot; with the same language**, so the visual spec carries the strategic line through. Quote PRODUCT.md directly where possible: if PRODUCT.md says *&quot;avoid dark mode with purple gradients, neon accents, glassmorphism&quot;*, the Don'ts here should repeat that by name.
### Do:
- **Do** [specific prescription with exact values / named rule].
- **Do** [...]
### Don't:
- **Don't** [specific prohibition — e.g. &quot;use border-left greater than 1px as a colored stripe&quot;].
- **Don't** [...]
- **Don't** [...]" aria-label="Copy to clipboard"></button></div>
<h3 id="step-4b-write-designjson-sidecar-extensions-only">Step 4b: Write DESIGN.json sidecar (extensions only)</h3>
<p>The frontmatter owns token primitives (colors, typography, rounded, spacing, components). The sidecar at <code>DESIGN.json</code> carries <strong>what Stitch&#39;s schema can&#39;t hold</strong>: tonal ramps per color, shadow/elevation tokens, motion tokens, breakpoints, full component HTML/CSS snippets (the panel renders these into a shadow DOM), and narrative (north star, rules, do&#39;s/don&#39;ts). It extends the frontmatter, it doesn&#39;t duplicate it.</p>
<p>Regenerate the sidecar whenever you regenerate DESIGN.md. If the user only asks to refresh the sidecar (e.g., from the live panel&#39;s stale-hint), preserve DESIGN.md and write only DESIGN.json.</p>
<h4 id="schema">Schema</h4>
<div class="code-block-wrap"><pre class="code-block code-block--json"><code>{
&quot;schemaVersion&quot;: 2,
&quot;generatedAt&quot;: &quot;ISO-8601 string&quot;,
&quot;title&quot;: &quot;Design System: [Project Title]&quot;,
&quot;extensions&quot;: {
&quot;colorMeta&quot;: {
&quot;primary&quot;: { &quot;role&quot;: &quot;primary&quot;, &quot;displayName&quot;: &quot;Editorial Magenta&quot;, &quot;canonical&quot;: &quot;oklch(60% 0.25 350)&quot;, &quot;tonalRamp&quot;: [&quot;...&quot;, &quot;...&quot;, &quot;...&quot;] },
&quot;warm-ash-cream&quot;: { &quot;role&quot;: &quot;neutral&quot;, &quot;displayName&quot;: &quot;Warm Ash Cream&quot;, &quot;canonical&quot;: &quot;oklch(96% 0.005 350)&quot;, &quot;tonalRamp&quot;: [&quot;...&quot;, &quot;...&quot;, &quot;...&quot;] }
},
&quot;typographyMeta&quot;: {
&quot;display&quot;: { &quot;displayName&quot;: &quot;Display&quot;, &quot;purpose&quot;: &quot;Hero headlines only.&quot; }
},
&quot;shadows&quot;: [
{ &quot;name&quot;: &quot;ambient-low&quot;, &quot;value&quot;: &quot;0 4px 24px rgba(0,0,0,0.12)&quot;, &quot;purpose&quot;: &quot;Diffuse hover glow under accent elements.&quot; }
],
&quot;motion&quot;: [
{ &quot;name&quot;: &quot;ease-standard&quot;, &quot;value&quot;: &quot;cubic-bezier(0.4, 0, 0.2, 1)&quot;, &quot;purpose&quot;: &quot;Default easing for state transitions.&quot; }
],
&quot;breakpoints&quot;: [
{ &quot;name&quot;: &quot;sm&quot;, &quot;value&quot;: &quot;640px&quot; }
]
},
&quot;components&quot;: [
{
&quot;name&quot;: &quot;Primary Button&quot;,
&quot;kind&quot;: &quot;button | input | nav | chip | card | custom&quot;,
&quot;refersTo&quot;: &quot;button-primary&quot;,
&quot;description&quot;: &quot;One-line what and when.&quot;,
&quot;html&quot;: &quot;&lt;button class=\&quot;ds-btn-primary\&quot;&gt;GET STARTED&lt;/button&gt;&quot;,
&quot;css&quot;: &quot;.ds-btn-primary { background: #191c1d; color: #fff; padding: 16px 48px; letter-spacing: 0.05em; text-transform: uppercase; font-weight: 500; border: none; border-radius: 0; transition: background 0.2s, transform 0.2s; } .ds-btn-primary:hover { background: oklch(60% 0.25 350); transform: translateY(-2px); }&quot;
}
],
&quot;narrative&quot;: {
&quot;northStar&quot;: &quot;The Editorial Sanctuary&quot;,
&quot;overview&quot;: &quot;2-3 paragraphs of the philosophy — pulled from DESIGN.md Overview section.&quot;,
&quot;keyCharacteristics&quot;: [&quot;...&quot;, &quot;...&quot;],
&quot;rules&quot;: [{ &quot;name&quot;: &quot;The One Voice Rule&quot;, &quot;body&quot;: &quot;...&quot;, &quot;section&quot;: &quot;colors|typography|elevation&quot; }],
&quot;dos&quot;: [&quot;Do use ...&quot;],
&quot;donts&quot;: [&quot;Don&#39;t use ...&quot;]
}
}</code></pre><button class="code-block-copy" type="button" data-copy="{
&quot;schemaVersion&quot;: 2,
&quot;generatedAt&quot;: &quot;ISO-8601 string&quot;,
&quot;title&quot;: &quot;Design System: [Project Title]&quot;,
&quot;extensions&quot;: {
&quot;colorMeta&quot;: {
&quot;primary&quot;: { &quot;role&quot;: &quot;primary&quot;, &quot;displayName&quot;: &quot;Editorial Magenta&quot;, &quot;canonical&quot;: &quot;oklch(60% 0.25 350)&quot;, &quot;tonalRamp&quot;: [&quot;...&quot;, &quot;...&quot;, &quot;...&quot;] },
&quot;warm-ash-cream&quot;: { &quot;role&quot;: &quot;neutral&quot;, &quot;displayName&quot;: &quot;Warm Ash Cream&quot;, &quot;canonical&quot;: &quot;oklch(96% 0.005 350)&quot;, &quot;tonalRamp&quot;: [&quot;...&quot;, &quot;...&quot;, &quot;...&quot;] }
},
&quot;typographyMeta&quot;: {
&quot;display&quot;: { &quot;displayName&quot;: &quot;Display&quot;, &quot;purpose&quot;: &quot;Hero headlines only.&quot; }
},
&quot;shadows&quot;: [
{ &quot;name&quot;: &quot;ambient-low&quot;, &quot;value&quot;: &quot;0 4px 24px rgba(0,0,0,0.12)&quot;, &quot;purpose&quot;: &quot;Diffuse hover glow under accent elements.&quot; }
],
&quot;motion&quot;: [
{ &quot;name&quot;: &quot;ease-standard&quot;, &quot;value&quot;: &quot;cubic-bezier(0.4, 0, 0.2, 1)&quot;, &quot;purpose&quot;: &quot;Default easing for state transitions.&quot; }
],
&quot;breakpoints&quot;: [
{ &quot;name&quot;: &quot;sm&quot;, &quot;value&quot;: &quot;640px&quot; }
]
},
&quot;components&quot;: [
{
&quot;name&quot;: &quot;Primary Button&quot;,
&quot;kind&quot;: &quot;button | input | nav | chip | card | custom&quot;,
&quot;refersTo&quot;: &quot;button-primary&quot;,
&quot;description&quot;: &quot;One-line what and when.&quot;,
&quot;html&quot;: &quot;<button class=\&quot;ds-btn-primary\&quot;>GET STARTED</button>&quot;,
&quot;css&quot;: &quot;.ds-btn-primary { background: #191c1d; color: #fff; padding: 16px 48px; letter-spacing: 0.05em; text-transform: uppercase; font-weight: 500; border: none; border-radius: 0; transition: background 0.2s, transform 0.2s; } .ds-btn-primary:hover { background: oklch(60% 0.25 350); transform: translateY(-2px); }&quot;
}
],
&quot;narrative&quot;: {
&quot;northStar&quot;: &quot;The Editorial Sanctuary&quot;,
&quot;overview&quot;: &quot;2-3 paragraphs of the philosophy — pulled from DESIGN.md Overview section.&quot;,
&quot;keyCharacteristics&quot;: [&quot;...&quot;, &quot;...&quot;],
&quot;rules&quot;: [{ &quot;name&quot;: &quot;The One Voice Rule&quot;, &quot;body&quot;: &quot;...&quot;, &quot;section&quot;: &quot;colors|typography|elevation&quot; }],
&quot;dos&quot;: [&quot;Do use ...&quot;],
&quot;donts&quot;: [&quot;Don't use ...&quot;]
}
}" aria-label="Copy to clipboard"></button></div>
<p><strong>What changed from schemaVersion 1.</strong> The old sidecar carried token primitive arrays (<code>tokens.colors[]</code>, <code>tokens.typography[]</code>, etc.). Those values now live in the frontmatter. The sidecar only carries metadata that can&#39;t live in the frontmatter — tonal ramps, canonical OKLCH when the hex is an approximation, display names, role hints — keyed by the frontmatter token name (<code>colorMeta.&lt;token-name&gt;</code>, <code>typographyMeta.&lt;token-name&gt;</code>). Components still carry full HTML/CSS because Stitch&#39;s 8-prop set can&#39;t hold them.</p>
<h4 id="component-translation-rules">Component translation rules</h4>
<p>The <code>html</code> and <code>css</code> fields must be <strong>self-contained, drop-in snippets</strong> that render correctly when injected into a shadow DOM. The panel applies them directly — no post-processing, no framework runtime.</p>
<ol>
<li><strong>Tailwind expansion.</strong> If the source uses Tailwind (className=&quot;bg-primary text-white rounded-lg px-6 py-3&quot;), expand every utility to literal CSS properties in the <code>css</code> string. Do <strong>not</strong> reference Tailwind classes; do <strong>not</strong> assume a Tailwind CSS bundle is loaded. Each component is self-contained.</li>
<li><strong>Token resolution.</strong> If the project exposes tokens as CSS custom properties on <code>:root</code> (e.g. <code>--color-primary</code>, <code>--radius-md</code>), reference them via <code>var(--color-primary)</code> — they inherit through the shadow DOM and stay live-bound. If tokens live only in JS theme objects (styled-components, CSS-in-JS), resolve to literal values at generation time.</li>
<li><strong>Icons.</strong> Inline as SVG. Do not reference Lucide/Heroicons packages, icon fonts, or <code>&lt;img src=&quot;...&quot;&gt;</code>. A typical icon is 16-24px; copy the SVG path data directly.</li>
<li><strong>States.</strong> Include <code>:hover</code>, <code>:focus-visible</code>, and (if meaningful) <code>:active</code> rules inline. A static default-only snapshot makes the panel feel dead. Hover + focus rules in the CSS make it feel alive.</li>
<li><strong>Reset bloat.</strong> Extract only the component&#39;s <em>distinctive</em> CSS (background, color, padding, border-radius, typography, transition). Skip universal resets (<code>box-sizing: border-box</code>, <code>line-height: inherit</code>, <code>-webkit-font-smoothing</code>). The panel already has a neutral canvas; don&#39;t re-ship resets.</li>
<li><strong>Scoped class names.</strong> Prefix every class with <code>ds-</code> (e.g. <code>ds-btn-primary</code>, <code>ds-input-search</code>) so component CSS doesn&#39;t collide with other components&#39; CSS in the same shadow DOM.</li>
</ol>
<h4 id="what-to-include">What to include</h4>
<p>Aim for a tight set of <strong>5-10 components</strong> that best represent the visual system:</p>
<ul>
<li><strong>Canonical primitives (always include if the project has them):</strong> button (each variant as a separate component entry), input/text field, navigation, chip/tag, card.</li>
<li><strong>Signature components (include if distinctive):</strong> hero CTA, featured card, filter pill, any custom pattern the user mentioned as important in PRODUCT.md.</li>
<li><strong>Skip the rest.</strong> Utility components, form building blocks, wrapper layouts — not worth documenting unless visually distinctive.</li>
</ul>
<p>If the project has <strong>no component library yet</strong> (bare landing page, new project), synthesize canonical primitives from the tokens using best-practice defaults consistent with the DESIGN.md&#39;s rules. Every DESIGN.json has <em>something</em> to render, even on day zero.</p>
<h4 id="tonal-ramps">Tonal ramps</h4>
<p>For each color token, generate an 8-step <code>tonalRamp</code> array — dark to light, same hue and chroma, stepped lightness from ~15% to ~95%. The panel renders this as a strip under the swatch. If the project already defines a tonal scale (Material <code>surface-container-low</code> family, Tailwind-style <code>blue-50..blue-900</code>), use those values. Otherwise synthesize in OKLCH.</p>
<h4 id="narrative-mapping">Narrative mapping</h4>
<p>Pull directly from the DESIGN.md you just wrote:</p>
<ul>
<li><code>narrative.northStar</code> → the <code>**Creative North Star: &quot;...&quot;**</code> line from Overview</li>
<li><code>narrative.overview</code> → the philosophy paragraphs from Overview</li>
<li><code>narrative.keyCharacteristics</code> → the bulleted <code>**Key Characteristics:**</code> list</li>
<li><code>narrative.rules</code> → every <code>**The [Name] Rule.** [body]</code> across all sections, tagged with <code>section</code></li>
<li><code>narrative.dos</code> / <code>narrative.donts</code> → the bullet lists from Do&#39;s and Don&#39;ts verbatim</li>
</ul>
<p>Do not reword. The panel shows these as secondary collapsible context; the same voice that&#39;s in the Markdown carries through.</p>
<h3 id="step-5-confirm-refine-and-refresh-session-cache">Step 5: Confirm, refine, and refresh session cache</h3>
<ol>
<li>Show the user the full DESIGN.md you wrote. Briefly highlight the non-obvious creative choices (descriptive color names, atmosphere language, named rules).</li>
<li>Mention that <code>DESIGN.json</code> was also written alongside — the live panel will now render this project&#39;s actual button/input/nav primitives instead of generic approximations.</li>
<li>Offer to refine any section: &quot;Want me to revise a section, add component patterns I missed, or adjust the atmosphere language?&quot;</li>
<li><strong>Refresh the session cache.</strong> Run <code>node {{scripts_path}}/load-context.mjs</code> one final time so the newly-written DESIGN.md lands in conversation. Subsequent commands in this session will use the fresh version automatically without re-reading.</li>
</ol>
<h2 id="seed-mode">Seed mode</h2>
<p>For projects with no visual system to extract yet. Produces a minimal scaffold, not a full spec.</p>
<h3 id="step-1-confirm-seed-mode">Step 1: Confirm seed mode</h3>
<p>Before interviewing: &quot;There&#39;s no existing visual system to scan. I&#39;ll ask five quick questions to seed a starter DESIGN.md. You can re-run <code>/impeccable document</code> once there&#39;s code, to capture the real tokens and components. OK?&quot;</p>
<p>If the user prefers to skip, stop. No file.</p>
<h3 id="step-2-five-questions">Step 2: Five questions</h3>
<p>Group into one <code>AskUserQuestion</code> interaction. Options must be concrete.</p>
<ol>
<li><p><strong>Color strategy.</strong> Pick one:</p>
<ul>
<li>Restrained — tinted neutrals + one accent ≤10%</li>
<li>Committed — one saturated color carries 3060% of the surface</li>
<li>Full palette — 34 named color roles, each deliberate</li>
<li>Drenched — the surface IS the color</li>
</ul>
<p>Then: one hue family or anchor reference (&quot;deep teal&quot;, &quot;mustard&quot;, &quot;Klim #ff4500 orange&quot;).</p>
</li>
<li><p><strong>Typography direction.</strong> Pick one (specific fonts come later):</p>
<ul>
<li>Serif display + sans body</li>
<li>Single sans (warm / technical / geometric / humanist — pick a feel)</li>
<li>Display + mono</li>
<li>Mono-forward</li>
<li>Editorial script + sans</li>
</ul>
</li>
<li><p><strong>Motion energy.</strong> Pick one:</p>
<ul>
<li>Restrained — state changes only</li>
<li>Responsive — feedback + transitions, no choreography</li>
<li>Choreographed — orchestrated entrances, scroll-driven sequences</li>
</ul>
</li>
<li><p><strong>Three named references.</strong> Brands, products, printed objects. Not adjectives.</p>
</li>
<li><p><strong>One anti-reference.</strong> What it should NOT feel like. Also named.</p>
</li>
</ol>
<h3 id="step-3-write-seed-designmd">Step 3: Write seed DESIGN.md</h3>
<p>Use the six-section spec from Scan mode. Populate what the interview answers; leave the rest as honest placeholders. The seed is a scaffold, not a fabricated spec.</p>
<p>Lead the file with:</p>
<div class="code-block-wrap"><pre class="code-block code-block--markdown"><code>&lt;!-- SEED — re-run /impeccable document once there&#39;s code to capture the actual tokens and components. --&gt;</code></pre><button class="code-block-copy" type="button" data-copy="<!-- SEED — re-run /impeccable document once there's code to capture the actual tokens and components. -->" aria-label="Copy to clipboard"></button></div>
<p>Per-section guidance in seed mode:</p>
<ul>
<li><strong>Overview</strong>: Creative North Star and philosophy phrased from the answers (color strategy + motion energy + references). Reference the user&#39;s anti-reference directly.</li>
<li><strong>Colors</strong>: Color strategy as a Named Rule (e.g. <em>&quot;The Drenched Rule. The surface IS the color.&quot;</em>). Hue family or anchor reference. No hex values — mark as <code>[to be resolved during implementation]</code>.</li>
<li><strong>Typography</strong>: the direction the user picked (e.g. &quot;Serif display + sans body&quot;). No font names yet — <code>[font pairing to be chosen at implementation]</code>.</li>
<li><strong>Elevation</strong>: inferred from motion energy. Restrained/Responsive → flat by default; Choreographed → layered. One sentence.</li>
<li><strong>Components</strong>: omit entirely — no components exist yet.</li>
<li><strong>Do&#39;s and Don&#39;ts</strong>: carry PRODUCT.md&#39;s anti-references directly plus the anti-reference named in Q5.</li>
</ul>
<p>Seed mode writes a minimal frontmatter with <code>name</code> and <code>description</code> only — no colors, typography, rounded, spacing, or components yet. Real tokens land on the next Scan-mode run. Skip the <code>DESIGN.json</code> sidecar in seed mode for the same reason: nothing to render.</p>
<h3 id="step-4-confirm-and-refresh-session-cache">Step 4: Confirm and refresh session cache</h3>
<ol>
<li>Show the seed DESIGN.md. Call out that it is a seed (the marker is the literal commitment).</li>
<li>Tell the user: &quot;Re-run <code>/impeccable document</code> once you have some code. That pass will extract real tokens and generate the sidecar.&quot;</li>
<li>Run <code>node {{scripts_path}}/load-context.mjs</code> once so the seed lands in conversation for the rest of the session.</li>
</ol>
<h2 id="style-guidelines">Style guidelines</h2>
<ul>
<li><strong>Frontmatter first, prose second.</strong> Tokens go in the YAML frontmatter; prose contextualizes them. Don&#39;t redefine a token value in two places — the frontmatter is normative.</li>
<li><strong>Cite PRODUCT.md anti-references by name</strong> in the Do&#39;s and Don&#39;ts section. If PRODUCT.md lists &quot;SaaS landing-page clichés&quot; or &quot;generic AI tool marketing&quot; as anti-references, the DESIGN.md Don&#39;ts should repeat those phrases verbatim so the visual spec enforces the strategic line.</li>
<li><strong>Match the spec, don&#39;t invent new sections.</strong> The six section names are fixed. If you have Layout/Motion/Responsive content to document, fold it into Overview (philosophy-level rules) or Components (per-component behavior).</li>
<li><strong>Descriptive &gt; technical</strong>: &quot;Gently curved edges (8px radius)&quot; &gt; &quot;rounded-lg&quot;. Include the technical value in parens, lead with the description.</li>
<li><strong>Functional &gt; decorative</strong>: for each token, explain WHERE and WHY it&#39;s used, not just WHAT it is.</li>
<li><strong>Exact values in parens</strong>: hex codes, px/rem values, font weights — always the number in parens alongside the description.</li>
<li><strong>Use Named Rules</strong>: <code>**The [Name] Rule.** [short doctrine]</code>. These are memorable, citable, and much stickier for AI consumers than bullet lists. Stitch&#39;s own outputs use them heavily (&quot;The No-Line Rule&quot;, &quot;The Ghost Border Fallback&quot;). Aim for 1-3 per section.</li>
<li><strong>Be forceful</strong>. The voice of a design director. &quot;Prohibited&quot;, &quot;forbidden&quot;, &quot;never&quot;, &quot;always&quot; — not &quot;consider&quot;, &quot;might&quot;, &quot;prefer&quot;. Match PRODUCT.md&#39;s tone.</li>
<li><strong>Concrete anti-pattern tests</strong>. Stitch writes things like <em>&quot;If it looks like a 2014 app, the shadow is too dark and the blur is too small.&quot;</em> A one-sentence audit test beats a paragraph of principle.</li>
<li><strong>Reference PRODUCT.md</strong>. The anti-references section of PRODUCT.md should directly inform the Do&#39;s and Don&#39;ts section here. Quote or paraphrase.</li>
<li><strong>Group colors by role</strong>, not by hex-order or hue-order. Primary / Secondary / Tertiary / Neutral is the spec ordering.</li>
</ul>
<h2 id="pitfalls">Pitfalls</h2>
<ul>
<li>Don&#39;t paste raw CSS class names. Translate to descriptive language.</li>
<li>Don&#39;t extract every token. Stop at what&#39;s actually reused — one-offs pollute the system.</li>
<li>Don&#39;t invent components that don&#39;t exist. If the project only has buttons and cards, only document those.</li>
<li>Don&#39;t overwrite an existing DESIGN.md without asking.</li>
<li>Don&#39;t duplicate content from PRODUCT.md. DESIGN.md is strictly visual.</li>
<li>Don&#39;t add a &quot;Layout Principles&quot; or &quot;Motion&quot; or &quot;Responsive Behavior&quot; top-level section. The spec has six, not nine. Fold that content where it belongs.</li>
<li>Don&#39;t rename sections even slightly. &quot;Colors&quot; not &quot;Color Palette &amp; Roles&quot;. &quot;Typography&quot; not &quot;Typography Rules&quot;. Tooling parsing depends on exact headers.</li>
<li>Don&#39;t duplicate token values between frontmatter and prose. If a color is in <code>colors.primary</code> as hex, the prose can name it and describe its role but should not reassert a different hex. The frontmatter is normative.</li>
<li>Don&#39;t invent frontmatter token groups outside Stitch&#39;s schema (no <code>motion:</code>, <code>breakpoints:</code>, <code>shadows:</code> at the top level). Stitch&#39;s Zod schema only accepts <code>colors</code>, <code>typography</code>, <code>rounded</code>, <code>spacing</code>, <code>components</code>. Anything else belongs in the sidecar&#39;s <code>extensions</code>.</li>
</ul>
</div>
</section>
</article>
</div>
</div>
</main>
<script>
// Copy buttons on rendered code blocks
document.addEventListener('click', (e) => {
const btn = e.target.closest('[data-copy]');
if (!btn) return;
const text = btn.getAttribute('data-copy');
if (!text) return;
navigator.clipboard.writeText(text).then(() => {
btn.classList.add('is-copied');
setTimeout(() => btn.classList.remove('is-copied'), 1500);
}).catch(() => {});
});
// Mobile sidebar toggle (shown on narrow viewports, hidden on desktop).
document.addEventListener('click', (e) => {
const toggle = e.target.closest('.skills-sidebar-toggle');
if (!toggle) return;
const expanded = toggle.getAttribute('aria-expanded') === 'true';
toggle.setAttribute('aria-expanded', String(!expanded));
});
// Before/after split-compare: drag on touch, hover OR drag on mouse.
// Pointer events attach to the padded .split-comparison wrapper so
// there is a ~20px invisible buffer around the visible box. The
// divider only snaps back when the pointer leaves that outer buffer.
(function initSplitCompare() {
const wrappers = document.querySelectorAll('.split-comparison');
if (wrappers.length === 0) return;
const hasHover = matchMedia('(hover: hover)').matches;
const DEFAULT_POSITION = 50;
for (const wrapper of wrappers) {
const container = wrapper.querySelector('.split-container');
const splitAfter = wrapper.querySelector('.split-after');
const splitDivider = wrapper.querySelector('.split-divider');
if (!container || !splitAfter || !splitDivider) continue;
const tanAngle = Math.tan(10 * Math.PI / 180);
let skewOffset = 8;
const recalcSkew = () => {
const r = container.getBoundingClientRect();
if (r.width > 0 && r.height > 0) {
skewOffset = 50 * r.height * tanAngle / r.width;
}
};
recalcSkew();
window.addEventListener('resize', recalcSkew, { passive: true });
let targetX = DEFAULT_POSITION;
let currentX = DEFAULT_POSITION;
let rafId = null;
const paint = (pct) => {
const x = Math.max(-skewOffset, Math.min(100 + skewOffset, pct));
splitAfter.style.clipPath =
`polygon(${x + skewOffset}% 0%, 100% 0%, 100% 100%, ${x - skewOffset}% 100%)`;
splitDivider.style.left = `${x}%`;
};
const step = () => {
currentX += (targetX - currentX) * 0.2;
if (Math.abs(targetX - currentX) < 0.1) {
currentX = targetX;
rafId = null;
} else {
rafId = requestAnimationFrame(step);
}
paint(currentX);
};
const setTarget = (pct) => {
targetX = pct;
if (rafId === null) rafId = requestAnimationFrame(step);
};
paint(DEFAULT_POSITION);
// Percentage is always relative to the VISIBLE .split-container,
// not the padded .split-comparison wrapper. The pointer event
// target is the wrapper but the clip-path math uses the inner box.
const pctFromClientX = (clientX) => {
const rect = container.getBoundingClientRect();
return ((clientX - rect.left) / rect.width) * 100;
};
let hovering = false;
let dragging = false;
wrapper.addEventListener('pointerenter', (e) => {
if (hasHover && e.pointerType === 'mouse') {
hovering = true;
}
});
wrapper.addEventListener('pointerdown', (e) => {
dragging = true;
wrapper.setPointerCapture(e.pointerId);
setTarget(pctFromClientX(e.clientX));
});
wrapper.addEventListener('pointermove', (e) => {
if (dragging || hovering) {
setTarget(pctFromClientX(e.clientX));
}
});
const endDrag = (e) => {
if (dragging) {
dragging = false;
try { wrapper.releasePointerCapture(e.pointerId); } catch {}
}
};
wrapper.addEventListener('pointerup', endDrag);
wrapper.addEventListener('pointercancel', endDrag);
wrapper.addEventListener('pointerleave', (e) => {
endDrag(e);
if (hovering) {
hovering = false;
setTarget(DEFAULT_POSITION);
}
});
}
})();
</script>
</body>
</html>