Files
Keysat 6f486c4475 Mark recap Case-B design retrofit done; log cleanup-execution learnings
- Flip recap's Case-B /design backfill from "in flight" -> done in
  ROADMAP/AGENTS: contract extracted + two-phase conformance cleanup
  shipped (recap app 0.2.161).
- Add three cleanup-execution Field notes to guides/design.md:
  CSS-value-position var-ify scoping, exclude standalone no-:root
  exports, border-radius-clamp capsule snapping.
- Note the standalone-export literal-hex exception in design-checker.md's
  Color dimension.
2026-06-17 09:42:28 -05:00

21 KiB

Design round-trip — orchestration guide

Substance file per the portability protocol. Vendor wrappers (e.g. adapters/claude/commands/design.md) point here; this guide is self-contained and written as plain prose any orchestrating agent could follow. This is also the authoritative definition of the design/ folder convention that /new-project scaffolds and the design-checker agent audits against — both point here.

You run the design round-trip for a repo that has (or will have) a user-facing interface: you establish the look — by scoping a fresh design, importing prior guidelines, or extracting the de-facto design already in the code — then (optionally) take it through an external visual tool (Anthropic's Claude Design in the cloud is the default front-end, but Figma or a plain conversation feed the same contract), and distill the result into a small set of durable, vendor-neutral, on-disk design artifacts that every future agent reads before building UI. You run in the main thread — establishing a look is an interactive, iterative conversation, not a delegated job — so you talk to the user and react to what they show you. Do not behave like a subagent.

The arc: read the situation → establish the design intent → (optionally) round-trip through the cloud tool → distill into the repo → promote what you learned. The principle underneath: the cloud tool is an interchangeable front-end; what lives in the repo is a DESIGN.md brand brief plus a tokens.tokens.json token file, and those two files are the contract. Never let the repo depend on a proprietary export format — if Claude Design vanished tomorrow, the on-disk contract and everything that reads it must still stand.

Posture (how to run the conversation)

Be a collaborator drawing out a look the user may not be able to name yet. Lead with inspiration, not specification. The user often won't know exactly what they want — that's fine and expected. Invite them to show you references: "drop any screenshots of apps/sites whose look you like into design/inspiration/, or paste them here." React to each concretely (what about it works — the restraint, the density, the palette, the type?), build a shared vocabulary, and converge. Propose a draft direction and let them correct it rather than interrogating them. At most a focused question or two per turn. Scale the ceremony to the surface: a single admin panel needs a light brief; a public landing page or a consumer app deserves the full walk. And push back — if two references pull in opposite directions, or a stated brand value contradicts the inspiration, name it.

The on-disk contract: the design/ folder

Every repo with a user-facing surface carries a design/ folder. This is the layout you create and maintain (folder name is design/, not brand/):

design/
  BRIEF.md             # pre-flight: the scoped input packet handed to the cloud tool (fresh/redesign runs)
  DESIGN.md            # the durable brand brief — the contract agents read before UI work
  tokens.tokens.json   # W3C DTCG design tokens — the machine-readable value source
  inspiration/         # reference images + UI screenshots the user likes (first-class input; kept in git)
  brand/               # logo.svg, fonts, generated palette.css and other delivered assets
  _imports/<date>/     # raw export bundles / prior guidelines, dated (kept in git for provenance)

DESIGN.md + tokens.tokens.json are the contract; everything else is scaffolding and provenance. inspiration/ and _imports/ are kept in git — the references record why the look is what it is, and the raw imports record where it came from. And the repo's AGENTS.md carries one line so every tool honors the contract:

Design: before building or changing any user-facing UI, read design/DESIGN.md and design/tokens.tokens.json and conform to them.

Phase 0 — Read the situation, pick the on-ramp

Before anything, determine which of four situations you're in — it sets the whole run:

  • Refinedesign/DESIGN.md already exists. You're updating an existing contract; skip to the phase that fits the change.
  • Import (Case A) — no contract, but the repo (or the user) has prior design/branding guidelines in some ad-hoc form (a doc, an HTML brand page, a Claude Design export). Go to Phase A → Import.
  • Extract (Case B) — no contract and no guidelines, but there's an existing user-facing UI whose look grew organically. Go to Phase A → Extract.
  • Fresh — no contract and no UI yet (a new or pre-UI project). Go to Phase A → Fresh.

Also settle the posture with the user up front for backfills: document-as-is (cheaply turn what exists into a contract) vs redesign/elevate (take it through the cloud tool to improve the look first). Document-as-is skips Phase B; redesign runs it.

Phase A — Establish the design intent

Pick the branch from Phase 0. All three converge on Phase C (the contract).

Fresh — inspiration-first scoping → design/BRIEF.md. Produce the packet the user walks into the cloud tool with, so they never start from a blank canvas. Work it out with the user, inspiration-first:

  1. Gather inspiration. Ask for reference images / UI screenshots; save under design/inspiration/. For each, capture in one line what the user likes about it, so the intent survives as text, not just pixels.
  2. Draft the brief in the five-part structure the cloud tool responds to: Goal, Layout, Content, Audience, Reference pattern (the inspiration, named), plus a ~200-word brand description (voice, mood, what it is not).
  3. Assemble the input checklist — a repo subdirectory to point at (never the whole monorepo), files to upload (logo, fonts, inspiration images, any existing contract), and live URLs to web-capture.
  4. Write design/BRIEF.md with the brief, brand description, inspiration list + notes, the input checklist, and a copy-pasteable prompt block.

Import (Case A) — locate → map → gap-fill → reconcile.

  1. Locate the prior guidelines — search the repo (branding docs, HTML brand pages, an exported bundle) and ask the user where they live or to paste/re-export them. Drop the raw artifact into design/_imports/<date>/ for provenance.
  2. Map their content onto our nine-section DESIGN.md structure and DTCG tokens — this is reformatting, not reinvention; preserve the actual values.
  3. Gap-fill — flag every section our ideal contract wants that the prior artifact doesn't cover (often: spacing scale, component states, responsive rules, do's/don'ts), and fill from the deployed UI or by asking.
  4. Reconcile the guidelines against what the product actually renders (landing, app, admin) — where the code diverges from the stated brand, surface it for the user's call.

Extract (Case B) — inventory → reconcile → (then formalize in Phase C).

  1. Inventory the as-built design. Read the user-facing code and produce a descriptive record of what the design currently is: every color used, type styles, spacing patterns, component treatments, depth/elevation — including the inconsistencies (the three almost-the-same blues, the four heading sizes). A read-only design-checker cannot do this (it needs a contract to check against), so inventory here in the main thread, optionally delegating a read-only reader to gather the raw values. First enumerate every styling surface — there is often more than one (a second stylesheet, a separate auth/landing page, CSS embedded in a string literal that ships a self-contained export); a grep over one <style> block silently misses the others. And read the brand mark / icon before the CSS — it frequently encodes the intended color story the code only partly realized.
  2. Reconcile with the user. Surface the conflicts and let them make the canonical calls — which blue is the blue, which scale is the scale. Organically-arrived-at does not mean correct; their taste decides. This is the high-value human step; don't auto-resolve it.

Phase B — (Optional) cloud round-trip

Run this only for fresh designs that need the visual tool, or redesign/elevate backfills. Document-as-is backfills skip it. You cannot run the cloud tool yourself — the default, Claude Design, is cloud-only at claude.ai/design, browser-driven, and the user does this step. Hand them a runbook (the steps below are written for Claude Design; adapt them for Figma or whatever visual tool the user prefers):

  • What to paste (the prompt block from BRIEF.md) and upload/point at (the checklist).
  • How to iterate: inline canvas comments, direct edits, sliders/toggles — not just re-prompting.
  • What to export: the coding-agent handoff bundle (Claude Design calls it "Handoff to Claude Code") — richest output: HTML/CSS/JS + per-state screenshots + a README of stack/ conventions — and a few screenshots. PDF/PPTX/Canva are presentation-only — skip them. Drop the bundle into design/_imports/<date>/.

If the user used Figma or just talked through the look, that's fine — the same Phase C applies.

Phase C — Distill into the durable contract

Turn the input — a cloud export, imported guidelines, or a reconciled inventory — into the vendor-neutral contract. When distilling a Claude Design export, note it is agent-mediated, not a mechanical export: Claude Design emits standalone HTML with inline, hardcoded CSS (no CSS custom properties, no DTCG tokens), so you read values out of the export/screenshots and author the contract yourself. Worth a human glance the first few runs.

  1. Preserve provenance. Confirm the raw input is committed under design/_imports/<date>/.
  2. Author design/DESIGN.md in the nine-section format coding agents parse: Visual theme, Color palette, Typography, Component styling, Layout, Depth/elevation, Do's and don'ts, Responsive behavior, Agent prompt guide (a short "when building UI here, do X" note).
  3. Author design/tokens.tokens.json — W3C DTCG (JSON; each token has $type and $value; groups nest; references use {group.token}). Pull colors, type scale, spacing, radii, shadows from the input. A design-tokens build tool (e.g. Style Dictionary) — or a token-extraction skill if your harness ships one — can assist; optional.
  4. Populate design/brand/ — logo, fonts, optionally a palette.css generated from the tokens via Style Dictionary.
  5. Wire the contract in. Ensure the AGENTS.md Design line is present; add if missing.
  6. Commit the design/ folder. For backfills, then fan out design-checker: the gap between the just-canonicalized contract and the current code is a cleanup backlog — capture it to that repo's ROADMAP.md (don't silently fix it in the same pass).

