From 9e3229493ba354d7f6e1dc451aff5a846d9324a7 Mon Sep 17 00:00:00 2001 From: Evan Harmon Date: Tue, 16 Jun 2026 22:20:33 -0500 Subject: [PATCH 01/16] feat(skills): upgrade design-handoff for greenfield + real export bundle Rework the design-handoff skill to match Claude Design's real .tar.gz "Handoff to Claude Code" bundle and to handle both reconciling into an existing design system and bootstrapping a new one from scratch. - Correct the export assumptions: drop the unverified ?v=N cache-busting, the task export:design/.design/tokens.json pipeline, and bundle screenshots. The bundle is README + chat transcript + prototype HTML/JSX/CSS + tokens.css + uploads, ported (not pasted) into the stack. - Add a greenfield bootstrap path (Tailwind v4 + shadcn init, globals.css, /brand, docs/design, Taskfile tasks) with per-framework recipes: TanStack Router, React Router/plain, and Astro 6 (React islands). - Decompose the monolithic SKILL.md into a lean (~220-line) phased/gated orchestrator plus nine progressive-disclosure references. - Add bundled assets: a zero-dependency OKLCH->WCAG static contrast checker (check-contrast.mjs, tested exit 0/1/2) and Taskfile.design.yml. - Preserve the strong parts: role-based token mapping, the dual contrast gate, the licensing gate, sign-off-before-deletion, and PR-not-merge. Update CLAUDE.md and README.md to reflect greenfield + the new structure. Co-Authored-By: Claude Opus 4.8 (1M context) --- CLAUDE.md | 2 +- README.md | 48 +-- ai/skills/design/design-handoff/SKILL.md | 289 ++++++++++-------- .../design-handoff/assets/Taskfile.design.yml | 50 +++ .../design-handoff/assets/check-contrast.mjs | 283 +++++++++++++++++ .../references/accessibility-verification.md | 80 +++++ .../references/assets-fonts-favicons.md | 90 ++++++ .../design-handoff/references/brand-page.md | 86 ++++++ .../references/components-and-states.md | 91 ++++++ .../references/ethics-and-licensing.md | 75 +++++ .../references/greenfield-bootstrap.md | 115 +++++++ .../references/ingesting-the-bundle.md | 83 +++++ .../references/token-reconciliation.md | 202 ++++++++---- .../references/verification-and-signoff.md | 74 +++++ 14 files changed, 1362 insertions(+), 206 deletions(-) create mode 100644 ai/skills/design/design-handoff/assets/Taskfile.design.yml create mode 100755 ai/skills/design/design-handoff/assets/check-contrast.mjs create mode 100644 ai/skills/design/design-handoff/references/accessibility-verification.md create mode 100644 ai/skills/design/design-handoff/references/assets-fonts-favicons.md create mode 100644 ai/skills/design/design-handoff/references/brand-page.md create mode 100644 ai/skills/design/design-handoff/references/components-and-states.md create mode 100644 ai/skills/design/design-handoff/references/ethics-and-licensing.md create mode 100644 ai/skills/design/design-handoff/references/greenfield-bootstrap.md create mode 100644 ai/skills/design/design-handoff/references/ingesting-the-bundle.md create mode 100644 ai/skills/design/design-handoff/references/verification-and-signoff.md diff --git a/CLAUDE.md b/CLAUDE.md index ef7b6f1..23dbda8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -60,7 +60,7 @@ Pre-commit is configured with `no-commit-to-branch` — direct commits to `main` - `ai/` — AI assets organized by type: `skills/`, `prompts/`, `agents/`, `rules/`, `evals/`, `tools/`, `workflows/`, `mcp/`, `knowledge/`, `memories/`. Most are placeholder directories for now; `skills/` is the populated one. Skills follow the Agent Skills convention — a `SKILL.md` with YAML frontmatter (`name`, `description`) plus optional `references/`. Current content is a `design/` suite for the Claude Design → code workflow: - `skills/design/explore-designs/` — guides using Claude Design to explore design directions (asks about the target frontend stack/tooling). - `skills/design/create-design-system/` — placeholder for design-system setup. - - `skills/design/design-handoff/` — full skill: reconcile a finished Claude Design export into a real codebase (tokens → shadcn/Tailwind v4 OKLCH, `/brand` page, contrast + licensing gates). + - `skills/design/design-handoff/` — full skill: implement a Claude Design `.tar.gz` handoff bundle into a real codebase — either reconcile into an existing design system or **bootstrap a new one** (tokens → shadcn/Tailwind v4 OKLCH, `/brand`, contrast + licensing gates). A lean phased/gated `SKILL.md` plus a `references/` set and bundled `assets/` (a zero-dependency contrast checker + Taskfile snippets). - `snippets/` — small reusable code snippets (placeholder). - `docs/` — project docs, e.g. the new-project checklist. - `test/` — tool configuration used by scans (e.g. `whisperConfig.yml` for Whispers); not actual tests. diff --git a/README.md b/README.md index 514226f..ddfa148 100644 --- a/README.md +++ b/README.md @@ -13,28 +13,28 @@ Author: Evan Harmon ## Repository Structure -| Directory | Contents | -| --- | --- | -| [`templates/`](./templates/) | Copy-paste boilerplates organized by category — see the [template index](#template-index) below | -| [`scripts/`](./scripts/) | Standalone scripts and utilities (AppleScript/Automator apps, command snippets) | -| [`ai/`](./ai/) | AI assets — skills, prompts, agents, rules, evals, etc. — see the [AI assets index](#ai-assets) below | -| [`snippets/`](./snippets/) | Small reusable code snippets (work in progress) | -| [`docs/`](./docs/) | Project docs, e.g. the new-project [checklist](./docs/CHECKLIST.md) | +| Directory | Contents | +| ---------------------------- | ----------------------------------------------------------------------------------------------------- | +| [`templates/`](./templates/) | Copy-paste boilerplates organized by category — see the [template index](#template-index) below | +| [`scripts/`](./scripts/) | Standalone scripts and utilities (AppleScript/Automator apps, command snippets) | +| [`ai/`](./ai/) | AI assets — skills, prompts, agents, rules, evals, etc. — see the [AI assets index](#ai-assets) below | +| [`snippets/`](./snippets/) | Small reusable code snippets (work in progress) | +| [`docs/`](./docs/) | Project docs, e.g. the new-project [checklist](./docs/CHECKLIST.md) | ## Template Index -| Template | Category | Description | -| --- | --- | --- | -| [`ansible.md`](./templates/ansible.md) | Ansible | Standard Ansible project directory structure and setup notes | -| [`docker/genericStack`](./templates/docker/genericStack/) | Docker | Generic multi-service Compose sandbox (Ubuntu, nginx, optional DB stack with Postgres/memcached/Adminer) plus `dc*` helper scripts | -| [`docker/n8n-compose`](./templates/docker/n8n-compose/) | Docker | n8n workflow automation behind Traefik with automatic HTTPS (Let's Encrypt) | -| [`scriptTemplates/shellScriptTemplate.sh`](./templates/scriptTemplates/shellScriptTemplate.sh) | Scripts | Shell script starter with safe defaults, traps, and arg parsing | -| [`scriptTemplates/pythonScriptTemplate.py`](./templates/scriptTemplates/pythonScriptTemplate.py) | Scripts | Python CLI starter with argparse, logging, and validation | -| [`scriptTemplates/goScriptTemplate.go`](./templates/scriptTemplates/goScriptTemplate.go) | Scripts | Go CLI starter with flag parsing, logging, and validation | -| [`serverlessFunctionTemplates/awsLambda.py`](./templates/serverlessFunctionTemplates/awsLambda.py) | Serverless | AWS Lambda handler (Python) with input validation and error responses | -| [`serverlessFunctionTemplates/gcpFunction.py`](./templates/serverlessFunctionTemplates/gcpFunction.py) | Serverless | Google Cloud Function (Python/Flask) with input validation and error responses | -| [`serverlessFunctionTemplates/netlifyFunction.js`](./templates/serverlessFunctionTemplates/netlifyFunction.js) | Serverless | Netlify Function (Node.js) that fetches and returns JSON from an API | -| [`webTemplates/netlifyForm.html`](./templates/webTemplates/netlifyForm.html) | Web | Netlify-ready HTML contact form with honeypot spam protection | +| Template | Category | Description | +| -------------------------------------------------------------------------------------------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------- | +| [`ansible.md`](./templates/ansible.md) | Ansible | Standard Ansible project directory structure and setup notes | +| [`docker/genericStack`](./templates/docker/genericStack/) | Docker | Generic multi-service Compose sandbox (Ubuntu, nginx, optional DB stack with Postgres/memcached/Adminer) plus `dc*` helper scripts | +| [`docker/n8n-compose`](./templates/docker/n8n-compose/) | Docker | n8n workflow automation behind Traefik with automatic HTTPS (Let's Encrypt) | +| [`scriptTemplates/shellScriptTemplate.sh`](./templates/scriptTemplates/shellScriptTemplate.sh) | Scripts | Shell script starter with safe defaults, traps, and arg parsing | +| [`scriptTemplates/pythonScriptTemplate.py`](./templates/scriptTemplates/pythonScriptTemplate.py) | Scripts | Python CLI starter with argparse, logging, and validation | +| [`scriptTemplates/goScriptTemplate.go`](./templates/scriptTemplates/goScriptTemplate.go) | Scripts | Go CLI starter with flag parsing, logging, and validation | +| [`serverlessFunctionTemplates/awsLambda.py`](./templates/serverlessFunctionTemplates/awsLambda.py) | Serverless | AWS Lambda handler (Python) with input validation and error responses | +| [`serverlessFunctionTemplates/gcpFunction.py`](./templates/serverlessFunctionTemplates/gcpFunction.py) | Serverless | Google Cloud Function (Python/Flask) with input validation and error responses | +| [`serverlessFunctionTemplates/netlifyFunction.js`](./templates/serverlessFunctionTemplates/netlifyFunction.js) | Serverless | Netlify Function (Node.js) that fetches and returns JSON from an API | +| [`webTemplates/netlifyForm.html`](./templates/webTemplates/netlifyForm.html) | Web | Netlify-ready HTML contact form with honeypot spam protection | See [`templates/README.md`](./templates/README.md) for conventions and per-category details. @@ -42,11 +42,11 @@ See [`templates/README.md`](./templates/README.md) for conventions and per-categ `ai/` collects reusable AI assets organized by type — `skills/`, `prompts/`, `agents/`, `rules/`, `evals/`, `tools/`, `workflows/`, `mcp/`, `knowledge/`, and `memories/`. Most are placeholders for now; the populated area is **skills**, which follow the Agent Skills convention (a `SKILL.md` with `name`/`description` frontmatter). -| Skill | Status | Description | -| --- | --- | --- | -| [`design/explore-designs`](./ai/skills/design/explore-designs/) | Draft | Guides using Claude Design to explore design directions across your frontend stack | -| [`design/create-design-system`](./ai/skills/design/create-design-system/) | Placeholder | Design-system setup | -| [`design/design-handoff`](./ai/skills/design/design-handoff/) | Ready | Reconciles a finished Claude Design export into a real codebase — tokens → shadcn/Tailwind v4 OKLCH, `/brand` page, contrast + licensing gates | +| Skill | Status | Description | +| ------------------------------------------------------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [`design/explore-designs`](./ai/skills/design/explore-designs/) | Draft | Guides using Claude Design to explore design directions across your frontend stack | +| [`design/create-design-system`](./ai/skills/design/create-design-system/) | Placeholder | Design-system setup | +| [`design/design-handoff`](./ai/skills/design/design-handoff/) | Ready | Implements a Claude Design `.tar.gz` handoff into a real codebase — reconcile an existing design system or bootstrap a new one (tokens → shadcn/Tailwind v4 OKLCH, `/brand`, contrast + licensing gates) | ## Inspired by Other Boilerplate Repos diff --git a/ai/skills/design/design-handoff/SKILL.md b/ai/skills/design/design-handoff/SKILL.md index a54a0ec..3c900d3 100644 --- a/ai/skills/design/design-handoff/SKILL.md +++ b/ai/skills/design/design-handoff/SKILL.md @@ -1,191 +1,220 @@ --- name: design-handoff description: >- - Implement a finished Claude Design in the actual code repo. Use this whenever - the user has exported a design from Claude Design (Anthropic's design canvas product) - and wants to turn it into real code — phrases like "I finished designing in - Claude Design", "implement this design", "do the design handoff", "I exported - the handoff bundle", "turn this design into code", etc. This is the Claude Design → - code-repo implementation workflow for the stack in this repo. - NOTE: this is NOT session/context handoff between - agent sessions — it is specifically about implementing a visual/UX design in code. - Trigger it even if the user doesn't say the word "skill". + Implement a finished Claude Design in this code repo — the Claude Design → code handoff. Use + whenever the user has a design from Claude Design (Anthropic's design canvas) to turn into real + code: phrases like "I finished designing in Claude Design", "implement this design", "do the design + handoff", "Handoff to Claude Code", "I exported the handoff bundle / tokens.css / a .tar.gz design", + "turn this design into code", or "set up a design system from this design". Handles both a single + feature AND establishing a new design system in a repo that has none. Targets React + Vite + + Tailwind v4 + shadcn/ui (Astro 6 and TanStack Router fully supported). This is NOT session/context + handoff between agent sessions — it is about implementing a visual/UX design in code. Trigger it + even if the user doesn't say the word "skill". --- # Design Handoff (Claude Design → repo) -Turn a finished Claude Design into working, on-brand code in this repo. The native Claude Design export drops a **handoff bundle** (usually standalone HTML/CSS/JS, screenshots, the tokens it used, and a README) into the repo; your job is to reconcile that generic bundle into _this repo's_ conventions — not to paste it in verbatim. +Turn a finished Claude Design into working, on-brand code in this repo. The "Handoff to Claude Code" +export is a **`.tar.gz` bundle** — a README, the design **chat transcript**, prototype HTML/JSX/CSS, a +`tokens.css`, and your uploads. That code is **prototype-grade** (it runs on in-browser Babel + UMD +React); your job is to **port** it into this repo's stack, not paste it in. There are two paths: +**reconcile** into an existing design system, or **bootstrap** a new one when the repo has none. -The core principle running through every step: **`src/styles/globals.css` is the canonical runtime token source, and `DESIGN.md` is the AI-facing statement of intent.** When they disagree, `globals.css` wins for runtime. The handoff bundle is the reference for the _intended_ design — it stays in place until **the user has reviewed the implementation and approved it**, and only then is it removed before merge. Never assume your implementation is correct; the user decides whether it matches the intent. +The core principle running through every step: **`src/styles/globals.css` is the canonical runtime +token source, and `DESIGN.md` is the AI-facing statement of intent.** When they disagree, `globals.css` +wins for runtime. The handoff bundle is the reference for the _intended_ design — it stays in place +until **the user has reviewed the implementation and approved it**, and only then is it removed before +merge. Never assume your implementation is correct; the user decides whether it matches the intent. ## Definition of done -Copy this checklist into your reply at the **start** of the run and tick each -box as you finish it. Do not report the handoff complete until every box is -checked. The three **gates** are blocking — you may not take the action a gate -guards until its box is true. +Copy this checklist into your reply at the **start** of the run and tick each box as you finish it. Do +not report the handoff complete until every box is checked. The three **gates** are blocking — you may +not take the action a gate guards until its box is true. Reconciliation -- [ ] Implemented from the canonical **un-suffixed** sources, not the `?v=N` snapshots -- [ ] Tokens merged into `globals.css` by **role** (not export name), for Tailwind v4, OKLCH, three-layer — export never blind-pasted -- [ ] `.dark` authored by hand: brand hue held constant, neutrals inverted +- [ ] Bundle ingested from the `.tar.gz`: README → chat transcript → HTML → `tokens.css`/`site.css` → + `js/*.jsx` (read for intent and **ported**, never pasted into `src/`) +- [ ] Framework + router detected; greenfield-vs-brownfield decided +- [ ] Tokens merged into `globals.css` by **role** (not export name) — Tailwind v4, OKLCH, three-layer; + export never blind-pasted +- [ ] `.dark` authored by hand (brand hue held, neutrals inverted); `--tw-prose-*` mapped if prose is + used - [ ] `DESIGN.md` reconciled, not clobbered Implementation -- [ ] shadcn/ui + Lucide only; styled **exclusively** with semantic tokens (zero arbitrary hex / one-off color literals) +- [ ] shadcn/ui + Lucide (named imports) only; styled **exclusively** with semantic tokens (zero + arbitrary hex / one-off color literals) - [ ] States covered: default, empty, loading, error, disabled -- [ ] `/brand` updated in the **same** change (can't drift from `DESIGN.md`/`globals.css`) -- [ ] Assets placed correctly: static → repo, dynamic/user media → R2; fonts self-hosted OFL/Apache `.woff2` in public/fonts; favicons generated from the mark -- [ ] OKLCH for color values; **three-tier semantic** token naming (primitive → semantic → component). +- [ ] `/brand` built/updated in the **same** change (scope asked at runtime) +- [ ] Assets placed (static → repo, user media → R2); fonts self-hosted OFL/Apache `.woff2`; favicons + generated from the mark Gates (each blocks the action it guards — do not proceed until true) -- [ ] **Licensing** (blocks commit): every font/icon/image cleared for commercial use; anything unclear stopped and flagged, not guessed -- [ ] **Contrast** (blocks sign-off): static `task lint:design` green **and** rendered ratios measured on the running page — both themes, every text role incl. long-form prose — reported as **numbers**, never "looks fine". WCAG AA (4.5:1). -- [ ] **Sign-off** (blocks deletion): screenshots shown (both themes, all built states), deltas surfaced, user has **explicitly approved** — not inferred from a green build or your own confidence +- [ ] **Licensing** (blocks commit): every font/icon/image cleared for commercial use; AI logos + flagged; anything unclear stopped, not guessed +- [ ] **Contrast** (blocks sign-off): static `task lint:design` green **and** rendered ratios measured + on the running page — both themes, every text role incl. long-form prose — reported as + **numbers**, never "looks fine". WCAG AA (4.5:1 text; 3:1 large/UI). +- [ ] **Sign-off** (blocks deletion): screenshots shown (both themes, all built states), deltas + surfaced, user has **explicitly approved** — not inferred from a green build or your confidence Close-out (only once the sign-off gate is true) - [ ] `task verify` green and the build compiles; hooks never bypassed (`--no-verify` prohibited) - [ ] Handoff bundle deleted (or a thin screenshot + intent note extracted first if states remain) -- [ ] `docs/design/` updated; DDR flagged if a real design-system decision was made -- [ ] Conventional Commit; PR opened for human review (no direct merge to `main`) - -## Inputs - -- A handoff bundle at `docs/design/handoff-/`. If you can't find one, ask the user where the export landed (or whether they've exported yet) before proceeding. -- The existing repo: `DESIGN.md` (root), `src/styles/globals.css`, `docs/design/`, `Taskfile.yml`, and the project's `CLAUDE.md`. - -## Stack (target for all implementation) - -TypeScript 6 or above, React, Vite, pnpm, Node 24 or above, Astro 6 or above, Tailwind CSS v4 or above, shadcn/ui, Cloudflare Pages/Workers. Favor **shadcn/ui** for components and **Lucide** for icons. +- [ ] `docs/design/` and `/brand` updated; DDR flagged if a real design-system decision was made +- [ ] Conventional Commit on a **feature branch**; PR opened for human review (no direct merge to + `main`) + +## Inputs & stack + +- A handoff bundle, usually unpacked to `docs/design/handoff-/`. If you can't find one, ask + the user where the export landed (or whether they've exported yet) before proceeding. +- The existing repo: `DESIGN.md` (root), `src/styles/globals.css`, `docs/design/`, `Taskfile.yml`, and + the project's `CLAUDE.md`. +- **Stack target:** TypeScript, React, Vite, pnpm, Tailwind CSS v4, shadcn/ui, Lucide, Cloudflare + Pages/Workers. Named primary router **TanStack Router**; **React Router**/plain React and **Astro 6** + fully supported. Favor **shadcn/ui** for components and **Lucide** for icons. + +## Detect first: framework, router, design-system state + +Before changing anything, read the repo to establish three things — they drive every later +file-placement decision: + +- **Framework + router.** Where `/brand`, routes, and shadcn live differs per framework: TanStack → + `src/routes/brand.tsx` + `src/components/ui`; React Router/plain → a normal `/brand` route; Astro → + `src/pages/brand.astro` with React **islands** for interactive specimens. Any other framework adapts + the same three roles (global stylesheet import, component dir, route entry) — never block on an + unrecognized router. Details in `greenfield-bootstrap.md`, `components-and-states.md`, + `brand-page.md`. +- **Greenfield vs brownfield.** A design system is present when `globals.css` has real `:root` semantic + tokens **and** a `/brand` route exists → reconcile into it. Otherwise → bootstrap it first (Phase 1). +- **Where the bundle landed.** Find `docs/design/handoff-*/`; if you can't, ask before proceeding. --- ## Procedure -Work through these in order. Explanations of _why_ are included because they change how you make judgment calls. - -### 0. Locate and read the bundle - -`view` the `docs/design/handoff-/` directory. Read the README (it states the design intent and structure), look at the screenshots, and note the tokens and component structure it used. This is your spec — but it's a _generic_ spec, not yet adapted to the stack. - -**Load the file the prototype actually renders, not a stale snapshot.** Claude Design exports cache-bust its scripts with query strings, e.g. `` holding every token's name, `oklch`, + hex, and (for pairs) contrast ratio, plus the breakpoints, type scale, and component inventory. + Optionally also serve it at `/brand.json` for heavier automation. +- **Keep the DOM semantic and stable** (correct heading order, consistent specimen markup) so scraping + and visual-regression stay reliable across builds. Every specimen renders from tokens (never + hardcoded) and works under the light/dark toggle and at every breakpoint — so one page powers token + docs, visual-regression, and contrast auditing at once. + +### Always-on essentials + +- A **light/dark toggle** wired to the `.dark` class so every specimen is checkable in both themes. +- An **accessibility note** — the target (WCAG 2.2 AA), the contrast commitment, focus/keyboard support, + and reduced-motion. +- Link the route discreetly — e.g. from the footer. ## Tier 2 — downloadable brand / press kit (opt-in) From fe744d0d570bf51d9eb58df1b98d50fb644d8cf6 Mon Sep 17 00:00:00 2001 From: Evan Harmon Date: Wed, 17 Jun 2026 11:47:45 -0500 Subject: [PATCH 05/16] docs(skills): make /brand collateral selectable by group with a fuller taxonomy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Specify exactly how the user picks collateral, and broaden the menu: - Selection mechanism (in the upfront intake): a multiSelect "what should /brand deliver beyond the core guide?" (brand/press kit, marketing collateral), then — if collateral — a multiSelect of four buckets, with the auto "Other" option capturing the long tail (AskUserQuestion caps a question at four options). Confirm platforms/sizes/formats per chosen group. - Four selectable buckets, each with concrete items and the right output formats: Social & web (per-platform sizes, OG cards, IAB ad sizes); Email (React Email, tested clients); Print (print-ready CMYK PDFs, bleed/crop); Presentations & documents (editable pptx/Slides, pitch deck, one-pager, doc templates). - Long-tail groups behind "Other": Motion & video, Merch & environmental, Product & app-store, Audio & bespoke. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../design-handoff/references/brand-page.md | 67 +++++++++++++------ 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/ai/skills/design/design-handoff/references/brand-page.md b/ai/skills/design/design-handoff/references/brand-page.md index 77d9236..daa4cd4 100644 --- a/ai/skills/design/design-handoff/references/brand-page.md +++ b/ai/skills/design/design-handoff/references/brand-page.md @@ -26,13 +26,23 @@ rather than duplicating. ## Decide how far to take it (asked up front) -`/brand` can range from a single-page style guide to a full brand/press kit with downloadable -collateral. The right scope depends on the handoff, so it's settled **up front in the intake batch** -(see SKILL.md, "Gather decisions up front") rather than mid-build — by the time you reach Phase 3 you -already have the answer. Offer the tiers below, defaulting to the core style guide and adding -collateral the user opts into. A `.pptx` deck and email templates are wasted effort for a small feature -handoff and exactly right for a brand launch — let the user decide. If the scope somehow wasn't -captured during intake, ask before building `/brand` rather than assuming. +`/brand` always includes the **core style guide** (Tier 1). The two opt-in layers — the **brand/press +kit** (Tier 2) and **marketing collateral** (Tier 3) — are settled **up front in the intake batch** (see +SKILL.md, "Gather decisions up front") rather than mid-build, so by Phase 3 you already have the answer. +Ask with `AskUserQuestion`: + +1. **Scope (multiSelect):** "Beyond the core style guide, what should `/brand` deliver?" — options + **Brand/press kit** and **Marketing collateral**. Selecting neither means core-only; choosing both is + fine. +2. **Collateral groups (only if collateral was chosen, multiSelect):** "Which collateral groups?" — offer + the four buckets from Tier 3 (Social & web, Email, Print, Presentations & documents). A question caps + at four options, so the buckets fill the slots and the auto **Other** option (free text) captures the + long tail (motion/video, merch, app-store, audio). For each chosen group, confirm the specifics — + which platforms, sizes, and formats — before generating. + +Default to core-only and add only what the user opts into: a `.pptx` deck and email templates are wasted +effort for a small feature handoff and exactly right for a brand launch. If scope somehow wasn't captured +during intake, ask before building `/brand` rather than assuming. ## Tier 1 — the core living style guide (always) @@ -128,18 +138,37 @@ This route is also a machine source of truth, so give it a stable, queryable str - Downloadable logos, wordmarks, monograms, and favicons (SVG + PNG) with usage do's and don'ts. - A press/brand-kit bundle (zip) of the above for external use. -## Tier 3 — collateral (opt-in, "when it makes sense") - -Generate only what the user asks for: - -- **Social media** — example posts/templates for LinkedIn, Instagram, Facebook, Bluesky, etc. -- **Print** — flyers, business cards, and the like, downloadable as PDFs. -- **Email** — templates and snippets, downloadable as HTML/CSS bundles, preferably built with **React - Email**. -- **Slides** — an example deck template in `.pptx` that is genuinely **editable** (real text and - shapes), not a flat, image-based deck. - -These tiers map onto the design suite's artifact taxonomy in `ai/skills/README.md` (Tokens / +## Tier 3 — collateral (opt-in, chosen by group) + +Collateral spans dozens of artifact types, so the user picks **groups** during intake (see "Decide how +far to take it"). Generate only the selected groups, build every piece from the same tokens so it stays +on-brand, and confirm the specifics (which platforms, sizes, formats) before producing. The four +selectable buckets: + +- **Social & web** — social profile art (avatar, cover/banner) and post/story templates sized per + platform (LinkedIn, Instagram, X, Facebook, Bluesky, TikTok, YouTube thumbnails); OG/share cards + (static or dynamically generated); display/banner ads in standard IAB sizes. Export at the correct + per-platform dimensions. +- **Email** — transactional and marketing templates, a newsletter layout, and an email signature; built + with **React Email**, shipped as HTML/CSS bundles, and tested against major clients (Gmail, Outlook, + Apple Mail). +- **Print** — business cards, letterhead, flyers, posters, brochures, stickers, and signage as + **print-ready PDFs** (CMYK, 300dpi, with bleed and crop marks). +- **Presentations & documents** — an **editable** `.pptx` (and/or Google Slides) deck with real text and + shapes (never a flat, image-based deck), a pitch deck, and a one-pager/sales sheet; plus document + templates (proposals, reports, case studies, invoices, résumé) for Word / Google Docs / Notion. + +Pick **Other** and name it for the long tail: + +- **Motion & video** — animated logo (Lottie), social-video templates, intro/outro stingers, animated + GIFs. +- **Merch & environmental** — apparel, stickers, tote bags, mugs; event/booth banners; office and + wayfinding signage. +- **Product & app-store** — app-store screenshots and listing graphics, in-app illustration and + empty-state art, onboarding graphics. +- **Audio & bespoke** — podcast cover art, audio-brand stings, or anything one-off. + +These groups map onto the design suite's artifact taxonomy in `ai/skills/README.md` (Tokens / Components / Pages & Templates / Assets / Collateral), so `/brand` stays aligned with the broader design-suite roadmap. From 98072aa20cace5ad2dbdb4e065c75a4e80aeab41 Mon Sep 17 00:00:00 2001 From: Evan Harmon Date: Wed, 17 Jun 2026 11:58:00 -0500 Subject: [PATCH 06/16] docs(skills): add podcast cover art to /brand Social & web group Stickers already live in the Print group; add podcast cover art to Social & web and drop the now-duplicate mention from the Audio long-tail item. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../design/design-handoff/references/brand-page.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ai/skills/design/design-handoff/references/brand-page.md b/ai/skills/design/design-handoff/references/brand-page.md index daa4cd4..7aeb08f 100644 --- a/ai/skills/design/design-handoff/references/brand-page.md +++ b/ai/skills/design/design-handoff/references/brand-page.md @@ -145,10 +145,10 @@ far to take it"). Generate only the selected groups, build every piece from the on-brand, and confirm the specifics (which platforms, sizes, formats) before producing. The four selectable buckets: -- **Social & web** — social profile art (avatar, cover/banner) and post/story templates sized per - platform (LinkedIn, Instagram, X, Facebook, Bluesky, TikTok, YouTube thumbnails); OG/share cards - (static or dynamically generated); display/banner ads in standard IAB sizes. Export at the correct - per-platform dimensions. +- **Social & web** — social profile art (avatar, cover/banner), post/story templates sized per platform + (LinkedIn, Instagram, X, Facebook, Bluesky, TikTok, YouTube thumbnails), and podcast cover art; + OG/share cards (static or dynamically generated); display/banner ads in standard IAB sizes. Export at + the correct per-platform dimensions. - **Email** — transactional and marketing templates, a newsletter layout, and an email signature; built with **React Email**, shipped as HTML/CSS bundles, and tested against major clients (Gmail, Outlook, Apple Mail). @@ -166,7 +166,7 @@ Pick **Other** and name it for the long tail: wayfinding signage. - **Product & app-store** — app-store screenshots and listing graphics, in-app illustration and empty-state art, onboarding graphics. -- **Audio & bespoke** — podcast cover art, audio-brand stings, or anything one-off. +- **Audio & bespoke** — audio-brand stings, sonic logos, or anything one-off. These groups map onto the design suite's artifact taxonomy in `ai/skills/README.md` (Tokens / Components / Pages & Templates / Assets / Collateral), so `/brand` stays aligned with the broader From e454bdec91c7c2b31efbb36de67e4d9b719d30a9 Mon Sep 17 00:00:00 2001 From: Evan Harmon Date: Wed, 17 Jun 2026 12:06:09 -0500 Subject: [PATCH 07/16] docs(skills): expand /brand Tier 2 into a full, automation-ready press kit Give the brand/press kit the same depth as Tier 1/3: a comprehensive, external- facing kit that is both a human page and a machine endpoint. - Contents: full logo suite (variants/formats), favicon set, color (hex/oklch/ rgb/cmyk/pantone + .ase + JSON), typography spec, a PDF brand book, boilerplate copy (short/medium/long), imagery, links and a usage license. - Packaging: a stable brand-kit.zip with a sane folder layout, plus a human press-kit page that previews and links everything (Tier 1 anchors + data-*). - Automation endpoint: a /brand/kit.json manifest (version, assets with per- format URLs, color set, fonts+licenses, boilerplate, links, contact), stable versioned asset URLs, and a CORS note. Internal token truth (Tier 1 #brand-tokens) vs external asset truth (this manifest). Co-Authored-By: Claude Opus 4.8 (1M context) --- .../design-handoff/references/brand-page.md | 54 ++++++++++++++++++- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/ai/skills/design/design-handoff/references/brand-page.md b/ai/skills/design/design-handoff/references/brand-page.md index 7aeb08f..fa45781 100644 --- a/ai/skills/design/design-handoff/references/brand-page.md +++ b/ai/skills/design/design-handoff/references/brand-page.md @@ -135,8 +135,58 @@ This route is also a machine source of truth, so give it a stable, queryable str ## Tier 2 — downloadable brand / press kit (opt-in) -- Downloadable logos, wordmarks, monograms, and favicons (SVG + PNG) with usage do's and don'ts. -- A press/brand-kit bundle (zip) of the above for external use. +The brand/press kit is the **external-facing** counterpart to the style guide: the assets, metadata, +and copy a partner, journalist, vendor, or downstream system needs to represent the brand correctly. +Build it as both a human page **and** a machine-consumable endpoint, generated from the same tokens and +source as `globals.css`/`DESIGN.md` so it never drifts. + +### Contents + +- **Logo suite** — primary lockup, monogram/mark, and wordmark; horizontal and stacked variants; in + full-color, single-color (black, white), and reversed (for dark backgrounds). Each as **SVG** + (primary) and transparent **PNG** at several resolutions; add PDF/EPS when print vendors need them. + Include the clear-space rule, minimum size, and a misuse row. +- **Favicon & app-icon set** — `favicon.ico`, `favicon.svg`, `apple-touch-icon.png` (180), PWA icons + (192/512 plus a maskable), and `site.webmanifest` (the set generated in `assets-fonts-favicons.md`). +- **Color** — the palette as swatches with **hex, oklch, RGB, and CMYK** (add Pantone/spot for print), + plus a downloadable Adobe swatch file (`.ase`) and a JSON block. +- **Typography** — the brand font files (or links and license), the fallback stack, and a one-page + type spec (families, roles, scale, weights). +- **Brand guidelines** — a downloadable **PDF brand book** (logo usage, color, type, spacing, voice, + do's and don'ts): the portable form of Tier 1. +- **Boilerplate copy** — company/product descriptions in short (~25 words), medium (~50), and long + (~100) forms; the tagline; founder/team bios; key facts (founded, location, category); and a + press/contact email. +- **Imagery** — approved hero/product shots, team/founder photos, and any brand illustration, at both + web and print resolution, with usage and credit notes. +- **Links & license** — canonical site, social handles, press contact, and a short usage statement + (what third parties may and may not do — e.g. don't alter or recolor the logo). + +### Packaging & download + +- A single **`brand-kit.zip`** at a stable URL, organized into `logo/`, `favicon/`, `color/`, `type/`, + `guidelines/`, `images/`, and `copy/`, with a `README` manifest at the root. +- A human **press-kit page** (e.g. `/brand/press-kit`, or a section of `/brand`) that previews + everything and links each asset plus the full zip — with the same stable anchors and `data-*` hooks + as Tier 1. + +### As an automation endpoint + +Expose the kit so other systems and agents can consume it programmatically, not just humans: + +- **`/brand/kit.json`** (or `/press-kit.json`) — a machine-readable **manifest** carrying a `version` + and `updatedAt`, every asset with its `name`, `description`, and per-format / per-resolution URLs, the + full color set (hex/oklch/rgb/cmyk/pantone), font names and license URLs, the boilerplate copy + variants, social links, and the press contact. Generate it from the same source as the tokens so it + can't drift. +- **Stable, versioned asset URLs** — each logo/icon/image at a durable path (e.g. `/brand/assets/...`), + and `brand-kit.zip` at a fixed URL automations can fetch. +- **CORS** — if the JSON or zip will be fetched cross-origin (partner sites, agents), enable permissive + CORS on those endpoints. +- Keep the manifest the single thing other tools read, and render the page from it — so page and + endpoint can never disagree. This extends Tier 1's automation structure outward: Tier 1's + `#brand-tokens` JSON is the _internal_ token truth; this manifest is the _external_ asset/metadata + truth. ## Tier 3 — collateral (opt-in, chosen by group) From fe2e4cad020d7d18ab7c4ffe01f8b4d9c397cf01 Mon Sep 17 00:00:00 2001 From: Evan Harmon Date: Wed, 17 Jun 2026 12:18:16 -0500 Subject: [PATCH 08/16] docs(skills): tighten design-handoff orchestration, gates, and chat tracking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Audit pass on SKILL.md as the orchestrator: - Fix step ordering: "Detect first" and "Gather decisions up front" sat above the Procedure even though they must run AFTER ingest (the intake text even assumes the intent was already read). Fold ingest -> detect -> decide into a single ordered Phase 0 so reading order matches execution order. Phases 1-7 and every reference's phase-number citation stay valid. - Gates: go from three to four explicit, phase-mapped, evidence-bearing gates — (1) static contrast [Phase 2], (2) licensing [Phase 4], (3) verification [Phase 5, now incl. rendered contrast + responsive + cross-browser], and (4) sign-off [Phase 6]. Rename the Phase 5 heading to match. - Chat tracking: strengthen the Definition of Done so the agent posts the checklist to the chat up front, ticks it as phases complete, and reports each gate's PASS with evidence (numbers, screenshots, the user's approval) before taking the guarded action — completion criteria stay visible in the conversation, not buried in the file. Co-Authored-By: Claude Opus 4.8 (1M context) --- ai/skills/design/design-handoff/SKILL.md | 116 +++++++++--------- .../design-handoff/references/brand-page.md | 2 +- 2 files changed, 56 insertions(+), 62 deletions(-) diff --git a/ai/skills/design/design-handoff/SKILL.md b/ai/skills/design/design-handoff/SKILL.md index c9175b0..45d1c74 100644 --- a/ai/skills/design/design-handoff/SKILL.md +++ b/ai/skills/design/design-handoff/SKILL.md @@ -28,15 +28,21 @@ merge. Never assume your implementation is correct; the user decides whether it ## Definition of done -Copy this checklist into your reply at the **start** of the run and tick each box as you finish it. Do -not report the handoff complete until every box is checked. The three **gates** are blocking — you may -not take the action a gate guards until its box is true. +**Render this in the chat — don't just leave it buried in this file.** At the **start** of the run, +paste the checklist below into your reply. Re-post it with boxes ticked as you finish each phase, and at +every **gate** state in the chat whether it **PASSED**, with the **evidence** (the measured numbers, the +screenshots taken, the user's words). Do **not** declare the handoff done until every box is ticked **in +the chat** and all four gates show **PASS with evidence**. Keeping the criteria visible in the +conversation is how you and the user know nothing was skipped. + +The four **gates** are blocking: you may not take the action a gate guards until it is green and you +have shown why in the chat. Reconciliation - [ ] Bundle ingested from the `.tar.gz`: README → chat transcript → HTML → `tokens.css`/`site.css` → `js/*.jsx` (read for intent and **ported**, never pasted into `src/`) -- [ ] Framework + router detected; greenfield-vs-brownfield decided +- [ ] Framework + router detected; greenfield-vs-brownfield decided; up-front questions asked - [ ] Tokens merged into `globals.css` by **role** (not export name) — Tailwind v4, OKLCH, three-layer; export never blind-pasted - [ ] `.dark` authored by hand (brand hue held, neutrals inverted); `--tw-prose-*` mapped if prose is @@ -48,29 +54,31 @@ Implementation - [ ] shadcn/ui + Lucide (named imports) only; styled **exclusively** with semantic tokens (zero arbitrary hex / one-off color literals) - [ ] States covered: default, empty, loading, error, disabled -- [ ] Responsive (mobile-first): holds at phone/tablet/desktop with no horizontal overflow; - cross-browser verified on Chromium, Firefox, and WebKit (incl. mobile Safari) via Playwright +- [ ] Responsive (mobile-first): holds at phone/tablet/desktop with no horizontal overflow - [ ] `/brand` built/updated in the **same** change (scope chosen up front during intake) - [ ] Assets placed (static → repo, user media → R2); fonts self-hosted OFL/Apache `.woff2`; favicons generated from the mark -Gates (each blocks the action it guards — do not proceed until true) +Gates — post **PASS + evidence** in the chat before taking the guarded action -- [ ] **Licensing** (blocks commit): every font/icon/image cleared for commercial use; AI logos - flagged; anything unclear stopped, not guessed -- [ ] **Contrast** (blocks sign-off): static `task lint:design` green **and** rendered ratios measured - on the running page — both themes, every text role incl. long-form prose — reported as - **numbers**, never "looks fine". WCAG AA (4.5:1 text; 3:1 large/UI). -- [ ] **Sign-off** (blocks deletion): screenshots shown (both themes, all built states), deltas - surfaced, user has **explicitly approved** — not inferred from a green build or your confidence +- [ ] **① Static contrast** (blocks implementation — Phase 2): `task lint:design` is green; every token + pair meets WCAG AA (4.5:1 text, 3:1 large/UI) in **both** themes. _Evidence:_ the checker output. +- [ ] **② Licensing** (blocks commit — Phase 4): every font/icon/image cleared for commercial use; AI + logos flagged; anything unclear stopped, not guessed. _Evidence:_ the per-asset license list. +- [ ] **③ Verification** (blocks sign-off — Phase 5): `task verify` green and the build compiles; + **rendered** contrast measured as **numbers** (both themes, every text role incl. long-form + prose); responsive at phone/tablet/desktop with no overflow; cross-browser on + Chromium/Firefox/WebKit (incl. mobile Safari). _Evidence:_ the numbers + the screenshot matrix. +- [ ] **④ Sign-off** (blocks deletion & close-out — Phase 6): screenshots shown (both themes, all + states, key breakpoints), deltas surfaced, user has **explicitly approved**. _Evidence:_ the + user's approval in the chat — never inferred from a green build or your own confidence. -Close-out (only once the sign-off gate is true) +Close-out (only once gate ④ is green) -- [ ] `task verify` green and the build compiles; hooks never bypassed (`--no-verify` prohibited) - [ ] Handoff bundle deleted (or a thin screenshot + intent note extracted first if states remain) - [ ] `docs/design/` and `/brand` updated; DDR flagged if a real design-system decision was made -- [ ] Conventional Commit on a **feature branch**; PR opened for human review (no direct merge to - `main`) +- [ ] Conventional Commit on a **feature branch**; PR opened for human review; hooks never bypassed + (`--no-verify` prohibited); no direct merge to `main` ## Inputs & stack @@ -82,52 +90,38 @@ Close-out (only once the sign-off gate is true) Pages/Workers. Named primary router **TanStack Router**; **React Router**/plain React and **Astro 6** fully supported. Favor **shadcn/ui** for components and **Lucide** for icons. -## Detect first: framework, router, design-system state - -Before changing anything, read the repo to establish three things — they drive every later -file-placement decision: - -- **Framework + router.** Where `/brand`, routes, and shadcn live differs per framework: TanStack → - `src/routes/brand.tsx` + `src/components/ui`; React Router/plain → a normal `/brand` route; Astro → - `src/pages/brand.astro` with React **islands** for interactive specimens. Any other framework adapts - the same three roles (global stylesheet import, component dir, route entry) — never block on an - unrecognized router. Details in `greenfield-bootstrap.md`, `components-and-states.md`, - `brand-page.md`. -- **Greenfield vs brownfield.** A design system is present when `globals.css` has real `:root` semantic - tokens **and** a `/brand` route exists → reconcile into it. Otherwise → bootstrap it first (Phase 1). -- **Where the bundle landed.** Find `docs/design/handoff-*/`; if you can't, ask before proceeding. - -## Gather decisions up front (one `AskUserQuestion` batch) - -You've now read the design intent and know the framework and greenfield-vs-brownfield — so this is the -moment to ask **everything you'll need from the user at once, in a single `AskUserQuestion` batch** (it -takes up to 4 questions). Front-loading lets Phases 1–5 run uninterrupted instead of stopping to ask -mid-build. Ask about: - -- **`/brand` scope** — core style guide → full brand/press kit with collateral (tiers in - `brand-page.md`); default to the core style guide. -- **Any other genuine ambiguity** the chat transcript left open — e.g. which routes/pages are in scope - for a feature, whether a specific font/icon set is required, dark mode if not obvious. Only ask what - you genuinely can't determine yourself; don't pad the batch. - -The **one** decision that can't be front-loaded is the **Phase 6 sign-off** — it is approval of the -_built_ result, so it necessarily comes after implementation. Settle everything else here. - --- ## Procedure -Work the phases in order. Each gate blocks the action it guards. Explanations of _why_ live in the -referenced files — read the reference when you reach its phase. - -### Phase 0 — Ingest the bundle - -Decompress the `.tar.gz` and read in the order its README dictates: `README.md` ("CODING AGENTS: READ -THIS FIRST") → `chats/chat1.md` (design intent — the bundle's real value) → the entry HTML → -`tokens.css`/`site.css` → the `js/*.jsx` components → `uploads/` (your inputs, **not** screenshots). -The code is prototype-grade; read it for structure and intent, then **port** it — don't paste -`.jsx`/`.html` into `src/`. Do not expect a `tokens.json`, a machine-readable spec, or per-state -screenshots — none ship. See `ingesting-the-bundle.md`. +Work the phases in order, and **track them in the chat** (see "Definition of done"): post the checklist +up front, tick boxes as you go, and report each gate's PASS with evidence. Explanations of _why_ live in +the referenced files — read the reference when you reach its phase. + +### Phase 0 — Ingest, detect & decide + +All the up-front orientation happens here, before any building: + +1. **Ingest.** Decompress the `.tar.gz` and read in the order its README dictates: `README.md` ("CODING + AGENTS: READ THIS FIRST") → `chats/chat1.md` (design intent — the bundle's real value) → the entry + HTML → `tokens.css`/`site.css` → the `js/*.jsx` components → `uploads/` (your inputs, **not** + screenshots). The code is prototype-grade; read it for structure and intent, then **port** it — + don't paste `.jsx`/`.html` into `src/`. Don't expect a `tokens.json`, a machine-readable spec, or + per-state screenshots — none ship. Locate the bundle at `docs/design/handoff-*/`; if you can't find + it, ask where the export landed before proceeding. (`ingesting-the-bundle.md`) +2. **Detect framework, router & design-system state** — they drive every later file-placement decision. + Router/framework: TanStack → `src/routes/brand.tsx` and `src/components/ui`; React Router/plain → a + normal `/brand` route; Astro → `src/pages/brand.astro` with React **islands** for interactive + specimens; any other framework maps the same three roles (global stylesheet import, component dir, + route entry) — never block on an unrecognized router. Greenfield vs brownfield: a design system is + present when `globals.css` has real `:root` semantic tokens **and** a `/brand` route exists → + reconcile into it (skip to Phase 2); otherwise → bootstrap first (Phase 1). +3. **Decide up front — one `AskUserQuestion` batch.** Now that you've read the intent and know the + stack, ask **everything you'll need at once** (up to 4 questions) so Phases 1–5 run uninterrupted: + the **`/brand` scope** (core guide → brand/press kit → collateral groups; `brand-page.md`), plus any + **genuine ambiguity** the transcript left open (routes/pages in scope, a required font/icon set, + dark mode if unclear). Only ask what you can't determine yourself. The **one** thing that can't be + front-loaded is the Phase 6 **sign-off** — it approves the built result. ### Phase 1 — Greenfield bootstrap (only if no design system exists) @@ -167,7 +161,7 @@ trademark-able but **not** copyrightable — recommend human edits + a clearance become the brand. If any license is unclear, **stop and flag it** rather than guessing. See `ethics-and-licensing.md`. -### Phase 5 — Verify — GATE: rendered contrast +### Phase 5 — Verify — GATE: verification (contrast, responsive, cross-browser) Run the gates (`task lint:design`, `check`, `verify` — create any that's missing; never `--no-verify`). Build, run the app, and screenshot every view in **both light and dark**, for every state, **and across diff --git a/ai/skills/design/design-handoff/references/brand-page.md b/ai/skills/design/design-handoff/references/brand-page.md index fa45781..5666ed8 100644 --- a/ai/skills/design/design-handoff/references/brand-page.md +++ b/ai/skills/design/design-handoff/references/brand-page.md @@ -28,7 +28,7 @@ rather than duplicating. `/brand` always includes the **core style guide** (Tier 1). The two opt-in layers — the **brand/press kit** (Tier 2) and **marketing collateral** (Tier 3) — are settled **up front in the intake batch** (see -SKILL.md, "Gather decisions up front") rather than mid-build, so by Phase 3 you already have the answer. +SKILL.md Phase 0, "Decide up front") rather than mid-build, so by Phase 3 you already have the answer. Ask with `AskUserQuestion`: 1. **Scope (multiSelect):** "Beyond the core style guide, what should `/brand` deliver?" — options From 48cf6f32d77bb74532922838779df341f32e8fcb Mon Sep 17 00:00:00 2001 From: Evan Harmon Date: Wed, 17 Jun 2026 12:29:56 -0500 Subject: [PATCH 09/16] feat(skills): provision Playwright (not just use it) in design-handoff verify MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Playwright's usage was documented but its setup wasn't — inconsistent with how the skill provisions its other gates, and broken for greenfield repos that have no Playwright at all. Now handled end to end: - Detect & provision: if @playwright/test is missing, install it + run `npx playwright install` + write playwright.config.ts (the same provisioning stance the skill takes for check-contrast.mjs and the Taskfile tasks). - Add a `verify:browsers` task to Taskfile.design.yml (Playwright sweep across Chromium/Firefox/WebKit × devices) so the cross-engine check runs like the other gates; wire it into the Phase 5 task list. - Fallback rule: agent-browser is Chromium-only and does NOT satisfy the cross-engine half of gate ③; if Playwright/cloud lab truly can't run, flag the gap to the user rather than reporting the cross-browser gate as PASS. Co-Authored-By: Claude Opus 4.8 (1M context) --- ai/skills/design/design-handoff/SKILL.md | 3 ++- .../design-handoff/assets/Taskfile.design.yml | 7 +++++++ .../responsive-and-cross-browser.md | 19 +++++++++++++++++-- .../references/verification-and-signoff.md | 3 +++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/ai/skills/design/design-handoff/SKILL.md b/ai/skills/design/design-handoff/SKILL.md index 45d1c74..7f86d0b 100644 --- a/ai/skills/design/design-handoff/SKILL.md +++ b/ai/skills/design/design-handoff/SKILL.md @@ -166,7 +166,8 @@ become the brand. If any license is unclear, **stop and flag it** rather than gu Run the gates (`task lint:design`, `check`, `verify` — create any that's missing; never `--no-verify`). Build, run the app, and screenshot every view in **both light and dark**, for every state, **and across key breakpoints (phone/tablet/desktop) and engines (Chromium/Firefox/WebKit incl. mobile Safari)** — -Playwright drives all three from one config (`responsive-and-cross-browser.md`). Then +Playwright drives all three from one config; set it up if the repo lacks it (agent-browser is +Chromium-only and doesn't substitute) — see `responsive-and-cross-browser.md`. Then measure **rendered** contrast on the running page (static tokens passing isn't enough — a runtime layer like `.prose` can override them): computed colors, both themes, every text role incl. long-form prose, reported as **numbers**. Fix and re-measure failures before showing the user. See diff --git a/ai/skills/design/design-handoff/assets/Taskfile.design.yml b/ai/skills/design/design-handoff/assets/Taskfile.design.yml index ad2eb23..fefbf82 100644 --- a/ai/skills/design/design-handoff/assets/Taskfile.design.yml +++ b/ai/skills/design/design-handoff/assets/Taskfile.design.yml @@ -39,6 +39,13 @@ tasks: - cmd: echo "Extracted to {{.DEST}}/ — open README.md first (the 'CODING AGENTS READ THIS FIRST' file), then chats/, then the HTML." silent: true + verify:browsers: + desc: Cross-browser/viewport screenshot sweep (Playwright — Chromium/Firefox/WebKit × devices) + # Requires @playwright/test and `npx playwright install`; the skill provisions both if missing. + # Needs the dev server running (or a Playwright webServer config). Captures the Phase 5 matrix. + cmds: + - npx playwright test {{.CLI_ARGS}} + # Aggregator for repos that DON'T already define `verify`. If the repo HAS a `verify`/`check` # task, delete this and instead add `lint:design` to that task's `deps:` so the design gate # runs as part of the normal verification pass. diff --git a/ai/skills/design/design-handoff/references/responsive-and-cross-browser.md b/ai/skills/design/design-handoff/references/responsive-and-cross-browser.md index 28bf9da..38f06fe 100644 --- a/ai/skills/design/design-handoff/references/responsive-and-cross-browser.md +++ b/ai/skills/design/design-handoff/references/responsive-and-cross-browser.md @@ -41,8 +41,18 @@ Pass on all three at your breakpoints and you've covered the matrix. Playwright drives **chromium, firefox, and webkit** from one config, emulates devices/viewports, and produces repeatable screenshots — and it can read computed styles, so it doubles for the rendered -contrast check in `accessibility-verification.md`. Most repos here already have it (`@playwright/test` -plus the Playwright CLI). Install the browser binaries once with `npx playwright install`. +contrast check in `accessibility-verification.md`. + +**Set it up if the repo doesn't have it.** Check for `@playwright/test`; if it's missing (always the +case in a greenfield repo), provision it — the same way this skill provisions its other gates: + +```bash +pnpm add -D @playwright/test +npx playwright install # download the chromium/firefox/webkit binaries (once) +``` + +Then write `playwright.config.ts` with the projects below and add the `verify:browsers` task from +`assets/Taskfile.design.yml`, so the cross-engine sweep runs like every other gate. ```ts // playwright.config.ts — the cross-engine × device matrix @@ -83,6 +93,11 @@ a cloud lab (BrowserStack, LambdaTest, Sauce Labs). Use whatever the repo standardizes on for interactive poking, but use Playwright (or a cloud lab) for the actual cross-engine verification. +If Playwright genuinely can't run here and only **agent-browser** is available, you can still do the +Chromium responsive pass with it — but the **cross-engine** half of gate ③ is then unmet. Provision +Playwright (or use a cloud lab); if neither is possible, **flag the gap to the user** rather than +reporting the cross-browser gate as PASS. + ## The Phase 5 matrix Capture every implemented view across `{light, dark}` × `{phone ~375, tablet ~768/1024, desktop diff --git a/ai/skills/design/design-handoff/references/verification-and-signoff.md b/ai/skills/design/design-handoff/references/verification-and-signoff.md index 9ba5092..3dd92d3 100644 --- a/ai/skills/design/design-handoff/references/verification-and-signoff.md +++ b/ai/skills/design/design-handoff/references/verification-and-signoff.md @@ -14,6 +14,9 @@ discipline. scan. - `task check` — typecheck + lint + format (fast static verification). - `task verify` — the fuller pass (build, etc.). + - `task verify:browsers` — the Playwright cross-engine/viewport screenshot sweep. Set Playwright up + if the repo lacks it (`responsive-and-cross-browser.md`); agent-browser is Chromium-only and does + **not** substitute for it. **Never use `--no-verify`** or otherwise skip git hooks — the hooks and CI are the authoritative gates, and bypassing them defeats the point. If a needed task doesn't exist in the repo, **add it** From 7794f35a9010211e87878f7c7302a48b482718a3 Mon Sep 17 00:00:00 2001 From: Evan Harmon Date: Wed, 17 Jun 2026 12:45:48 -0500 Subject: [PATCH 10/16] feat(skills): bundle a parameterized Playwright screenshot spec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ship the cross-browser sweep as a reusable template rather than making the agent write it from scratch each run — the matrix/iteration logic is stable and easy to get subtly wrong, while only a few inputs truly vary per project. - assets/brand-screenshots.spec.ts: a parameterized harness. Engine × device comes from playwright.config.ts `projects`; the spec adds route × theme and writes one full-page PNG per route × theme per project. Three marked fill-ins: ROUTES, baseURL/webServer, and setTheme() (defaults to shadcn's .dark class). Includes a commented per-specimen capture using the data-brand-specimen hooks. - Add `use.baseURL` + `webServer` to the config example so the spec runs. - Wire it through: verify:browsers runs it; documented in responsive-and-cross-browser.md and listed in SKILL.md's bundled assets. Co-Authored-By: Claude Opus 4.8 (1M context) --- ai/skills/design/design-handoff/SKILL.md | 7 ++- .../design-handoff/assets/Taskfile.design.yml | 5 +- .../assets/brand-screenshots.spec.ts | 53 +++++++++++++++++++ .../responsive-and-cross-browser.md | 22 ++++++-- 4 files changed, 80 insertions(+), 7 deletions(-) create mode 100644 ai/skills/design/design-handoff/assets/brand-screenshots.spec.ts diff --git a/ai/skills/design/design-handoff/SKILL.md b/ai/skills/design/design-handoff/SKILL.md index 7f86d0b..718a582 100644 --- a/ai/skills/design/design-handoff/SKILL.md +++ b/ai/skills/design/design-handoff/SKILL.md @@ -230,8 +230,11 @@ Bundled assets (the skill installs these into the target repo): - **`assets/check-contrast.mjs`** — zero-dependency static WCAG-AA token-contrast checker; copy to `scripts/check-contrast.mjs`. -- **`assets/Taskfile.design.yml`** — design task snippets (`lint:design`, `ingest:design`) to merge - into the repo's `Taskfile.yml`. +- **`assets/Taskfile.design.yml`** — design task snippets (`lint:design`, `ingest:design`, + `verify:browsers`) to merge into the repo's `Taskfile.yml`. +- **`assets/brand-screenshots.spec.ts`** — a parameterized Playwright sweep (route × theme × the + config's engine/device matrix); fill in `ROUTES`, `baseURL`/`webServer`, and `setTheme()`. Run by + `task verify:browsers`. ## Complements diff --git a/ai/skills/design/design-handoff/assets/Taskfile.design.yml b/ai/skills/design/design-handoff/assets/Taskfile.design.yml index fefbf82..5d81243 100644 --- a/ai/skills/design/design-handoff/assets/Taskfile.design.yml +++ b/ai/skills/design/design-handoff/assets/Taskfile.design.yml @@ -41,8 +41,9 @@ tasks: verify:browsers: desc: Cross-browser/viewport screenshot sweep (Playwright — Chromium/Firefox/WebKit × devices) - # Requires @playwright/test and `npx playwright install`; the skill provisions both if missing. - # Needs the dev server running (or a Playwright webServer config). Captures the Phase 5 matrix. + # Requires @playwright/test and `npx playwright install` (the skill provisions both if missing), + # plus a baseURL/webServer in playwright.config.ts. Runs the bundled brand-screenshots.spec.ts — + # the route × theme × engine/device sweep that captures the Phase 5 matrix. cmds: - npx playwright test {{.CLI_ARGS}} diff --git a/ai/skills/design/design-handoff/assets/brand-screenshots.spec.ts b/ai/skills/design/design-handoff/assets/brand-screenshots.spec.ts new file mode 100644 index 0000000..c753d81 --- /dev/null +++ b/ai/skills/design/design-handoff/assets/brand-screenshots.spec.ts @@ -0,0 +1,53 @@ +// brand-screenshots.spec.ts — bundled TEMPLATE for the design-handoff cross-browser sweep. +// +// Runs under `task verify:browsers` (i.e. `npx playwright test`). The engine × device axis comes from +// playwright.config.ts `projects` (chromium / firefox / webkit + iPhone / iPad); this spec adds the +// route × theme axis and writes one full-page PNG per route × theme per project, into +// screenshots//. +// +// It is a PARAMETERIZED template, not a from-scratch write — fill in three spots for the repo: +// 1. ROUTES below (always include "/brand"; add the feature's pages). +// 2. playwright.config.ts must set `use.baseURL` and a `webServer` that starts the dev server. +// 3. setTheme() defaults to shadcn's `.dark` class on ; change it only if the repo toggles +// dark mode differently (a data attribute, a cookie, etc.). +import { test, type Page } from "@playwright/test"; + +const ROUTES = ["/", "/brand"]; +const THEMES = ["light", "dark"] as const; + +async function setTheme(page: Page, theme: (typeof THEMES)[number]) { + await page.emulateMedia({ colorScheme: theme }); // for prefers-color-scheme apps + await page.evaluate((t) => { + document.documentElement.classList.toggle("dark", t === "dark"); // for class-based (shadcn) apps + }, theme); +} + +const slugify = (route: string) => + route.replace(/[^\w]+/g, "_").replace(/^_|_$/g, "") || "home"; + +for (const route of ROUTES) { + for (const theme of THEMES) { + test(`${route} [${theme}]`, async ({ page }, testInfo) => { + await page.goto(route, { waitUntil: "networkidle" }); + await setTheme(page, theme); + await page.evaluate(async () => { + await document.fonts.ready; // avoid a flash of unstyled text in the capture + }); + await page.screenshot({ + path: `screenshots/${testInfo.project.name}/${slugify(route)}-${theme}.png`, + fullPage: true, + }); + }); + } +} + +// Optional: per-specimen shots on /brand for component-level visual regression, using the +// data-brand-specimen hooks from brand-page.md. Uncomment and adapt. +// +// test("brand specimens", async ({ page }, testInfo) => { +// await page.goto("/brand", { waitUntil: "networkidle" }); +// for (const el of await page.locator("[data-brand-specimen]").all()) { +// const name = await el.getAttribute("data-brand-specimen"); +// await el.screenshot({ path: `screenshots/${testInfo.project.name}/specimen-${name}.png` }); +// } +// }); diff --git a/ai/skills/design/design-handoff/references/responsive-and-cross-browser.md b/ai/skills/design/design-handoff/references/responsive-and-cross-browser.md index 38f06fe..7881c3d 100644 --- a/ai/skills/design/design-handoff/references/responsive-and-cross-browser.md +++ b/ai/skills/design/design-handoff/references/responsive-and-cross-browser.md @@ -55,9 +55,15 @@ Then write `playwright.config.ts` with the projects below and add the `verify:br `assets/Taskfile.design.yml`, so the cross-engine sweep runs like every other gate. ```ts -// playwright.config.ts — the cross-engine × device matrix +// playwright.config.ts — baseURL + dev server, then the cross-engine × device matrix import { defineConfig, devices } from "@playwright/test"; export default defineConfig({ + use: { baseURL: "http://localhost:5173" }, // your dev server (Vite 5173, Astro 4321, …) + webServer: { + command: "pnpm dev", + url: "http://localhost:5173", + reuseExistingServer: true, + }, projects: [ { name: "chromium", use: { ...devices["Desktop Chrome"] } }, { name: "firefox", use: { ...devices["Desktop Firefox"] } }, @@ -74,8 +80,18 @@ For a quick ad-hoc capture without a test file, the Playwright CLI takes one scr npx playwright screenshot --device="iPhone 14" http://localhost:5173/brand brand-iphone.png ``` -For the full Phase 5 sweep, drive a short script over `[chromium, firefox, webkit]` × `[viewports]` × -`[light, dark]`, saving a PNG per cell. +For the full Phase 5 sweep, use the bundled **`assets/brand-screenshots.spec.ts`** template, run by +`task verify:browsers`. It is a parameterized harness, not a from-scratch write: the engine × device +axis comes from the `projects` above, and the spec adds the route × theme axis, writing one full-page +PNG per route × theme per project. Fill in three spots and it works: + +- **`ROUTES`** — always include `/brand`, plus the feature's pages. +- **`baseURL` and `webServer`** (in the config above) — point them at the dev server. +- **`setTheme()`** — defaults to shadcn's `.dark` class on ``; change it only if the repo toggles + dark mode differently (data attribute, cookie). + +To capture per-specimen shots on `/brand`, extend the spec to locate the `data-brand-specimen` hooks +(`brand-page.md`); the template includes a commented starting point. **WebKit ≈ Safari, not identical.** Playwright's WebKit is the open-source engine — very close to Safari and the best automated proxy for Safari and iOS Safari, but it lacks Apple-proprietary bits and From 2640fc6eaf3edfcb569db75f95dd69394849246e Mon Sep 17 00:00:00 2001 From: Evan Harmon Date: Wed, 17 Jun 2026 17:31:00 -0500 Subject: [PATCH 11/16] feat(skills): add three explicit modes + drift governance to design-handoff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the skill handle three use cases as first-class modes, and make ingestion format-agnostic — without redesigning what's already there. - Three modes (establish / evolve / implement-feature), detected in Phase 0 (ask if ambiguous) and routed in Phase 2. The intro, Definition of Done, Phase 1/2, and Guardrails now reflect them. - Drift governance / anti-clobber doctrine: the bundle is a PROPOSAL, the repo is truth. Never overwrite globals.css wholesale; diff against canonical; new tokens are a decision point (force-fit vs. deliberate additive extension); record system changes as a DDR with a SemVer bump. This protects an established system when a feature handoff re-emits drifted tokens. - New reference evolving-the-system.md: token diff (added/changed/removed), SemVer classification, aliasing + deprecation for breaking changes, the DDR record, and /brand as the regression surface. - token-reconciliation.md gains a consume-first section (diff/map/decision-point + OKLCH closeness tolerance); ingesting-the-bundle.md gains a defensive, format-agnostic section (proprietary unstable format; parse for intent; also fits other tools like Google Stitch). Keep DDR (repo convention), not the research's PDR term. Co-Authored-By: Claude Opus 4.8 (1M context) --- ai/skills/design/design-handoff/SKILL.md | 149 +++++++++++------- .../references/evolving-the-system.md | 65 ++++++++ .../references/ingesting-the-bundle.md | 13 +- .../references/token-reconciliation.md | 48 +++++- 4 files changed, 213 insertions(+), 62 deletions(-) create mode 100644 ai/skills/design/design-handoff/references/evolving-the-system.md diff --git a/ai/skills/design/design-handoff/SKILL.md b/ai/skills/design/design-handoff/SKILL.md index 718a582..0a26ed4 100644 --- a/ai/skills/design/design-handoff/SKILL.md +++ b/ai/skills/design/design-handoff/SKILL.md @@ -14,17 +14,29 @@ description: >- # Design Handoff (Claude Design → repo) -Turn a finished Claude Design into working, on-brand code in this repo. The "Handoff to Claude Code" -export is a **`.tar.gz` bundle** — a README, the design **chat transcript**, prototype HTML/JSX/CSS, a -`tokens.css`, and your uploads. That code is **prototype-grade** (it runs on in-browser Babel + UMD -React); your job is to **port** it into this repo's stack, not paste it in. There are two paths: -**reconcile** into an existing design system, or **bootstrap** a new one when the repo has none. - -The core principle running through every step: **`src/styles/globals.css` is the canonical runtime -token source, and `DESIGN.md` is the AI-facing statement of intent.** When they disagree, `globals.css` -wins for runtime. The handoff bundle is the reference for the _intended_ design — it stays in place -until **the user has reviewed the implementation and approved it**, and only then is it removed before -merge. Never assume your implementation is correct; the user decides whether it matches the intent. +Turn a finished design from **Claude Design** (or a similar tool) into working, on-brand code in this +repo. The export is a **handoff bundle** — commonly a `.tar.gz` from "Handoff to Claude Code" holding a +README, the design **chat transcript**, prototype HTML/JSX/CSS, a token file, and uploads. But that +format is an unstable research preview, not a standard, so **parse defensively**: read what's actually +present rather than assuming exact filenames or folders. That same defensiveness lets the skill absorb +Claude Design's format changes and adapt to other tools (e.g. Google Stitch). The prototype code is +**prototype-grade** (it often runs on in-browser Babel + UMD React); your job is to **port** it into +this repo's stack, not paste it in. + +**Three modes — detect which one you're in (Phase 0) and route accordingly:** + +- **`establish`** — the repo has no design system yet; bootstrap one from the bundle. +- **`evolve`** — the repo has a design system and the bundle deliberately changes it (new/changed/removed + tokens or brand); reconcile and **version** the change. +- **`implement-feature`** — the repo has a design system and the bundle is a bounded feature; build it + **consume-first**, honoring the design without clobbering the established system. + +The core principle running through all three: **`src/styles/globals.css` is the canonical runtime token +source and `DESIGN.md` is the AI-facing statement of intent — the repo is the source of truth, and the +bundle is a _proposal_.** When they disagree, `globals.css` wins; **never overwrite it wholesale from a +bundle** — diff and apply deliberate changes only. The bundle stays in place until **the user has +reviewed the implementation and approved it**, and only then is it removed before merge. Never assume +your implementation is correct; the user decides whether it matches the intent. ## Definition of done @@ -40,14 +52,17 @@ have shown why in the chat. Reconciliation -- [ ] Bundle ingested from the `.tar.gz`: README → chat transcript → HTML → `tokens.css`/`site.css` → - `js/*.jsx` (read for intent and **ported**, never pasted into `src/`) -- [ ] Framework + router detected; greenfield-vs-brownfield decided; up-front questions asked -- [ ] Tokens merged into `globals.css` by **role** (not export name) — Tailwind v4, OKLCH, three-layer; - export never blind-pasted -- [ ] `.dark` authored by hand (brand hue held, neutrals inverted); `--tw-prose-*` mapped if prose is - used -- [ ] `DESIGN.md` reconciled, not clobbered +- [ ] Bundle ingested **defensively** (parse what's there; don't assume exact filenames): intent/README + → chat transcript → markup → token file → assets, read for intent and **ported**, never pasted + into `src/` +- [ ] **Mode detected** — `establish` / `evolve` / `implement-feature` (asked if ambiguous); framework + + router detected; up-front questions asked +- [ ] Bundle tokens treated as a **proposal** — diffed against canonical `globals.css`, never + overwritten wholesale; new tokens resolved (force-fit to existing, or deliberate extension) +- [ ] Tokens in `globals.css` are by **role** (not export name) — Tailwind v4, OKLCH, three-layer; + `.dark` authored (brand hue held, neutrals inverted); `--tw-prose-*` mapped if prose is used +- [ ] `DESIGN.md` reconciled (not clobbered); a system change (`establish`/`evolve`, or a feature + extension) carries a **DDR + SemVer bump** Implementation @@ -76,7 +91,7 @@ Gates — post **PASS + evidence** in the chat before taking the guarded action Close-out (only once gate ④ is green) - [ ] Handoff bundle deleted (or a thin screenshot + intent note extracted first if states remain) -- [ ] `docs/design/` and `/brand` updated; DDR flagged if a real design-system decision was made +- [ ] `docs/design/` and `/brand` updated; a system change recorded as a **DDR with a SemVer bump** - [ ] Conventional Commit on a **feature branch**; PR opened for human review; hooks never bypassed (`--no-verify` prohibited); no direct merge to `main` @@ -102,20 +117,25 @@ the referenced files — read the reference when you reach its phase. All the up-front orientation happens here, before any building: -1. **Ingest.** Decompress the `.tar.gz` and read in the order its README dictates: `README.md` ("CODING - AGENTS: READ THIS FIRST") → `chats/chat1.md` (design intent — the bundle's real value) → the entry - HTML → `tokens.css`/`site.css` → the `js/*.jsx` components → `uploads/` (your inputs, **not** - screenshots). The code is prototype-grade; read it for structure and intent, then **port** it — - don't paste `.jsx`/`.html` into `src/`. Don't expect a `tokens.json`, a machine-readable spec, or - per-state screenshots — none ship. Locate the bundle at `docs/design/handoff-*/`; if you can't find - it, ask where the export landed before proceeding. (`ingesting-the-bundle.md`) -2. **Detect framework, router & design-system state** — they drive every later file-placement decision. - Router/framework: TanStack → `src/routes/brand.tsx` and `src/components/ui`; React Router/plain → a - normal `/brand` route; Astro → `src/pages/brand.astro` with React **islands** for interactive - specimens; any other framework maps the same three roles (global stylesheet import, component dir, - route entry) — never block on an unrecognized router. Greenfield vs brownfield: a design system is - present when `globals.css` has real `:root` semantic tokens **and** a `/brand` route exists → - reconcile into it (skip to Phase 2); otherwise → bootstrap first (Phase 1). +1. **Ingest (defensively).** Unpack the bundle and read it for intent — don't hard-code its layout; the + format is an unstable preview and varies by tool. The common Claude Design shape is a `.tar.gz` with + a README ("CODING AGENTS: READ THIS FIRST") → `chats/*.md` (the design conversation — the real + intent) → the entry HTML → a token file (`tokens.css`/`site.css`) → components → `uploads/`. Read + whatever is actually present in that spirit (intent/README → transcript → markup → tokens → assets), + and adapt if a piece is named or shaped differently. The prototype code is prototype-grade — read it + for structure and intent, then **port** it; don't paste markup into `src/`. Locate the bundle (often + `docs/design/handoff-*/`); if you can't find it, ask where the export landed. (`ingesting-the-bundle.md`) +2. **Detect mode, framework & router.** **Mode** — `establish` (no design system: no real `:root` tokens + in `globals.css` and no `/brand` route), `evolve` (a system exists and the bundle is + token/brand-dominant, or intent says "update the design system"), or `implement-feature` (a system + exists and the bundle is a page/feature, its tokens mostly a re-emission of the existing set). Judge + from the bundle's content (tokens vs. screens), the chat intent, and the repo state; **if it's + ambiguous, ask** (fold the question into the batch below) rather than guess — a wrong guess risks + clobbering the system. **Framework + router** drive file placement: TanStack → `src/routes/brand.tsx` + and `src/components/ui`; React Router/plain → a normal `/brand` route; Astro → `src/pages/brand.astro` + with React **islands** for interactive specimens; any other framework maps the same three roles + (global stylesheet import, component dir, route entry) — never block on an unrecognized router. + `establish` runs Phase 1 next; `evolve`/`implement-feature` skip to Phase 2. 3. **Decide up front — one `AskUserQuestion` batch.** Now that you've read the intent and know the stack, ask **everything you'll need at once** (up to 4 questions) so Phases 1–5 run uninterrupted: the **`/brand` scope** (core guide → brand/press kit → collateral groups; `brand-page.md`), plus any @@ -123,22 +143,33 @@ All the up-front orientation happens here, before any building: dark mode if unclear). Only ask what you can't determine yourself. The **one** thing that can't be front-loaded is the Phase 6 **sign-off** — it approves the built result. -### Phase 1 — Greenfield bootstrap (only if no design system exists) +### Phase 1 — `establish`: greenfield bootstrap (only if no design system exists) -If detection found no design system, stand one up before reconciling: install and configure Tailwind -v4 and shadcn for the detected framework, let `shadcn init` write the default three-layer -`globals.css`, scaffold the `/brand` route, `DESIGN.md`, and `docs/design/`, copy -`scripts/check-contrast.mjs`, and add the design Taskfile tasks. Assumes a working frontend app already -exists. See `greenfield-bootstrap.md`. (Brownfield repos skip to Phase 2.) +If detection found no design system, stand one up before reconciling: install and configure Tailwind v4 +and shadcn for the detected framework, let `shadcn init` write the default three-layer `globals.css`, +scaffold the `/brand` route, `DESIGN.md`, and `docs/design/`, copy `scripts/check-contrast.mjs`, and add +the design Taskfile tasks. **Normalize whatever the bundle emits** (often HSL or inline values) into the +canonical OKLCH three-layer form, and record a **DDR establishing the system at v1.0.0**. Assumes a +working frontend app already exists. See `greenfield-bootstrap.md`. (An existing system skips to Phase +2.) ### Phase 2 — Reconcile tokens — GATE: static contrast -The most error-prone step; it has its own reference — **read `token-reconciliation.md` and follow -it.** Map the bundle's `tokens.css` into `globals.css`'s semantic slots **by role** (not by name), -express values in OKLCH, fill the roles shadcn needs but the export lacks, author the `.dark` block by -hand (hold brand hue, invert neutrals), and map `--tw-prose-*` if the app renders prose. Reconcile -`DESIGN.md`, don't clobber it. Then run `task lint:design` (`scripts/check-contrast.mjs`) and fix every -sub-AA pair — this static gate must be **green** before you implement. Numbers in +The most error-prone step, and where the modes diverge — **the bundle's tokens are a proposal, +`globals.css` is truth.** Read `token-reconciliation.md` (and `evolving-the-system.md` for `evolve`): + +- **`establish`** — write canonical tokens from the bundle: map by **role** into the shadcn three-layer + OKLCH `globals.css`, author `.dark` by hand (hold brand hue, invert neutrals), map `--tw-prose-*` if + prose is used. +- **`implement-feature` (consume-first)** — **diff** against canonical and map each value to the + **existing** token (inline hex/oklch → `bg-primary`, `text-muted-foreground`, …); add **nothing** by + default. A value with no close match is a **decision point**: force-fit to the nearest token, or + extend the system additively with a DDR — never inline. +- **`evolve`** — a three-bucket diff (added/changed/removed), classified with **SemVer**, breaking + changes handled by **aliasing + deprecating** (not deleting), recorded as a **DDR + version bump**. + +Reconcile `DESIGN.md` (don't clobber it). Then run `task lint:design` (`scripts/check-contrast.mjs`) and +fix every sub-AA pair — this static gate must be **green** before you implement. Numbers in `accessibility-verification.md`. ### Phase 3 — Implement components, assets & `/brand` @@ -184,8 +215,9 @@ the user explicitly approves.** The bundle stays fully in place through this ste ### Phase 7 — Close out (only after approval) Delete `docs/design/handoff-/` (or extract a thin screenshot + intent note first if states -remain), update `docs/design/` and `/brand`, and flag a **DDR** in `/decisions/` if a genuine -design-system decision was made. Commit with Conventional Commits on a **feature branch** (direct +remain), update `docs/design/` and `/brand`, and record a **DDR (with a SemVer bump)** in `/decisions/` +for any design-system change — `establish` (v1.0.0), `evolve` (patch/minor/major), or a feature token +extension. Commit with Conventional Commits on a **feature branch** (direct commits to `main` are blocked) and open a **PR** for human review — never merge to `main` directly. See `verification-and-signoff.md`. @@ -197,6 +229,12 @@ commits to `main` are blocked) and open a **PR** for human review — never merg - **Semantic tokens only.** Never arbitrary hex or one-off Tailwind color literals — they skip dark mode and the contrast gate. - **`globals.css` wins over `DESIGN.md`** for runtime. If they drift, flag it. +- **The bundle is a proposal; the repo is truth.** Never overwrite `globals.css` wholesale from a + bundle — diff against canonical and apply deliberate, approved changes only. +- **New tokens are a decision point.** Map to an existing token, or extend the system deliberately + (additive, with a DDR) — never invent ad-hoc values inline. +- **Record system changes as a DDR with a SemVer bump** (`establish` = v1.0.0; `evolve` = + patch/minor/major; a feature extension = minor). - **`/brand` is a maintained route, not a doc.** Keep it synced with the tokens; never let it drift. - **Get sign-off before deleting anything.** Approval is the user's decision, never inferred from a green build or your own confidence. @@ -205,12 +243,15 @@ commits to `main` are blocked) and open a **PR** for human review — never merg ## Reference files -- **`ingesting-the-bundle.md`** — Phase 0: the verified bundle anatomy and the prototype→production - port. -- **`token-reconciliation.md`** — Phase 2: `tokens.css` → shadcn three-layer OKLCH `globals.css`, by - role, including `.dark` and the `--tw-prose-*` mapping. -- **`greenfield-bootstrap.md`** — Phase 1: stand up Tailwind v4 + shadcn + `globals.css` + `/brand` + - Taskfile, per framework. +- **`ingesting-the-bundle.md`** — Phase 0: defensive, format-agnostic ingest; the common Claude Design + anatomy; and the prototype→production port. +- **`token-reconciliation.md`** — Phase 2: the proposal-vs-canonical doctrine — `establish` writes + canonical tokens by role; `implement-feature` diffs and maps to existing (the new-token decision + point). shadcn three-layer OKLCH, `.dark`, and the `--tw-prose-*` mapping. +- **`evolving-the-system.md`** — Phase 2 (`evolve`): the token diff (added/changed/removed), SemVer + classification, aliasing + deprecation, and the DDR/version record. +- **`greenfield-bootstrap.md`** — Phase 1 (`establish`): stand up Tailwind v4 + shadcn + `globals.css` + + `/brand` + Taskfile, per framework. - **`components-and-states.md`** — Phase 3: port the JSX, shadcn-first, Lucide, the full UI-state matrix. - **`assets-fonts-favicons.md`** — Phase 3: asset placement, self-hosted fonts (+ the `@import` order diff --git a/ai/skills/design/design-handoff/references/evolving-the-system.md b/ai/skills/design/design-handoff/references/evolving-the-system.md new file mode 100644 index 0000000..7c0e61c --- /dev/null +++ b/ai/skills/design/design-handoff/references/evolving-the-system.md @@ -0,0 +1,65 @@ +# Evolving an established design system + +Read this during **Phase 2** in **`evolve`** mode — when the bundle deliberately changes the design +system itself (not a single feature). The doctrine is the same as everywhere: the repo is truth, the +bundle is a proposal. Evolve means reconciling a proposed token change into canonical `globals.css` +**carefully and versioned** — never a blind overwrite, because much of a bundle's token block is a +re-emission that may have drifted from canonical. + +## 1. Diff before you write + +Parse the **current** semantic tokens from `globals.css` and the **incoming** set from the bundle, and +produce a three-bucket diff: + +- **Added** — semantic tokens in the bundle that don't exist in canonical. +- **Changed** — same token name, different value. Use an OKLCH **closeness tolerance** so a rounding + difference isn't flagged as a real change (see `token-reconciliation.md`). +- **Removed / renamed** — present in canonical, absent from the bundle. + +Show this diff to the user and apply only the deltas they approve. The re-emitted bundle is not +authority; the diff is the unit of change. + +## 2. Classify the change with SemVer + +Version the token set (the industry norm — IBM Carbon, Salesforce, and the W3C Design Tokens spec all +version tokens). Record the version in `DESIGN.md` (or a `tokens` header): + +- **patch** — value tweaks that don't change a token's role (e.g. nudging `--primary` lightness). +- **minor** — additive, backward-compatible new tokens (a new `--warning`, a new surface). +- **major** — renamed/removed tokens or role changes (breaking). + +Batch breaking changes into a single major release rather than scattering them across handoffs. + +## 3. Handle breaking changes with aliasing + deprecation (not deletion) + +Treat tokens like API endpoints — version, alias, and deprecate slowly: + +- When a token is renamed or removed, **alias** the old name to the new value for a migration window + (keep the old `--token` pointing at the new var). +- **Search the codebase** for every reference to the old token and migrate them. +- **Delete only after** all references are migrated. Don't yank a token out from under the components + that use it — that's the costly path everyone warns about. + +## 4. Record a DDR with the version bump + +Every system change is a **DDR** in `/decisions/` — your design-system changelog and governance trail. +A token-change DDR carries: a unique ID (e.g. `DDR-0xx`), status, context (why the change), the decision +(the exact token delta), alternatives considered, consequences (which components are affected, what +migration is needed), and the resulting **SemVer bump**. DDRs are append-only (the ADR tradition) — if a +later change reverses one, write a new superseding DDR rather than editing the old one. This gives Claude +Code a durable, queryable rationale trail for why the system is the way it is. + +## 5. `/brand` is the regression check + +After any system change, the `/brand` route renders every token and core component, so drift or breakage +is visually obvious — treat it as a visual test surface. Re-run the screenshot sweep +(`responsive-and-cross-browser.md`) and the contrast gate (`accessibility-verification.md`): a token +change can quietly break a contrast pair or a component that depended on the old value. + +## Why this care + +A system's tokens are referenced across the whole app, so changing them ripples. Renaming a token after +hundreds of components reference it means touching every reference — which is why `establish` builds +semantic naming in from the start and `evolve` aliases rather than renames in place. This discipline is +what lets the system change without breaking everything downstream — the difference between a design +system and a pile of values. diff --git a/ai/skills/design/design-handoff/references/ingesting-the-bundle.md b/ai/skills/design/design-handoff/references/ingesting-the-bundle.md index 9b47684..0de487c 100644 --- a/ai/skills/design/design-handoff/references/ingesting-the-bundle.md +++ b/ai/skills/design/design-handoff/references/ingesting-the-bundle.md @@ -4,6 +4,17 @@ Read this during **Phase 0**. It covers what the "Handoff to Claude Code" export open it, what to read and in what order, and the single most important mental shift: **the bundle is a prototype, not production code — you _port_ it, you don't copy it.** +## Be defensive about the format + +Claude Design is a fast-moving research preview, and its handoff is a **proprietary, non-standard** +format (not DTCG/W3C tokens, not Figma) that can change without notice. So **don't hard-code the +layout** — parse for _intent_, not for exact filenames or folders. The anatomy below is the common +shape as of now, not a contract: read what's actually present, and if a piece is named or structured +differently, adapt. The same posture lets this skill handle other design tools (e.g. Google Stitch), +whose bundles differ but carry the same ingredients — intent, tokens, markup, assets. Whatever the +format, the destination is identical: the repo's canonical `globals.css` / `DESIGN.md` / `/brand`, with +the bundle treated as a proposal. + ## What the export actually is "Handoff to Claude Code" produces a **gzipped tarball** (`.tar.gz`, served as `application/gzip`) — @@ -18,7 +29,7 @@ It extracts to a single project directory. Move/rename it to `docs/design/handof ## Anatomy (verified, current as of mid-2026) -``` +```text / README.md # headed "CODING AGENTS: READ THIS FIRST" chats/chat1.md # the full Claude Design conversation — design intent & rationale diff --git a/ai/skills/design/design-handoff/references/token-reconciliation.md b/ai/skills/design/design-handoff/references/token-reconciliation.md index f6e4ae4..ed359dd 100644 --- a/ai/skills/design/design-handoff/references/token-reconciliation.md +++ b/ai/skills/design/design-handoff/references/token-reconciliation.md @@ -1,12 +1,46 @@ # Token reconciliation: Claude Design `tokens.css` → shadcn `globals.css` -Read this during **Phase 2** of the `design-handoff` skill. The handoff bundle ships -`project/styles/tokens.css` (the design system's primitives — palette, fonts, spacing, radii, -type scale) plus `project/styles/site.css` (brand overrides, sometimes including a few dark-mode -hints). Your job: merge those into the repo's canonical `src/styles/globals.css` in shadcn's -three-layer **OKLCH** form — by **role**, not by name. It is **not** a drop-in; pasting `tokens.css` -into `globals.css` breaks the system. This is the most error-prone step in the whole handoff, which -is why it has its own reference. +Read this during **Phase 2**. The bundle ships a token file (commonly `tokens.css`, plus a `site.css` +of brand/dark-mode overrides) carrying the design's primitives — palette, fonts, spacing, radii, type +scale. What you do with it depends on the **mode**, but one rule is constant: **the bundle's tokens are +a proposal; `globals.css` is truth.** + +- **`establish`** (no system yet) — _write canonical_ tokens from the bundle. That's the bulk of this + doc: the conflicts, the skeleton, the by-role merge recipe, and authoring `.dark`. +- **`implement-feature`** (a feature against an existing system) — _consume-first_: diff and map to the + existing tokens, adding nothing by default. **Start at "Consume-first" below.** +- **`evolve`** (changing the system) — diff and version the change; see `evolving-the-system.md`. + +Either way it is **not** a drop-in — pasting a token file into `globals.css` breaks the system. + +## Consume-first (`implement-feature`): diff, don't redefine + +When the repo already has a design system, the feature bundle's tokens are a re-emission that may have +drifted — so you **consume** them, you don't rewrite: + +1. **Map every value to an existing semantic token.** For each color/spacing/radius/type value in the + bundle, resolve it to the matching token and use the utility (`bg-primary`, `text-muted-foreground`, + `rounded-lg`, …). Replace any inline `oklch(...)`/hex in the markup with the token. Add **nothing** + to `globals.css` by default. +2. **Match by OKLCH closeness, with a tolerance.** Treat a bundle color as "the same as" a canonical + token when it's within a small ΔL/ΔC/Δh bound (pick a default; let the user tune it), and **report + drift** rather than silently adopting the bundle's value — e.g. "bundle `--primary` is + `oklch(0.62 0.19 255)`, canonical is `oklch(0.60 0.16 250)` — keeping canonical." +3. **A value with no close match is a DECISION POINT — stop and surface it.** Two legitimate + resolutions: + - **Force-fit** (preferred for one-offs): snap to the nearest existing token. Use when the + difference is incidental or the value appears once. + - **Deliberately extend** (when the need is real and reusable): add the token _additively_ (the + shadcn pattern — define `--warning`/`--warning-foreground` in `:root` and `.dark`, expose via + `@theme inline`), update `/brand` and `DESIGN.md`, and record a DDR. That's an `evolve`-style + change folded into the feature, so it carries a SemVer bump (`evolving-the-system.md`). + - **Heuristic:** extend only if the value (a) is a _semantic role_, not just a shade, (b) will + plausibly recur, and (c) you'd document it in `/brand`. Otherwise force-fit. +4. **Never overwrite `globals.css` wholesale** from a feature bundle — it may re-emit the whole token + block; you apply only deliberate, approved additions. + +The rest of this doc (the conflicts, skeleton, and merge recipe) is the `establish` path — you'll also +dip into it when a feature legitimately extends the system. ## Why you can't paste it in From be47b6629c0a442115573293b57139891ea23ad9 Mon Sep 17 00:00:00 2001 From: Evan Harmon Date: Wed, 17 Jun 2026 17:44:29 -0500 Subject: [PATCH 12/16] docs(skills): rename modes to establish-design-system / evolve-design-system Make the system-vs-feature distinction explicit in the mode names: establish -> establish-design-system, evolve -> evolve-design-system. implement-feature is already clear and unchanged. Prose verbs/titles and the evolving-the-system.md filename are untouched. Co-Authored-By: Claude Opus 4.8 (1M context) --- ai/skills/design/design-handoff/SKILL.md | 32 +++++++++---------- .../references/evolving-the-system.md | 6 ++-- .../references/token-reconciliation.md | 8 ++--- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/ai/skills/design/design-handoff/SKILL.md b/ai/skills/design/design-handoff/SKILL.md index 0a26ed4..cbcab60 100644 --- a/ai/skills/design/design-handoff/SKILL.md +++ b/ai/skills/design/design-handoff/SKILL.md @@ -25,8 +25,8 @@ this repo's stack, not paste it in. **Three modes — detect which one you're in (Phase 0) and route accordingly:** -- **`establish`** — the repo has no design system yet; bootstrap one from the bundle. -- **`evolve`** — the repo has a design system and the bundle deliberately changes it (new/changed/removed +- **`establish-design-system`** — the repo has no design system yet; bootstrap one from the bundle. +- **`evolve-design-system`** — the repo has a design system and the bundle deliberately changes it (new/changed/removed tokens or brand); reconcile and **version** the change. - **`implement-feature`** — the repo has a design system and the bundle is a bounded feature; build it **consume-first**, honoring the design without clobbering the established system. @@ -55,13 +55,13 @@ Reconciliation - [ ] Bundle ingested **defensively** (parse what's there; don't assume exact filenames): intent/README → chat transcript → markup → token file → assets, read for intent and **ported**, never pasted into `src/` -- [ ] **Mode detected** — `establish` / `evolve` / `implement-feature` (asked if ambiguous); framework + +- [ ] **Mode detected** — `establish-design-system` / `evolve-design-system` / `implement-feature` (asked if ambiguous); framework + router detected; up-front questions asked - [ ] Bundle tokens treated as a **proposal** — diffed against canonical `globals.css`, never overwritten wholesale; new tokens resolved (force-fit to existing, or deliberate extension) - [ ] Tokens in `globals.css` are by **role** (not export name) — Tailwind v4, OKLCH, three-layer; `.dark` authored (brand hue held, neutrals inverted); `--tw-prose-*` mapped if prose is used -- [ ] `DESIGN.md` reconciled (not clobbered); a system change (`establish`/`evolve`, or a feature +- [ ] `DESIGN.md` reconciled (not clobbered); a system change (`establish-design-system`/`evolve-design-system`, or a feature extension) carries a **DDR + SemVer bump** Implementation @@ -125,8 +125,8 @@ All the up-front orientation happens here, before any building: and adapt if a piece is named or shaped differently. The prototype code is prototype-grade — read it for structure and intent, then **port** it; don't paste markup into `src/`. Locate the bundle (often `docs/design/handoff-*/`); if you can't find it, ask where the export landed. (`ingesting-the-bundle.md`) -2. **Detect mode, framework & router.** **Mode** — `establish` (no design system: no real `:root` tokens - in `globals.css` and no `/brand` route), `evolve` (a system exists and the bundle is +2. **Detect mode, framework & router.** **Mode** — `establish-design-system` (no design system: no real `:root` tokens + in `globals.css` and no `/brand` route), `evolve-design-system` (a system exists and the bundle is token/brand-dominant, or intent says "update the design system"), or `implement-feature` (a system exists and the bundle is a page/feature, its tokens mostly a re-emission of the existing set). Judge from the bundle's content (tokens vs. screens), the chat intent, and the repo state; **if it's @@ -135,7 +135,7 @@ All the up-front orientation happens here, before any building: and `src/components/ui`; React Router/plain → a normal `/brand` route; Astro → `src/pages/brand.astro` with React **islands** for interactive specimens; any other framework maps the same three roles (global stylesheet import, component dir, route entry) — never block on an unrecognized router. - `establish` runs Phase 1 next; `evolve`/`implement-feature` skip to Phase 2. + `establish-design-system` runs Phase 1 next; `evolve-design-system`/`implement-feature` skip to Phase 2. 3. **Decide up front — one `AskUserQuestion` batch.** Now that you've read the intent and know the stack, ask **everything you'll need at once** (up to 4 questions) so Phases 1–5 run uninterrupted: the **`/brand` scope** (core guide → brand/press kit → collateral groups; `brand-page.md`), plus any @@ -143,7 +143,7 @@ All the up-front orientation happens here, before any building: dark mode if unclear). Only ask what you can't determine yourself. The **one** thing that can't be front-loaded is the Phase 6 **sign-off** — it approves the built result. -### Phase 1 — `establish`: greenfield bootstrap (only if no design system exists) +### Phase 1 — `establish-design-system`: greenfield bootstrap (only if no design system exists) If detection found no design system, stand one up before reconciling: install and configure Tailwind v4 and shadcn for the detected framework, let `shadcn init` write the default three-layer `globals.css`, @@ -156,16 +156,16 @@ working frontend app already exists. See `greenfield-bootstrap.md`. (An existing ### Phase 2 — Reconcile tokens — GATE: static contrast The most error-prone step, and where the modes diverge — **the bundle's tokens are a proposal, -`globals.css` is truth.** Read `token-reconciliation.md` (and `evolving-the-system.md` for `evolve`): +`globals.css` is truth.** Read `token-reconciliation.md` (and `evolving-the-system.md` for `evolve-design-system`): -- **`establish`** — write canonical tokens from the bundle: map by **role** into the shadcn three-layer +- **`establish-design-system`** — write canonical tokens from the bundle: map by **role** into the shadcn three-layer OKLCH `globals.css`, author `.dark` by hand (hold brand hue, invert neutrals), map `--tw-prose-*` if prose is used. - **`implement-feature` (consume-first)** — **diff** against canonical and map each value to the **existing** token (inline hex/oklch → `bg-primary`, `text-muted-foreground`, …); add **nothing** by default. A value with no close match is a **decision point**: force-fit to the nearest token, or extend the system additively with a DDR — never inline. -- **`evolve`** — a three-bucket diff (added/changed/removed), classified with **SemVer**, breaking +- **`evolve-design-system`** — a three-bucket diff (added/changed/removed), classified with **SemVer**, breaking changes handled by **aliasing + deprecating** (not deleting), recorded as a **DDR + version bump**. Reconcile `DESIGN.md` (don't clobber it). Then run `task lint:design` (`scripts/check-contrast.mjs`) and @@ -216,7 +216,7 @@ the user explicitly approves.** The bundle stays fully in place through this ste Delete `docs/design/handoff-/` (or extract a thin screenshot + intent note first if states remain), update `docs/design/` and `/brand`, and record a **DDR (with a SemVer bump)** in `/decisions/` -for any design-system change — `establish` (v1.0.0), `evolve` (patch/minor/major), or a feature token +for any design-system change — `establish-design-system` (v1.0.0), `evolve-design-system` (patch/minor/major), or a feature token extension. Commit with Conventional Commits on a **feature branch** (direct commits to `main` are blocked) and open a **PR** for human review — never merge to `main` directly. See `verification-and-signoff.md`. @@ -233,7 +233,7 @@ commits to `main` are blocked) and open a **PR** for human review — never merg bundle — diff against canonical and apply deliberate, approved changes only. - **New tokens are a decision point.** Map to an existing token, or extend the system deliberately (additive, with a DDR) — never invent ad-hoc values inline. -- **Record system changes as a DDR with a SemVer bump** (`establish` = v1.0.0; `evolve` = +- **Record system changes as a DDR with a SemVer bump** (`establish-design-system` = v1.0.0; `evolve-design-system` = patch/minor/major; a feature extension = minor). - **`/brand` is a maintained route, not a doc.** Keep it synced with the tokens; never let it drift. - **Get sign-off before deleting anything.** Approval is the user's decision, never inferred from a @@ -245,12 +245,12 @@ commits to `main` are blocked) and open a **PR** for human review — never merg - **`ingesting-the-bundle.md`** — Phase 0: defensive, format-agnostic ingest; the common Claude Design anatomy; and the prototype→production port. -- **`token-reconciliation.md`** — Phase 2: the proposal-vs-canonical doctrine — `establish` writes +- **`token-reconciliation.md`** — Phase 2: the proposal-vs-canonical doctrine — `establish-design-system` writes canonical tokens by role; `implement-feature` diffs and maps to existing (the new-token decision point). shadcn three-layer OKLCH, `.dark`, and the `--tw-prose-*` mapping. -- **`evolving-the-system.md`** — Phase 2 (`evolve`): the token diff (added/changed/removed), SemVer +- **`evolving-the-system.md`** — Phase 2 (`evolve-design-system`): the token diff (added/changed/removed), SemVer classification, aliasing + deprecation, and the DDR/version record. -- **`greenfield-bootstrap.md`** — Phase 1 (`establish`): stand up Tailwind v4 + shadcn + `globals.css` + +- **`greenfield-bootstrap.md`** — Phase 1 (`establish-design-system`): stand up Tailwind v4 + shadcn + `globals.css` + `/brand` + Taskfile, per framework. - **`components-and-states.md`** — Phase 3: port the JSX, shadcn-first, Lucide, the full UI-state matrix. diff --git a/ai/skills/design/design-handoff/references/evolving-the-system.md b/ai/skills/design/design-handoff/references/evolving-the-system.md index 7c0e61c..cc57da8 100644 --- a/ai/skills/design/design-handoff/references/evolving-the-system.md +++ b/ai/skills/design/design-handoff/references/evolving-the-system.md @@ -1,6 +1,6 @@ # Evolving an established design system -Read this during **Phase 2** in **`evolve`** mode — when the bundle deliberately changes the design +Read this during **Phase 2** in **`evolve-design-system`** mode — when the bundle deliberately changes the design system itself (not a single feature). The doctrine is the same as everywhere: the repo is truth, the bundle is a proposal. Evolve means reconciling a proposed token change into canonical `globals.css` **carefully and versioned** — never a blind overwrite, because much of a bundle's token block is a @@ -59,7 +59,7 @@ change can quietly break a contrast pair or a component that depended on the old ## Why this care A system's tokens are referenced across the whole app, so changing them ripples. Renaming a token after -hundreds of components reference it means touching every reference — which is why `establish` builds -semantic naming in from the start and `evolve` aliases rather than renames in place. This discipline is +hundreds of components reference it means touching every reference — which is why `establish-design-system` builds +semantic naming in from the start and `evolve-design-system` aliases rather than renames in place. This discipline is what lets the system change without breaking everything downstream — the difference between a design system and a pile of values. diff --git a/ai/skills/design/design-handoff/references/token-reconciliation.md b/ai/skills/design/design-handoff/references/token-reconciliation.md index ed359dd..3c4f012 100644 --- a/ai/skills/design/design-handoff/references/token-reconciliation.md +++ b/ai/skills/design/design-handoff/references/token-reconciliation.md @@ -5,11 +5,11 @@ of brand/dark-mode overrides) carrying the design's primitives — palette, font scale. What you do with it depends on the **mode**, but one rule is constant: **the bundle's tokens are a proposal; `globals.css` is truth.** -- **`establish`** (no system yet) — _write canonical_ tokens from the bundle. That's the bulk of this +- **`establish-design-system`** (no system yet) — _write canonical_ tokens from the bundle. That's the bulk of this doc: the conflicts, the skeleton, the by-role merge recipe, and authoring `.dark`. - **`implement-feature`** (a feature against an existing system) — _consume-first_: diff and map to the existing tokens, adding nothing by default. **Start at "Consume-first" below.** -- **`evolve`** (changing the system) — diff and version the change; see `evolving-the-system.md`. +- **`evolve-design-system`** (changing the system) — diff and version the change; see `evolving-the-system.md`. Either way it is **not** a drop-in — pasting a token file into `globals.css` breaks the system. @@ -32,14 +32,14 @@ drifted — so you **consume** them, you don't rewrite: difference is incidental or the value appears once. - **Deliberately extend** (when the need is real and reusable): add the token _additively_ (the shadcn pattern — define `--warning`/`--warning-foreground` in `:root` and `.dark`, expose via - `@theme inline`), update `/brand` and `DESIGN.md`, and record a DDR. That's an `evolve`-style + `@theme inline`), update `/brand` and `DESIGN.md`, and record a DDR. That's an `evolve-design-system`-style change folded into the feature, so it carries a SemVer bump (`evolving-the-system.md`). - **Heuristic:** extend only if the value (a) is a _semantic role_, not just a shade, (b) will plausibly recur, and (c) you'd document it in `/brand`. Otherwise force-fit. 4. **Never overwrite `globals.css` wholesale** from a feature bundle — it may re-emit the whole token block; you apply only deliberate, approved additions. -The rest of this doc (the conflicts, skeleton, and merge recipe) is the `establish` path — you'll also +The rest of this doc (the conflicts, skeleton, and merge recipe) is the `establish-design-system` path — you'll also dip into it when a feature legitimately extends the system. ## Why you can't paste it in From 12aba1f0e7bdeee911bab271038c10c4a6cb49a8 Mon Sep 17 00:00:00 2001 From: Evan Harmon Date: Wed, 17 Jun 2026 18:06:03 -0500 Subject: [PATCH 13/16] docs(skills): add a deliverables coverage-checklist reference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Distill the implementation-relevant slice of a design-deliverables master list into one lean, on-demand reference — a completeness self-check (not a build mandate) the agent consults in establish-design-system / evolve-design-system and when building /brand, so it doesn't miss a token category, component family, or brand asset (e.g. chart palette, gradients, named z-index layers, named animations, OG images). - New references/deliverables-checklist.md: terse, pointer-based coverage list that links to the detailed references rather than re-explaining them; plus a "scoped OUT" section (page/screen catalog, UX-process artifacts, marketing production) noting those belong to the separate Claude Design *creation* skill. - Wire it in: SKILL.md reference index + a Phase 1 pointer; one-line pointers from greenfield-bootstrap.md, brand-page.md (Foundations), and evolving-the-system.md. Co-Authored-By: Claude Opus 4.8 (1M context) --- ai/skills/design/design-handoff/SKILL.md | 8 +- .../design-handoff/references/brand-page.md | 3 + .../references/deliverables-checklist.md | 74 +++++++++++++++++++ .../references/evolving-the-system.md | 4 +- .../references/greenfield-bootstrap.md | 3 +- 5 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 ai/skills/design/design-handoff/references/deliverables-checklist.md diff --git a/ai/skills/design/design-handoff/SKILL.md b/ai/skills/design/design-handoff/SKILL.md index cbcab60..82c5de8 100644 --- a/ai/skills/design/design-handoff/SKILL.md +++ b/ai/skills/design/design-handoff/SKILL.md @@ -150,8 +150,9 @@ and shadcn for the detected framework, let `shadcn init` write the default three scaffold the `/brand` route, `DESIGN.md`, and `docs/design/`, copy `scripts/check-contrast.mjs`, and add the design Taskfile tasks. **Normalize whatever the bundle emits** (often HSL or inline values) into the canonical OKLCH three-layer form, and record a **DDR establishing the system at v1.0.0**. Assumes a -working frontend app already exists. See `greenfield-bootstrap.md`. (An existing system skips to Phase -2.) +working frontend app already exists. Use `deliverables-checklist.md` to confirm the **full** token and +component set is covered, not just the brand colors. See `greenfield-bootstrap.md`. (An existing system +skips to Phase 2.) ### Phase 2 — Reconcile tokens — GATE: static contrast @@ -266,6 +267,9 @@ commits to `main` are blocked) and open a **PR** for human review — never merg lock-in. - **`verification-and-signoff.md`** — Phases 5–7: the gates, the sign-off loop, cleanup, and commit + PR. +- **`deliverables-checklist.md`** — a completeness self-check for token, component, brand, asset, and + collateral coverage; used in `establish-design-system`/`evolve-design-system` and when building + `/brand`. Bundled assets (the skill installs these into the target repo): diff --git a/ai/skills/design/design-handoff/references/brand-page.md b/ai/skills/design/design-handoff/references/brand-page.md index 5666ed8..5ee1e62 100644 --- a/ai/skills/design/design-handoff/references/brand-page.md +++ b/ai/skills/design/design-handoff/references/brand-page.md @@ -55,6 +55,9 @@ include it; this is the one place where more is better. ### Foundations +> Coverage check: run this section past `deliverables-checklist.md` so no token category (chart palette, +> gradients, named z-index layers, named animations, …) is forgotten. + - **Brand & voice** — the design's name, tagline, and a one-line positioning statement; 3–5 personality adjectives; voice & tone with two or three do/don't microcopy examples; capitalization, terminology, and how to refer to the product; date/number formatting conventions. diff --git a/ai/skills/design/design-handoff/references/deliverables-checklist.md b/ai/skills/design/design-handoff/references/deliverables-checklist.md new file mode 100644 index 0000000..ca4507e --- /dev/null +++ b/ai/skills/design/design-handoff/references/deliverables-checklist.md @@ -0,0 +1,74 @@ +# Deliverables coverage checklist + +A completeness check, **not** a build list. Consult it in **`establish-design-system`** and +**`evolve-design-system`** mode, and when building **`/brand`**, to make sure you haven't missed a token +category, component family, or brand asset. **Awareness, not a mandate:** only implement what the +handoff actually needs — this list prevents _missing_ things, it doesn't force _adding_ everything. It's +a self-check, **not** part of the chat-tracked Definition of Done. Each line points to the reference +that explains it. + +## Tokens & foundations → `token-reconciliation.md`, `brand-page.md` + +- [ ] Color — brand/primary, secondary, accent; neutral ramp; semantic (success/warning/error/info); + surfaces (base/card/popover/overlay); foreground (default/muted/on-color); border/input/ring; + interactive states; **data-viz / chart palette**; **named gradients**; light **and** dark +- [ ] Typography — families (display/body/mono); scale; weights; line-height; tracking; + heading/body/prose/link/list/code styles; responsive type; font loading and fallbacks +- [ ] Spacing & sizing — spacing scale; sizing/control heights; container/max-width; layout grid; + breakpoints; aspect-ratios +- [ ] Shape — radius scale; border widths +- [ ] Elevation — shadow scale; **named z-index layers** + (dropdown/sticky/overlay/modal/popover/toast/tooltip); focus ring +- [ ] Effects — opacity scale; blur/backdrop; overlay/scrim +- [ ] Motion — durations; easings; transition presets; **named animations** + (spinner/skeleton/toast/accordion); reduced-motion variants +- [ ] Interaction states — hover, focus-visible, active, disabled, loading, selected, error, read-only + +## Components (each in all states) → `components-and-states.md` + +- [ ] Actions; form inputs; labels and helpers; data display + (tables/lists/cards/stats/charts/avatars/badges); feedback and status; overlays and surfaces; + navigation; containers and layout; composed patterns (search+filter, bulk actions, user menu, + onboarding, consent, paywall) + +## Brand identity → `brand-page.md` (Tier 1/2), `ethics-and-licensing.md` + +- [ ] Logo system (lockup/mark/wordmark, mono/reversed/responsive, clear-space, min-size, misuse, + SVG/PNG/PDF exports) +- [ ] Brand color values in HEX / RGB / OKLCH / CMYK / Pantone; usage proportions +- [ ] Brand typography and licensing (OFL/Apache); web/print/fallback; pairings +- [ ] Voice & tone — personality, tagline, boilerplate (S/M/L), terminology, naming conventions +- [ ] Visual language — iconography (Lucide), illustration, photography direction, patterns/textures, + data-viz style, motion principles +- [ ] Brand book (web and downloadable PDF) with in-context application examples + +## Assets → `assets-fonts-favicons.md`, `brand-page.md` + +- [ ] Icon set; favicon (.ico and PNG); app icons (iOS/Android/PWA); apple-touch-icon +- [ ] Illustrations / graphics (spot, hero, empty-state); patterns / backgrounds +- [ ] **OG / social share images** (template and per-page variants) +- [ ] PWA `manifest.json` icons and theme color; splash screens + +## Collateral (opt-in groups) → `brand-page.md` (Tier 3) + +- [ ] Social & web; email; print; presentations & documents; and the "Other" long tail + (motion/video, merch/environmental, product/app-store, audio) — only the groups the user selected + +## Design-system docs → `evolving-the-system.md`, `brand-page.md` + +- [ ] `DESIGN.md` (intent and soft rules); token reference; component usage docs; accessibility + guidelines; **versioning / changelog** (SemVer and DDRs) + +## Scoped OUT — belongs to the Claude Design _creation_ skill, not this one + +This skill **implements what was handed off**; it doesn't commission the full design program. The +following are produced _in_ Claude Design and are out of scope here — a separate creation skill owns +them: + +- Page/screen catalog (marketing-site set, auth/account set, full app screens) +- UX-process artifacts (personas, jobs-to-be-done, IA/sitemaps, user flows/journeys, wireframes, + clickable prototypes, usability test plans) +- Marketing _production_ (vehicle wraps, trade-show booths, swag, printed mailers) + +If the handoff bundle happens to include any of these, implement what it contains — just don't treat +their absence as a gap in _this_ skill. diff --git a/ai/skills/design/design-handoff/references/evolving-the-system.md b/ai/skills/design/design-handoff/references/evolving-the-system.md index cc57da8..c68bbd6 100644 --- a/ai/skills/design/design-handoff/references/evolving-the-system.md +++ b/ai/skills/design/design-handoff/references/evolving-the-system.md @@ -4,7 +4,9 @@ Read this during **Phase 2** in **`evolve-design-system`** mode — when the bun system itself (not a single feature). The doctrine is the same as everywhere: the repo is truth, the bundle is a proposal. Evolve means reconciling a proposed token change into canonical `globals.css` **carefully and versioned** — never a blind overwrite, because much of a bundle's token block is a -re-emission that may have drifted from canonical. +re-emission that may have drifted from canonical. If the change adds a new role, cross-check +`deliverables-checklist.md` so the system stays complete (e.g. a new semantic color also needs its +`-foreground`, its `/brand` swatch, and a contrast pass). ## 1. Diff before you write diff --git a/ai/skills/design/design-handoff/references/greenfield-bootstrap.md b/ai/skills/design/design-handoff/references/greenfield-bootstrap.md index 1d64be2..2d4f02d 100644 --- a/ai/skills/design/design-handoff/references/greenfield-bootstrap.md +++ b/ai/skills/design/design-handoff/references/greenfield-bootstrap.md @@ -112,4 +112,5 @@ the design's real tokens are in. With the design system stood up, proceed to **Phase 2 — token reconciliation** (`token-reconciliation.md`): replace the default token _values_ with the design's, author `.dark`, and -get the static contrast gate green before implementing components. +get the static contrast gate green before implementing components. Before you call the system complete, +run it past `deliverables-checklist.md` so no token category or component family is missed. From c3b8b1d8f6036952524875559f2b6164b9bebc52 Mon Sep 17 00:00:00 2001 From: Evan Harmon Date: Wed, 17 Jun 2026 18:47:48 -0500 Subject: [PATCH 14/16] =?UTF-8?q?style(skills):=20fix=20MD031=20=E2=80=94?= =?UTF-8?q?=20blank=20lines=20around=20the=20indented=20fence=20in=20green?= =?UTF-8?q?field-bootstrap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Surround the in-list `ts` Vite-config block with blank lines so it satisfies markdownlint MD031 (blanks-around-fences). The fence stays indented under the list item, so the list structure is unchanged. Pre-existing nit unrelated to the skill's logic. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../design/design-handoff/references/greenfield-bootstrap.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ai/skills/design/design-handoff/references/greenfield-bootstrap.md b/ai/skills/design/design-handoff/references/greenfield-bootstrap.md index 2d4f02d..a79ad17 100644 --- a/ai/skills/design/design-handoff/references/greenfield-bootstrap.md +++ b/ai/skills/design/design-handoff/references/greenfield-bootstrap.md @@ -47,12 +47,14 @@ pnpm dlx shadcn@latest init # choose a base color (Neutral/Stone/Zinc ``` - **Vite plugin:** add Tailwind to `vite.config.ts`: + ```ts import tailwindcss from "@tailwindcss/vite"; export default defineConfig({ plugins: [tailwindcss() /*, …router plugin, react() */], }); ``` + - **Path alias:** ensure `@/*→ ./src/*` in `tsconfig.json` and `resolve.alias` in `vite.config.ts` (shadcn init prompts for this; components import as `@/components/ui/...`). - **Global stylesheet:** `src/styles/globals.css` (starts with `@import "tailwindcss";`), imported From 49a57453295f163d478fc1162ada79e7d4f0e94d Mon Sep 17 00:00:00 2001 From: Evan Harmon Date: Wed, 17 Jun 2026 19:43:34 -0500 Subject: [PATCH 15/16] docs(skills): fix gate count in verification-and-signoff (four, not three) Align with SKILL.md's four-gate model: the intro now says this file covers gates 3 (Verification, Phase 5) and 4 (Sign-off, Phase 6), with 1 (static contrast, Phase 2) and 2 (licensing, Phase 4) upstream. The recap lists all four numbered gates and marks Phase 7 close-out as post-gate actions, not a gate. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../references/verification-and-signoff.md | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/ai/skills/design/design-handoff/references/verification-and-signoff.md b/ai/skills/design/design-handoff/references/verification-and-signoff.md index 3dd92d3..6ab5d9b 100644 --- a/ai/skills/design/design-handoff/references/verification-and-signoff.md +++ b/ai/skills/design/design-handoff/references/verification-and-signoff.md @@ -1,9 +1,9 @@ # Verification & sign-off: prove it, get approval, then close out Read this during **Phases 5–7**. This is where you prove the implementation with numbers and -screenshots, get the user's explicit approval, and only **then** clean up and open a PR. Three gates -live here: rendered contrast, sign-off (blocks deleting the bundle), and the no-bypass commit -discipline. +screenshots, get the user's explicit approval, and only **then** clean up and open a PR. Two of the +skill's four gates fall in these phases — **③ Verification** (Phase 5) and **④ Sign-off** (Phase 6); the +upstream two (**① static contrast** at Phase 2, **② licensing** at Phase 4) are already behind you. ## Phase 5 — Verify (don't trust a green build) @@ -70,10 +70,16 @@ against. `main` are blocked and wrong. The agent **never merges to `main` directly**: open a **PR** for human review of the diff. -## Definition-of-done recap (the gates, in order) +## The four gates, in order -- **Licensing** (Phase 4) blocks **commit** — every asset cleared for commercial use. -- **Rendered contrast** (Phase 5) measured as **numbers**, both themes. -- **Sign-off** (Phase 6) blocks **deletion** — explicit user approval, never inferred. -- **Close-out** (Phase 7): `task verify` green, hooks not bypassed, bundle removed, docs + `/brand` - updated, DDR flagged if warranted, Conventional Commit, PR opened (no direct merge to `main`). +- **① Static contrast** (Phase 2) blocks **implementation** — `task lint:design` green; WCAG AA in both + themes. +- **② Licensing** (Phase 4) blocks **commit** — every font/icon/image cleared for commercial use. +- **③ Verification** (Phase 5) blocks **sign-off** — `task verify` green and the build compiles; + rendered contrast measured as **numbers** (both themes); responsive at phone/tablet/desktop; + cross-browser on Chromium/Firefox/WebKit (incl. mobile Safari). +- **④ Sign-off** (Phase 6) blocks **deletion & close-out** — explicit user approval, never inferred. + +Then **close-out** (Phase 7 — not a gate): bundle removed, docs and `/brand` updated, DDR + SemVer bump +recorded, Conventional Commit, PR opened — hooks never bypassed (`--no-verify` prohibited), no direct +merge to `main`. From 292562ef5ee595682994e348765b029a2b6b1f11 Mon Sep 17 00:00:00 2001 From: Evan Harmon Date: Wed, 17 Jun 2026 19:47:41 -0500 Subject: [PATCH 16/16] docs(skills): replace stale greenfield-vs-brownfield wording with the three modes Consistency pass found ingesting-the-bundle.md's 'After ingest' step still used the retired two-path model. Point it at SKILL.md Phase 0's mode detection (establish-design-system / evolve-design-system / implement-feature) instead. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../design-handoff/references/ingesting-the-bundle.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ai/skills/design/design-handoff/references/ingesting-the-bundle.md b/ai/skills/design/design-handoff/references/ingesting-the-bundle.md index 0de487c..02c1b16 100644 --- a/ai/skills/design/design-handoff/references/ingesting-the-bundle.md +++ b/ai/skills/design/design-handoff/references/ingesting-the-bundle.md @@ -87,8 +87,8 @@ the bundle's `.jsx`/`.html` into `src/`. ## After ingest Inventory what you got — the `tokens.css` palette/scales, the component list under `js/`, the fonts -referenced, the `uploads/` — then **detect the repo's framework + router** (see SKILL.md) so every -later file-placement decision is correct, and decide **greenfield vs brownfield** -(`greenfield-bootstrap.md` if no design system exists yet). Leave the bundle in -`docs/design/handoff-/` **untouched**: it is the reference the user signs off against in -Phase 6 and is not removed until Phase 7, after explicit approval. +referenced, the `uploads/` — then **detect the framework, router, and mode** (SKILL.md Phase 0): +`establish-design-system` (no system yet — `greenfield-bootstrap.md`), `evolve-design-system` +(changing the system — `evolving-the-system.md`), or `implement-feature` (a feature against an existing +system). Leave the bundle in `docs/design/handoff-/` **untouched**: it is the reference the +user signs off against in Phase 6 and is not removed until Phase 7, after explicit approval.