Phase D — Promote learnings (close the loop)

A /design run teaches you things. Two kinds, harvested from two places: the pre-flight scoping conversation (Phase A — what kinds of questions drew the look out, what inspiration prompts worked, where the brief was thin) and the distillation (Phase C — how the export actually behaved, what token-mapping heuristics held up, what tripped you). At the end of every run, ask: did this surface something generalizable about the process — not a fact about this project's brand?

  • If yes, promote it to the global standard. Propose an edit to this file (~/Projects/standards/guides/design.md) — usually a new bullet under Field notes below, or a refinement to a phase — so the next repo inherits it. Recurring design-checker violation patterns get the same treatment in guides/design-checker.md.
  • Keep the scope rule. Brand facts (this palette, this voice) live in the repo's design/DESIGN.md. Process learnings (how to scope, how to distill) live here in the global guide. Never cross them.
  • Show the diff and the rationale; don't silently rewrite the standard (per how-i-work.md).

The BRIEF.md skeleton

# Design brief — <surface/screen/app>

## Goal
<what this is; the single job it does>

## Layout
<structure, density, mobile-first?>

## Content
<the actual elements to include>

## Audience
<who uses it; the feeling it should evoke>

## Reference pattern (inspiration)
- inspiration/<file> — <what the user likes about it>

## Brand description (~200 words)
<voice, mood, what it is NOT>

## Inputs to bring to the cloud tool
- Point at: <repo subdir>
- Upload: <logo, fonts, inspiration images, existing DESIGN.md/tokens>
- Web-capture: <live URLs, if any>

## Prompt block (paste into the cloud tool, e.g. Claude Design)
> <Goal> … <Layout> … Include: <Content> … Audience: <…> … Style like <Reference>.

The tokens.tokens.json shape (W3C DTCG)

{
  "color": {
    "brand": { "$type": "color", "$value": "#1a1a2e" },
    "accent": { "$type": "color", "$value": "#e94560" }
  },
  "space": {
    "md": { "$type": "dimension", "$value": "16px" }
  },
  "font": {
    "body": { "$type": "fontFamily", "$value": "Inter" }
  }
}

Hard rules

  • The contract is DESIGN.md + tokens.tokens.json, never the proprietary bundle. The repo must stay readable and buildable if the cloud tool disappears. The bundle is provenance in _imports/, not a dependency.
  • Don't fabricate brand values. Every color, size, and rule traces to an export, an inspiration image, prior guidelines, the as-built code, or an explicit user choice — if you can't source it, ask, or mark it a placeholder to confirm. Never invent a palette from thin air.
  • Backfill reconciliation is the user's call. When the as-built design is inconsistent, you surface the conflicts; the user picks the canonical value. Don't auto-resolve taste.
  • Document-as-is vs redesign is the user's call, settled in Phase 0.
  • You don't run the cloud tool. Phase B is the user's; hand them a runbook and wait. Don't claim to have generated or exported anything you didn't.
  • Keep inspiration/ and _imports/ in git. They are the durable record of intent and origin. Never commit secrets; assets only.
  • Promote process learnings, not brand facts. Phase D feeds the global guide; brand facts stay in the repo.

Field notes

Accreted, field-tested learnings about the process — appended by Phase D as real runs teach us things. Brand facts never go here; only generalizable process/distillation knowledge.

  • (seed, from research 2026-06-16 — confirm on first live run) Claude Design exports standalone HTML with inline, hardcoded CSS — not CSS custom properties or DTCG tokens. Plan for Phase C token extraction to be agent-authored from the values, not a file copy.
  • (seed, from research 2026-06-16) The richest export is the "Handoff to Claude Code" bundle — HTML/CSS/JS + per-state screenshots + a README naming the target stack/conventions. Read that README first; it carries implementation intent beyond the visuals. PDF/PPTX/Canva exports are presentation-only and carry no usable style data.
  • (seed, from research 2026-06-16) On input, point Claude Design at a front-end subdirectory, not the whole monorepo — large trees choke the codebase scan. It accepts text prompts, image/doc uploads, live-URL web capture, and Figma files.
  • (import run, 2026-06-16, keysat) When a prior Claude Design artifact has a README that disagrees with its own shipped CSS/tokens (keysat's README named "Archivo" but every surface ships Manrope), the implemented stylesheet is authoritative for as-built values — encode that, and record the prose/code disagreement as a reconciliation note, not a guess.
  • (import run, 2026-06-16) Real type scales and shadows resist strict DTCG. As-built values use clamp() for the display scale, multi-layer composite shadows, and em letter-spacing — none map cleanly to a DTCG primitive. Keep them as documented strings and say so in the file's $description; don't force-fit or claim strict-spec compliance.
  • (import run, 2026-06-16) In document-as-is, encode the design system's stated intent in the contract even where the current code violates it (keysat's README forbids gold-as-fill, but the admin SPA ships two). design-checker then flags the code as the cleanup backlog — do not water the contract down to match non-compliant code.
  • (import run, 2026-06-16) "Each surface inlines its own copy of the tokens" is a recurring drift risk — name a canonical brand/palette.css, point DESIGN.md §Agent-guide at it, and log the consolidation as backlog. Before relocating an existing design dir into _imports/, grep that nothing imports it (in keysat, nothing did — safe to move).
  • (first Case-B extract run, 2026-06-16, recap) Harvest the inventory with grep frequency tables in the main thread, not a delegated reader. For a ~13k-line single file with ~450 inline styles, grep -oE '<pattern>' | sort | uniq -c | sort -rn per dimension (hex, rgba, font-size, weight, radius, shadow, breakpoint) produced a complete ranked census that stayed in context for the reconcile conversation — a sub-agent would have returned excerpts. The use-counts themselves are the reconcile evidence: "which dark is THE background" is answered by "132 uses + it's the PWA manifest.json theme_color," turning a taste call into a confirmation.
  • (first Case-B extract run, 2026-06-16) Disambiguate near-duplicates with frequency + an external anchor, not the eye. Ranking each value by use-count and cross-referencing a fixed reference (the PWA theme_color, the icon's gradient endpoints) reliably separated "one canonical + N strays" from "N intentional values," which is exactly the call to hand the user.
  • (first Case-B extract run, 2026-06-16) Present the reconcile conflicts as A/B/C forks, recommended-option-first, with the candidate values in each option's preview. Surfacing four conflicts (the background, the accent, the surface ladder, the type scale) as one batch of multiple-choice questions — each preview a monospace block showing the rival hexes in context — let the owner make every canonical call in a single turn instead of a long volley. This is the high-value human step; make it cheap to answer.
  • (first Case-B extract run, 2026-06-16) For a document-as-is extract, the "inspiration" is the code itself. There is no external reference set and no export bundle, so BRIEF.md and _imports/ are correctly skipped; instead write inspiration/README.md pointing at the harvested source files + the brand icon as the de-facto reference, and copy the icon into brand/. That preserves the why/where record the folder convention exists for.
  • (Case-B cleanup-execution run, 2026-06-17, recap) Scope an inline-hex→var() sweep to CSS-value position, not to style= attributes. Convert a hex only where the character before # is not a quote/backslash (i.e. it's preceded by :/space/,). That one rule auto-dodges the spots that must stay literal — hex held in JS logic (const c = …, quoted ternary branches like ${on ? "#1e293b" : …}), SVG fill=/stroke= attributes, and <meta theme-color> — without a hand-kept exclusion list, and it beats style="…" boundary-matching (which breaks on inner quotes inside ${…}). Verify after: every introduced var() resolves against :root, and 0 mapped hexes remain in CSS-value position (proves no silent misses).
  • (Case-B cleanup-execution run, 2026-06-17, recap) Exclude standalone generated documents from var-ification. A self-contained export (share page, print/PDF view, email body) ships its own <style> with no :root, so var(--token) won't resolve there — its literal hex is correct, not drift. Identify those regions (by line range or by the builder fn) and skip them. Snapping off-scale values inside them is still fine, since that's a literal change.
  • (Case-B cleanup-execution run, 2026-06-17, recap) border-radius clamps to half the shorter side — use it to snap capsules for free. A pill-shaped control (e.g. an 18px-tall count badge at radius 9) renders identically at any radius ≥ half its height, so snapping up to the next scale step (9→10) is on-scale and pixel-identical. Snap capsules up, not down, to avoid a visible change.

Final report

Short summary: the on-ramp taken (refine/import/extract/fresh) and posture (document/redesign), the design/ files written or updated, where the run stands (brief ready for the cloud tool, or contract distilled and committed), any design-checker cleanup backlog captured, any Phase-D learning promoted to this guide, and the unmistakable next action. If blocked, say exactly what blocked you — never guess or fabricate a look.