From 683b36bd2afd8f78e285838f76c491eaa6cc65be Mon Sep 17 00:00:00 2001 From: Barry Earsman Date: Sun, 26 Apr 2026 09:19:17 +1000 Subject: [PATCH 01/14] feat: new Figma Driven Development skill --- skills/figma-driven-development/SKILL.md | 268 +++++++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 skills/figma-driven-development/SKILL.md diff --git a/skills/figma-driven-development/SKILL.md b/skills/figma-driven-development/SKILL.md new file mode 100644 index 0000000..3b8c93a --- /dev/null +++ b/skills/figma-driven-development/SKILL.md @@ -0,0 +1,268 @@ +--- +name: figma-driven-development +description: Use when implementing UI from a Figma link. Required before writing any code when a Figma URL is provided. Also use when auditing an existing implementation for Figma fidelity. +--- + +# Figma-Driven Development + +## Overview + +Use Figma as a rigid implementation scaffold. Every visual decision must trace back to a specific fetched Figma node — no guessing, no implementing from memory. A shared catalogue file on disk lets multiple agents share discovery without re-fetching. + +Two modes: +- **Build mode** — implementing a section from scratch (Phases 1–6) +- **Audit mode** — checking an existing implementation against Figma (Phase 7) + +## Phase 1: Discover Figma Tools + +Before anything else, load the Figma tool schemas: + +``` +ToolSearch("figma") +ToolSearch("select:mcp__claude_ai_Figma__get_metadata,mcp__claude_ai_Figma__get_design_context,mcp__claude_ai_Figma__get_screenshot") +``` + +**If ToolSearch returns nothing:** The Figma integration needs to be connected. Ask the user to connect Figma via claude.ai settings (`/mcp`), then restart the session. Do not proceed without Figma access — do not implement from memory or screenshots. + +**Key tools:** +- `get_metadata` — XML structural tree (node IDs, names, sizes). Use for cataloguing. +- `get_design_context` — Reference code + screenshot + design values. Use for implementation when exact values are needed. +- `get_screenshot` — Visual render of any node. Use first — it's cheap. Only escalate to `get_design_context` when a discrepancy needs exact values to fix. + +## Phase 2: Parse the URL + +Extract `fileKey` and `nodeId` from the Figma URL: + +``` +https://www.figma.com/design/sHPq6WL754484sETatkL51/Name?node-id=9936-6 + ^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^ + fileKey nodeId (convert - to :) +``` + +**The `node-id` in the URL is the designers' intended starting frame — use it directly.** Do NOT start from `0:1` (the page root) — it returns the entire file tree and exceeds token limits. + +## Phase 3: Check for Existing Catalogue + +The catalogue lives at `.figma/[fileKey].md`. + +**If it exists:** Read it, then: +- Does the target section appear in the catalogue? → Go to Phase 5 (build) or Phase 7 (audit). +- Section missing from catalogue? → See "Section Not in Catalogue" below. + +**If not:** Continue to Phase 4. + +### Section Not in Catalogue + +Do NOT re-fetch root metadata. Instead, work through these steps in order: + +1. **Check for a naming mismatch.** Catalogue section names come from Figma layer names — the task may use a different label. Scan the catalogue descriptions carefully before concluding it's absent. + +2. **Screenshot the root node** to visually search for the section: + ``` + get_screenshot(fileKey, rootNodeId) + ``` + If you can see the section, it's in the root frame but wasn't catalogued. Fetch its metadata (via subagent), add it to the catalogue, then proceed. + +3. **If still not found:** The section may live in a different Figma frame not covered by the current catalogue. Ask the user to provide the specific Figma URL with the node-id focused on that section (e.g. by selecting it in Figma dev mode and copying the link). Do not guess — do not implement without a node ID. + +## Phase 4: Build the Catalogue + +### 4a. Fetch structural metadata for the root node + +``` +get_metadata(fileKey, nodeId) +``` + +⚠️ This response will likely exceed context limits. **Use a subagent to parse it:** + +> "File at [path] is a JSON array [{type, text}] where text is XML. Extract: (1) the root node name/type/size, (2) a table of its direct children — the XML `name` attribute, id, type, width, height. Return markdown only." + +**The XML `name` attribute on each child frame is the authoritative section name** — use it directly in the catalogue. Do not rename sections based on visual guesses; Figma layer names are what designers use to communicate intent. + +### 4b. Screenshot all sections in parallel for verification + +For all sections in the metadata children list, dispatch screenshots in parallel: + +``` +get_screenshot(fileKey, sectionNodeId) — one per section, all at once +``` + +A full-page overview screenshot is too small to read section headings — screenshot sections individually. Use the screenshots to write meaningful descriptions and catch mismatches between a layer name and its actual visual content. + +### 4c. Write the catalogue + +Save to `.figma/[fileKey].md`: + +```markdown +# Figma Catalogue — [File Name] +File key: [key] +Root node: `[nodeId]` ("[name]" — [width]×[height]px) +Catalogued: [date] + +## Sections + +### [Figma layer name] +- Node ID: `9936:51` +- Size: 1440×803px +- Description: [layout, key elements, purpose — from screenshot] + +[... one entry per section ...] + +## Shared Styles + +| Token | Observed value | Notes | +|-------|---------------|-------| +| Background | #?????? | Verify via get_design_context | +| Primary accent | #?????? | Buttons, badges, highlights | +| Heading font | [family weight/size] | Verify per section | + +> Exact values must be confirmed by fetching each section's design context. + +## DRY Opportunities + +Repeated patterns across sections — candidates for shared components or classes: + +- **[Pattern name]**: Appears in [Section A] ([nodeId]), [Section B] ([nodeId]) — candidate for `` or `.class-name` +``` + +### 4d. Identify DRY opportunities globally + +Before implementing anything, scan the section list for: +- Repeated background layers (same size/type appearing in multiple sections) +- Shared button variants +- Common content wrapper widths (e.g. 1180px centred column) +- Typography/heading patterns that repeat + +Note these in the catalogue. Implementing DRY later is expensive — find it now. + +## Phase 5: Implement a Section + +For the section you are implementing: + +1. **Re-read the catalogue** — find its node ID. +2. **Sanity-check the catalogue entry.** Take a screenshot and verify the visual content matches the catalogue description. If it doesn't match, re-catalogue that entry before proceeding. +3. **Check whether the target node is a sub-component.** If the node name suggests it is a sub-component rather than a full section (e.g. `PieChart`, `Icon`, `Card`, `Button`) — fetch the **parent node's metadata** before implementing. Labels, callouts, and decorators that visually belong to the sub-component are often siblings in the parent, not children of the sub-component node. Implement the smallest container that includes all visually related siblings. +4. **Screenshot first, design context only if needed.** Take a screenshot of the section. If the section doesn't exist yet in the codebase, proceed to fetch design context. If it does exist, compare the screenshot to the current implementation visually — only fetch `get_design_context` if you spot a discrepancy that needs exact values to resolve. +4. **Fetch design context when needed:** + ``` + get_design_context(fileKey, sectionNodeId) + ``` + This returns reference code (React + Tailwind), a screenshot, and design values. It is a **reference, not final code** — adapt it to the project's stack, conventions, and existing components. +5. **Extract from the response:** + - Layout: direction, alignment, padding, gap, max-width + - Background: colour, gradient stops, image references + - **All text content** — copy every text node's exact string. Screenshots can't catch copy mismatches. Cross-check text content in the code (and in the project's config/data layer — see note below) against these strings. + - Interactive elements: button labels, variants, states + - Decorative/structural elements: asset URLs, connector lines, dividers, positions + - Responsive variants: look for Mobile / Tablet / Desktop frames +6. **Check the config/data layer.** If the project separates copy or data into a config file (e.g. `site-config.ts`) or CMS, check that layer against Figma's text nodes — not just the component output. A copy mismatch may live entirely in config, invisible in the JSX. +7. **Download assets immediately after fetching design context — before writing any code.** `get_design_context` returns `figma.com/api/mcp/asset/...` URLs that expire in 7 days. Each new call to `get_design_context` (including for a parent or sibling node) returns *new* URLs for the same assets — do not mix URLs from different fetches. Download immediately from the URLs in the response you are currently working with, before touching the codebase. Classify each URL by purpose: + - **Images** (photos, illustrations, coin graphics) → `curl -o public/images/[name].[ext] "[url]"` — use descriptive filenames, not UUIDs + - **Icons** (SVG) → `curl -o public/icons/[name].svg "[url]"` — check if an equivalent already exists in the project before downloading + - **Structural elements** (connector lines, dividers, borders, decorative shapes) → **do not download** — reconstruct with CSS (`border`, `background: linear-gradient(...)`, inline SVG). Never use an expiring asset URL for a UI element. + - **Existing committed static asset** (e.g. `pie-chart.png`) approximating a Figma vector → this is a sign the original implementation bypassed this skill. The correct implementation is CSS reconstruction. Verify visual equivalence for now, but flag it as technical debt to be replaced with a proper CSS implementation. + + After downloading, reference committed paths in code — never the Figma asset URL. +8. **Cross-reference** every colour and spacing value against the existing design system (Tailwind config, CSS variables, existing components) before adding new tokens. +9. **Check DRY opportunities** from the catalogue — use or extend shared components/classes. +10. **Shared component fidelity:** If a shared component (e.g. ``) can't express the Figma layout for this specific section (e.g. inline vs. stacked text), inline the markup for that section. **Fidelity to the Figma takes precedence over reusing a shared component** when they conflict. Do not distort the layout to fit the component. +11. **Batch edits, then verify once.** Make all your edits for the section, then run typecheck/build once at the end. Do not run typecheck after each individual edit unless an edit is likely to introduce a type error you need to diagnose immediately. + +## Phase 6: Zooming Into Child Nodes + +If a section is complex or a value is unclear: + +``` +get_screenshot(fileKey, childNodeId) — visual confirmation (cheap, do this first) +get_design_context(fileKey, childNodeId) — exact values and reference code (only if needed) +``` + +**If a section contains repeated similar elements** (e.g. multiple connector lines, multiple cards, multiple icons that may differ): screenshot each child node individually to confirm their styles before implementing. The reference code from `get_design_context` may flatten similar elements into a single container, hiding style differences between them. + +**Watch for Figma coordinate artefacts.** The reference code from `get_design_context` is a direct translation of Figma's internal layout maths. Certain patterns only work correctly at the original design dimensions and will break at other sizes: + +| Artefact | Example | Risk | +|----------|---------|------| +| Percentage insets on absolute elements | `inset: "6.52% 3.42%"` | Collapses if parent has no explicit size | +| Negative insets exceeding 100% | `inset: "-102.42% -72.65%"` | Overflows or clips at different sizes | +| `calc()` with large px offsets | `left: calc(50% + 227.91px)` | Breaks at narrower containers | +| Pixel positions referencing parent size | `top: -220.86px` | Only valid at the exact original height | + +When you encounter these patterns: verify that the parent container has an explicit fixed size matching Figma's dimensions, or convert to values that will work at the target render size. + +Child node IDs are visible in `get_metadata` output and in Figma's URL when you click an element in dev mode. Do not guess values — re-fetch the specific node. + +## Phase 7: Audit Mode + +Use this when checking an existing implementation for Figma fidelity, rather than building from scratch. + +### 7a. Read the existing implementation first + +Before fetching anything from Figma, read all relevant source files — components, views, and the config/data layer. Build a mental model of what the code currently produces. + +### 7b. Screenshot all sections in parallel + +Using the node IDs from the catalogue, fetch screenshots of all sections at once: + +``` +get_screenshot(fileKey, sectionNodeId) — all sections in parallel +``` + +Do not fetch `get_design_context` yet — screenshots are cheap and may be sufficient to confirm sections are correct. + +### 7c. Build a diff list before touching any code + +Compare each section screenshot against the current implementation. For each section, classify: +- **Correct** — no action needed +- **Layout deviation** — wrong spacing, alignment, sizing +- **Copy mismatch** — text content differs (screenshots won't show this — cross-check text nodes separately) +- **Missing element** — Figma has something the implementation lacks +- **Wrong element** — implementation has something Figma doesn't + +Only fetch `get_design_context` for sections with layout deviations that need exact values. Sections confirmed correct by screenshot need no further Figma fetching. + +### 7d. Triage before editing + +Not all deviations are worth fixing. Use this priority order: +1. **Wrong layout or structure** — fix immediately +2. **Wrong copy** — fix immediately +3. **Missing element** — fix immediately +4. **Minor spacing deviation** (1–4px off) — fix if it's visible; skip if it's within Tailwind's scale rounding +5. **Pixel-perfect padding differences** that don't affect the visual feel — skip + +### 7e. Batch all edits, then verify once + +Make all fixes across all sections, then run typecheck/build once. Update the catalogue if any section's description was wrong. + +## What NOT to Do + +| Bad | Good | +|-----|------| +| Fetch `0:1` (page root) — returns entire file tree | Start from the URL's `node-id` — it's the right frame | +| Read large metadata results into main context | Use a subagent to parse oversized responses | +| Name sections from visual guesses or screenshots | Use the Figma XML `name` attribute — it's authoritative | +| Screenshot only the full page to identify sections | Screenshot each section individually — thumbnail is too small | +| Trust catalogue entry without sanity-checking | Verify node ID + visual content before implementing | +| Fetch `get_design_context` for every section upfront | Screenshot first — only fetch design context when a discrepancy needs exact values | +| Ignore copy when checking visual fidelity | Cross-check all text nodes explicitly — screenshots can't catch copy mismatches | +| Check only component JSX for copy accuracy | Also check the config/data layer (e.g. site-config.ts) — copy may live there | +| Leave Figma asset URLs in code | Download all images/icons and commit before writing any code | +| Use expiring Figma asset URLs for connector lines or dividers | Reconstruct structural elements with CSS | +| Treat a static asset approximating a Figma vector as acceptable long-term | Flag it as technical debt — correct implementation is CSS reconstruction | +| Assume repeated elements (lines, cards) are identical | Screenshot each child to confirm — they may differ | +| Force a shared component to fit a section's layout | Inline the markup when fidelity and DRY conflict | +| Hardcode a colour without checking existing tokens | Cross-reference every value against the design system | +| Run typecheck after every individual edit | Batch all edits, then verify compilation once at the end | +| Re-fetch root metadata when a section is missing from the catalogue | Screenshot the root node first — visually check if it exists | +| Implement a section not found in Figma | Ask the user for the specific node URL rather than guessing | + +## Catalogue File Location + +`.figma/[fileKey].md` — relative to the project root. + +- Lives inside the project so CK Search indexes it; agents can query it semantically rather than reading the whole file +- Listed in `.gitignore` — not committed, since it's generated and may go stale as the Figma evolves +- Survives reboots (unlike `/tmp/`), so the cataloguing cost is paid once per machine per project +- Written in Phase 4, read in Phases 5 and 7; multiple agents share it without re-fetching + +**On first use in a project:** create the directory with `mkdir -p .figma/` before writing the catalogue. From 90dc2f2f7fdc018c29339283ca2b7aeafc863856 Mon Sep 17 00:00:00 2001 From: Barry Earsman Date: Sun, 26 Apr 2026 09:31:44 +1000 Subject: [PATCH 02/14] feat: improve figma metadata handling --- skills/figma-driven-development/SKILL.md | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/skills/figma-driven-development/SKILL.md b/skills/figma-driven-development/SKILL.md index 3b8c93a..1c53da7 100644 --- a/skills/figma-driven-development/SKILL.md +++ b/skills/figma-driven-development/SKILL.md @@ -25,7 +25,7 @@ ToolSearch("select:mcp__claude_ai_Figma__get_metadata,mcp__claude_ai_Figma__get_ **If ToolSearch returns nothing:** The Figma integration needs to be connected. Ask the user to connect Figma via claude.ai settings (`/mcp`), then restart the session. Do not proceed without Figma access — do not implement from memory or screenshots. **Key tools:** -- `get_metadata` — XML structural tree (node IDs, names, sizes). Use for cataloguing. +- `get_metadata` — XML structural tree (node IDs, names, sizes). Use for cataloguing. **Always call via subagent** — root-level responses routinely exceed context limits and this is predictable, not a surprise. - `get_design_context` — Reference code + screenshot + design values. Use for implementation when exact values are needed. - `get_screenshot` — Visual render of any node. Use first — it's cheap. Only escalate to `get_design_context` when a discrepancy needs exact values to fix. @@ -69,16 +69,17 @@ Do NOT re-fetch root metadata. Instead, work through these steps in order: ### 4a. Fetch structural metadata for the root node -``` -get_metadata(fileKey, nodeId) -``` +**Always route `get_metadata` through a subagent.** A root frame covering a full marketing page (height > 2000px, 5+ sections) will exceed context limits — this is predictable, not a contingency. Do not call `get_metadata` in the main session and react to the overflow; plan for the subagent upfront. -⚠️ This response will likely exceed context limits. **Use a subagent to parse it:** +Call `get_metadata` in your main session, then immediately hand the result file path to a subagent. **Copy the exact file path from the tool result verbatim — do not retype it**, as UUID-based paths are easy to mistype. -> "File at [path] is a JSON array [{type, text}] where text is XML. Extract: (1) the root node name/type/size, (2) a table of its direct children — the XML `name` attribute, id, type, width, height. Return markdown only." +Subagent briefing template: +> "The file at **[paste exact path here]** is a JSON array [{type, text}] where text is XML. Using jq or python3 (do NOT use the Read tool — file is too large): (1) extract the root node name, type, width, height; (2) produce a markdown table of ALL direct children with columns: name | id | type | width | height. Return markdown only." **The XML `name` attribute on each child frame is the authoritative section name** — use it directly in the catalogue. Do not rename sections based on visual guesses; Figma layer names are what designers use to communicate intent. +**If children have generic names** (e.g. `Frame 168655…`): the designer left frames unnamed. In this case, section names in the catalogue must come from screenshots, not layer names — screenshot each child before writing the catalogue and name entries from their visual content. + ### 4b. Screenshot all sections in parallel for verification For all sections in the metadata children list, dispatch screenshots in parallel: @@ -240,7 +241,8 @@ Make all fixes across all sections, then run typecheck/build once. Update the ca |-----|------| | Fetch `0:1` (page root) — returns entire file tree | Start from the URL's `node-id` — it's the right frame | | Read large metadata results into main context | Use a subagent to parse oversized responses | -| Name sections from visual guesses or screenshots | Use the Figma XML `name` attribute — it's authoritative | +| Name sections from visual guesses or screenshots when layer names exist | Use the Figma XML `name` attribute — it's authoritative | +| Use layer names when frames are generically named (e.g. `Frame 168…`) | Screenshot each child first — visual content is your only reliable naming signal | | Screenshot only the full page to identify sections | Screenshot each section individually — thumbnail is too small | | Trust catalogue entry without sanity-checking | Verify node ID + visual content before implementing | | Fetch `get_design_context` for every section upfront | Screenshot first — only fetch design context when a discrepancy needs exact values | @@ -255,6 +257,9 @@ Make all fixes across all sections, then run typecheck/build once. Update the ca | Run typecheck after every individual edit | Batch all edits, then verify compilation once at the end | | Re-fetch root metadata when a section is missing from the catalogue | Screenshot the root node first — visually check if it exists | | Implement a section not found in Figma | Ask the user for the specific node URL rather than guessing | +| Implement a sub-component node in isolation (e.g. `PieChart`) | Fetch parent metadata first — labels and callouts are often siblings, not children | +| Download assets from one `get_design_context` call then re-fetch the node (or its parent) before writing code | Download immediately after each fetch — new calls return new URLs; do not mix | +| Use percentage insets, negative insets >100%, or `calc()` with large px offsets without checking parent size | Verify parent has an explicit fixed size matching Figma dimensions, or convert to size-safe values | ## Catalogue File Location From 5efd473019d779bd90edbbc3344ffd4345382886 Mon Sep 17 00:00:00 2001 From: Barry Earsman Date: Sun, 26 Apr 2026 16:35:04 +1000 Subject: [PATCH 03/14] refactor: reduce figma-driven-development skill size and harden visual gate Reduced from 353 to 208 lines by collapsing redundant prose and the standalone "What NOT to Do" table into a consolidated Key Rules table. Moved post-implementation visual verification from a skippable Phase 5b heading into a numbered step 12 inside Phase 5, labelled as a hard gate to prevent agents from skipping it. Co-Authored-By: Claude Sonnet 4.6 --- skills/figma-driven-development/SKILL.md | 290 +++++++++-------------- 1 file changed, 107 insertions(+), 183 deletions(-) diff --git a/skills/figma-driven-development/SKILL.md b/skills/figma-driven-development/SKILL.md index 1c53da7..d21948e 100644 --- a/skills/figma-driven-development/SKILL.md +++ b/skills/figma-driven-development/SKILL.md @@ -5,90 +5,58 @@ description: Use when implementing UI from a Figma link. Required before writing # Figma-Driven Development -## Overview - -Use Figma as a rigid implementation scaffold. Every visual decision must trace back to a specific fetched Figma node — no guessing, no implementing from memory. A shared catalogue file on disk lets multiple agents share discovery without re-fetching. - -Two modes: -- **Build mode** — implementing a section from scratch (Phases 1–6) -- **Audit mode** — checking an existing implementation against Figma (Phase 7) +Two modes: **Build** (Phases 1–6) and **Audit** (Phase 7). ## Phase 1: Discover Figma Tools -Before anything else, load the Figma tool schemas: - ``` ToolSearch("figma") ToolSearch("select:mcp__claude_ai_Figma__get_metadata,mcp__claude_ai_Figma__get_design_context,mcp__claude_ai_Figma__get_screenshot") ``` -**If ToolSearch returns nothing:** The Figma integration needs to be connected. Ask the user to connect Figma via claude.ai settings (`/mcp`), then restart the session. Do not proceed without Figma access — do not implement from memory or screenshots. +If ToolSearch returns nothing: ask the user to connect Figma via claude.ai settings (`/mcp`) and restart. Do not implement from memory or screenshots without Figma access. -**Key tools:** -- `get_metadata` — XML structural tree (node IDs, names, sizes). Use for cataloguing. **Always call via subagent** — root-level responses routinely exceed context limits and this is predictable, not a surprise. -- `get_design_context` — Reference code + screenshot + design values. Use for implementation when exact values are needed. -- `get_screenshot` — Visual render of any node. Use first — it's cheap. Only escalate to `get_design_context` when a discrepancy needs exact values to fix. +**Tools:** +- `get_metadata` — XML structural tree (node IDs, names, sizes). Always call via subagent — root responses exceed context limits predictably. +- `get_design_context` — Reference code + screenshot + design values. Use when exact values are needed. +- `get_screenshot` — Visual render of a node. Use first — it's cheap. Escalate to `get_design_context` only to resolve discrepancies. ## Phase 2: Parse the URL -Extract `fileKey` and `nodeId` from the Figma URL: - ``` https://www.figma.com/design/sHPq6WL754484sETatkL51/Name?node-id=9936-6 ^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^ fileKey nodeId (convert - to :) ``` -**The `node-id` in the URL is the designers' intended starting frame — use it directly.** Do NOT start from `0:1` (the page root) — it returns the entire file tree and exceeds token limits. +Use the URL's `node-id` directly — it's the designer's intended frame. Never start from `0:1` (page root) — it returns the entire file and exceeds token limits. ## Phase 3: Check for Existing Catalogue -The catalogue lives at `.figma/[fileKey].md`. - -**If it exists:** Read it, then: -- Does the target section appear in the catalogue? → Go to Phase 5 (build) or Phase 7 (audit). -- Section missing from catalogue? → See "Section Not in Catalogue" below. - -**If not:** Continue to Phase 4. - -### Section Not in Catalogue +Catalogue lives at `.figma/[fileKey].md`. -Do NOT re-fetch root metadata. Instead, work through these steps in order: - -1. **Check for a naming mismatch.** Catalogue section names come from Figma layer names — the task may use a different label. Scan the catalogue descriptions carefully before concluding it's absent. - -2. **Screenshot the root node** to visually search for the section: - ``` - get_screenshot(fileKey, rootNodeId) - ``` - If you can see the section, it's in the root frame but wasn't catalogued. Fetch its metadata (via subagent), add it to the catalogue, then proceed. - -3. **If still not found:** The section may live in a different Figma frame not covered by the current catalogue. Ask the user to provide the specific Figma URL with the node-id focused on that section (e.g. by selecting it in Figma dev mode and copying the link). Do not guess — do not implement without a node ID. +- **Exists + section present** → Phase 5 (build) or Phase 7 (audit) +- **Exists + section missing** → Check for naming mismatch first. Then `get_screenshot(fileKey, rootNodeId)` to visually search. If still not found, ask the user for the specific node URL — do not guess. +- **Not exists** → Phase 4 ## Phase 4: Build the Catalogue -### 4a. Fetch structural metadata for the root node - -**Always route `get_metadata` through a subagent.** A root frame covering a full marketing page (height > 2000px, 5+ sections) will exceed context limits — this is predictable, not a contingency. Do not call `get_metadata` in the main session and react to the overflow; plan for the subagent upfront. - -Call `get_metadata` in your main session, then immediately hand the result file path to a subagent. **Copy the exact file path from the tool result verbatim — do not retype it**, as UUID-based paths are easy to mistype. - -Subagent briefing template: -> "The file at **[paste exact path here]** is a JSON array [{type, text}] where text is XML. Using jq or python3 (do NOT use the Read tool — file is too large): (1) extract the root node name, type, width, height; (2) produce a markdown table of ALL direct children with columns: name | id | type | width | height. Return markdown only." +### 4a. Fetch root metadata via subagent -**The XML `name` attribute on each child frame is the authoritative section name** — use it directly in the catalogue. Do not rename sections based on visual guesses; Figma layer names are what designers use to communicate intent. +Always route `get_metadata` through a subagent — root frames for full pages predictably exceed context. Copy the exact file path from the tool result verbatim (UUID paths are easy to mistype). -**If children have generic names** (e.g. `Frame 168655…`): the designer left frames unnamed. In this case, section names in the catalogue must come from screenshots, not layer names — screenshot each child before writing the catalogue and name entries from their visual content. +Subagent prompt: +> "File at **[exact path]** is JSON `[{type, text}]` where text is XML. Using jq or python3 (NOT Read tool): (1) root node name, type, width, height; (2) markdown table of ALL direct children: name | id | type | width | height. Return markdown only." -### 4b. Screenshot all sections in parallel for verification +The XML `name` attribute is the authoritative section name. If frames are generically named (e.g. `Frame 168…`), screenshot each child before writing the catalogue and name from visual content. -For all sections in the metadata children list, dispatch screenshots in parallel: +### 4b. Screenshot all sections in parallel ``` get_screenshot(fileKey, sectionNodeId) — one per section, all at once ``` -A full-page overview screenshot is too small to read section headings — screenshot sections individually. Use the screenshots to write meaningful descriptions and catch mismatches between a layer name and its actual visual content. +A full-page overview is too small to read — screenshot sections individually. ### 4c. Write the catalogue @@ -101,173 +69,129 @@ Root node: `[nodeId]` ("[name]" — [width]×[height]px) Catalogued: [date] ## Sections - -### [Figma layer name] +### [Layer name] - Node ID: `9936:51` - Size: 1440×803px - Description: [layout, key elements, purpose — from screenshot] -[... one entry per section ...] - ## Shared Styles - | Token | Observed value | Notes | |-------|---------------|-------| | Background | #?????? | Verify via get_design_context | -| Primary accent | #?????? | Buttons, badges, highlights | -| Heading font | [family weight/size] | Verify per section | - -> Exact values must be confirmed by fetching each section's design context. +> Exact values must be confirmed by fetching design context. ## DRY Opportunities - -Repeated patterns across sections — candidates for shared components or classes: - -- **[Pattern name]**: Appears in [Section A] ([nodeId]), [Section B] ([nodeId]) — candidate for `` or `.class-name` +- **[Pattern]**: Appears in [Section A] ([nodeId]), [Section B] ([nodeId]) — candidate for `` or `.class` ``` -### 4d. Identify DRY opportunities globally +### 4d. Identify DRY opportunities -Before implementing anything, scan the section list for: -- Repeated background layers (same size/type appearing in multiple sections) -- Shared button variants -- Common content wrapper widths (e.g. 1180px centred column) -- Typography/heading patterns that repeat - -Note these in the catalogue. Implementing DRY later is expensive — find it now. +Before implementing, scan for: repeated background layers, shared button variants, common wrapper widths, repeated typography patterns. Finding DRY after implementation is expensive — find it now. ## Phase 5: Implement a Section -For the section you are implementing: - -1. **Re-read the catalogue** — find its node ID. -2. **Sanity-check the catalogue entry.** Take a screenshot and verify the visual content matches the catalogue description. If it doesn't match, re-catalogue that entry before proceeding. -3. **Check whether the target node is a sub-component.** If the node name suggests it is a sub-component rather than a full section (e.g. `PieChart`, `Icon`, `Card`, `Button`) — fetch the **parent node's metadata** before implementing. Labels, callouts, and decorators that visually belong to the sub-component are often siblings in the parent, not children of the sub-component node. Implement the smallest container that includes all visually related siblings. -4. **Screenshot first, design context only if needed.** Take a screenshot of the section. If the section doesn't exist yet in the codebase, proceed to fetch design context. If it does exist, compare the screenshot to the current implementation visually — only fetch `get_design_context` if you spot a discrepancy that needs exact values to resolve. -4. **Fetch design context when needed:** - ``` - get_design_context(fileKey, sectionNodeId) - ``` - This returns reference code (React + Tailwind), a screenshot, and design values. It is a **reference, not final code** — adapt it to the project's stack, conventions, and existing components. -5. **Extract from the response:** +1. Re-read the catalogue — find the node ID. +2. Sanity-check: screenshot the node, verify it matches the catalogue description. Re-catalogue if wrong. +3. **Sub-component check:** If the node is a sub-component (e.g. `PieChart`, `Card`, `Button`), fetch the **parent node's metadata** first — labels and decorators are often siblings, not children. +4. Screenshot first. Fetch `get_design_context` only if you spot a discrepancy needing exact values. +5. From `get_design_context`, extract: - Layout: direction, alignment, padding, gap, max-width - - Background: colour, gradient stops, image references - - **All text content** — copy every text node's exact string. Screenshots can't catch copy mismatches. Cross-check text content in the code (and in the project's config/data layer — see note below) against these strings. + - Background: colour, gradient stops, image refs + - **All text content** — copy every text node exactly. Screenshots can't catch copy mismatches. - Interactive elements: button labels, variants, states - - Decorative/structural elements: asset URLs, connector lines, dividers, positions - - Responsive variants: look for Mobile / Tablet / Desktop frames -6. **Check the config/data layer.** If the project separates copy or data into a config file (e.g. `site-config.ts`) or CMS, check that layer against Figma's text nodes — not just the component output. A copy mismatch may live entirely in config, invisible in the JSX. -7. **Download assets immediately after fetching design context — before writing any code.** `get_design_context` returns `figma.com/api/mcp/asset/...` URLs that expire in 7 days. Each new call to `get_design_context` (including for a parent or sibling node) returns *new* URLs for the same assets — do not mix URLs from different fetches. Download immediately from the URLs in the response you are currently working with, before touching the codebase. Classify each URL by purpose: - - **Images** (photos, illustrations, coin graphics) → `curl -o public/images/[name].[ext] "[url]"` — use descriptive filenames, not UUIDs - - **Icons** (SVG) → `curl -o public/icons/[name].svg "[url]"` — check if an equivalent already exists in the project before downloading - - **Structural elements** (connector lines, dividers, borders, decorative shapes) → **do not download** — reconstruct with CSS (`border`, `background: linear-gradient(...)`, inline SVG). Never use an expiring asset URL for a UI element. - - **Existing committed static asset** (e.g. `pie-chart.png`) approximating a Figma vector → this is a sign the original implementation bypassed this skill. The correct implementation is CSS reconstruction. Verify visual equivalence for now, but flag it as technical debt to be replaced with a proper CSS implementation. - - After downloading, reference committed paths in code — never the Figma asset URL. -8. **Cross-reference** every colour and spacing value against the existing design system (Tailwind config, CSS variables, existing components) before adding new tokens. -9. **Check DRY opportunities** from the catalogue — use or extend shared components/classes. -10. **Shared component fidelity:** If a shared component (e.g. ``) can't express the Figma layout for this specific section (e.g. inline vs. stacked text), inline the markup for that section. **Fidelity to the Figma takes precedence over reusing a shared component** when they conflict. Do not distort the layout to fit the component. -11. **Batch edits, then verify once.** Make all your edits for the section, then run typecheck/build once at the end. Do not run typecheck after each individual edit unless an edit is likely to introduce a type error you need to diagnose immediately. + - Decorative elements: asset URLs, connector lines, dividers, positions + - Responsive variants: Mobile / Tablet / Desktop frames +6. **Check the config/data layer** (e.g. `site-config.ts`) for copy — a mismatch may live entirely in config, invisible in JSX. +7. **Download assets immediately after fetching design context — before writing any code.** Asset URLs (`figma.com/api/mcp/asset/...`) expire in 7 days. Each new `get_design_context` call returns new URLs — do not mix URLs from different fetches. + - Images/illustrations → `curl -o public/images/[name].[ext] "[url]"` + - Icons (SVG) → `curl -o public/icons/[name].svg "[url]"` — check for existing equivalents first + - Structural elements (connector lines, dividers, shapes) → **do not download** — reconstruct with CSS (`border`, `linear-gradient`, inline SVG). Never use expiring URLs for UI elements. + - A static asset approximating a Figma vector is technical debt — flag it; correct impl is CSS. +8. Cross-reference every colour and spacing value against the existing design system before adding new tokens. +9. Apply DRY opportunities from the catalogue. +10. **Fidelity over DRY:** If a shared component can't express the Figma layout, inline the markup. Don't distort layout to fit a component. +11. Batch all edits, then run typecheck/build once at the end. +12. **REQUIRED — Visual gate. Do not move on until this is done:** + - Navigate and screenshot the live browser: `mcp__chrome-devtools__navigate_page(url: "http://localhost:3000")` then `mcp__chrome-devtools__take_screenshot()` + - Crop to the section — read its bounding box: `mcp__chrome-devtools__evaluate_script(script: "JSON.stringify(document.querySelector('[data-section=\"NAME\"]').getBoundingClientRect())")` + - Fetch the Figma screenshot for the same node: `get_screenshot(fileKey, sectionNodeId)` + - Diff the two. Triage using the priority order in Phase 7d. **Fix all layout, copy, and missing-element issues before proceeding to the next section.** ## Phase 6: Zooming Into Child Nodes -If a section is complex or a value is unclear: - ``` -get_screenshot(fileKey, childNodeId) — visual confirmation (cheap, do this first) -get_design_context(fileKey, childNodeId) — exact values and reference code (only if needed) +get_screenshot(fileKey, childNodeId) — visual confirmation first (cheap) +get_design_context(fileKey, childNodeId) — exact values only if needed ``` -**If a section contains repeated similar elements** (e.g. multiple connector lines, multiple cards, multiple icons that may differ): screenshot each child node individually to confirm their styles before implementing. The reference code from `get_design_context` may flatten similar elements into a single container, hiding style differences between them. - -**Watch for Figma coordinate artefacts.** The reference code from `get_design_context` is a direct translation of Figma's internal layout maths. Certain patterns only work correctly at the original design dimensions and will break at other sizes: +For repeated similar elements (connector lines, cards, icons): screenshot each child individually — `get_design_context` may flatten them, hiding style differences. -| Artefact | Example | Risk | -|----------|---------|------| -| Percentage insets on absolute elements | `inset: "6.52% 3.42%"` | Collapses if parent has no explicit size | -| Negative insets exceeding 100% | `inset: "-102.42% -72.65%"` | Overflows or clips at different sizes | -| `calc()` with large px offsets | `left: calc(50% + 227.91px)` | Breaks at narrower containers | -| Pixel positions referencing parent size | `top: -220.86px` | Only valid at the exact original height | +**Watch for Figma coordinate artefacts** — these only work at the original design dimensions: +| Artefact | Risk | +|----------|------| +| Percentage insets on absolute elements (`inset: "6.52% 3.42%"`) | Collapses without explicit parent size | +| Negative insets >100% (`inset: "-102.42% -72.65%"`) | Overflows at different sizes | +| `calc()` with large px offsets (`left: calc(50% + 227.91px)`) | Breaks at narrower containers | +| Pixel positions referencing parent size (`top: -220.86px`) | Only valid at exact original height | -When you encounter these patterns: verify that the parent container has an explicit fixed size matching Figma's dimensions, or convert to values that will work at the target render size. - -Child node IDs are visible in `get_metadata` output and in Figma's URL when you click an element in dev mode. Do not guess values — re-fetch the specific node. +Verify parent has an explicit fixed size matching Figma dimensions, or convert to size-safe values. ## Phase 7: Audit Mode -Use this when checking an existing implementation for Figma fidelity, rather than building from scratch. - ### 7a. Read the existing implementation first -Before fetching anything from Figma, read all relevant source files — components, views, and the config/data layer. Build a mental model of what the code currently produces. +Read all relevant source files — components, views, config/data layer — before fetching from Figma. ### 7b. Screenshot all sections in parallel -Using the node IDs from the catalogue, fetch screenshots of all sections at once: - ``` -get_screenshot(fileKey, sectionNodeId) — all sections in parallel +get_screenshot(fileKey, sectionNodeId) — all sections at once ``` -Do not fetch `get_design_context` yet — screenshots are cheap and may be sufficient to confirm sections are correct. - -### 7c. Build a diff list before touching any code - -Compare each section screenshot against the current implementation. For each section, classify: -- **Correct** — no action needed -- **Layout deviation** — wrong spacing, alignment, sizing -- **Copy mismatch** — text content differs (screenshots won't show this — cross-check text nodes separately) -- **Missing element** — Figma has something the implementation lacks -- **Wrong element** — implementation has something Figma doesn't - -Only fetch `get_design_context` for sections with layout deviations that need exact values. Sections confirmed correct by screenshot need no further Figma fetching. - -### 7d. Triage before editing - -Not all deviations are worth fixing. Use this priority order: -1. **Wrong layout or structure** — fix immediately -2. **Wrong copy** — fix immediately -3. **Missing element** — fix immediately -4. **Minor spacing deviation** (1–4px off) — fix if it's visible; skip if it's within Tailwind's scale rounding -5. **Pixel-perfect padding differences** that don't affect the visual feel — skip - -### 7e. Batch all edits, then verify once - -Make all fixes across all sections, then run typecheck/build once. Update the catalogue if any section's description was wrong. - -## What NOT to Do - -| Bad | Good | -|-----|------| -| Fetch `0:1` (page root) — returns entire file tree | Start from the URL's `node-id` — it's the right frame | -| Read large metadata results into main context | Use a subagent to parse oversized responses | -| Name sections from visual guesses or screenshots when layer names exist | Use the Figma XML `name` attribute — it's authoritative | -| Use layer names when frames are generically named (e.g. `Frame 168…`) | Screenshot each child first — visual content is your only reliable naming signal | -| Screenshot only the full page to identify sections | Screenshot each section individually — thumbnail is too small | -| Trust catalogue entry without sanity-checking | Verify node ID + visual content before implementing | -| Fetch `get_design_context` for every section upfront | Screenshot first — only fetch design context when a discrepancy needs exact values | -| Ignore copy when checking visual fidelity | Cross-check all text nodes explicitly — screenshots can't catch copy mismatches | -| Check only component JSX for copy accuracy | Also check the config/data layer (e.g. site-config.ts) — copy may live there | -| Leave Figma asset URLs in code | Download all images/icons and commit before writing any code | -| Use expiring Figma asset URLs for connector lines or dividers | Reconstruct structural elements with CSS | -| Treat a static asset approximating a Figma vector as acceptable long-term | Flag it as technical debt — correct implementation is CSS reconstruction | -| Assume repeated elements (lines, cards) are identical | Screenshot each child to confirm — they may differ | -| Force a shared component to fit a section's layout | Inline the markup when fidelity and DRY conflict | -| Hardcode a colour without checking existing tokens | Cross-reference every value against the design system | -| Run typecheck after every individual edit | Batch all edits, then verify compilation once at the end | -| Re-fetch root metadata when a section is missing from the catalogue | Screenshot the root node first — visually check if it exists | -| Implement a section not found in Figma | Ask the user for the specific node URL rather than guessing | -| Implement a sub-component node in isolation (e.g. `PieChart`) | Fetch parent metadata first — labels and callouts are often siblings, not children | -| Download assets from one `get_design_context` call then re-fetch the node (or its parent) before writing code | Download immediately after each fetch — new calls return new URLs; do not mix | -| Use percentage insets, negative insets >100%, or `calc()` with large px offsets without checking parent size | Verify parent has an explicit fixed size matching Figma dimensions, or convert to size-safe values | - -## Catalogue File Location - -`.figma/[fileKey].md` — relative to the project root. - -- Lives inside the project so CK Search indexes it; agents can query it semantically rather than reading the whole file -- Listed in `.gitignore` — not committed, since it's generated and may go stale as the Figma evolves -- Survives reboots (unlike `/tmp/`), so the cataloguing cost is paid once per machine per project -- Written in Phase 4, read in Phases 5 and 7; multiple agents share it without re-fetching - -**On first use in a project:** create the directory with `mkdir -p .figma/` before writing the catalogue. +### 7c. Build a diff list before touching code + +For each section: **Correct** / **Layout deviation** / **Copy mismatch** / **Missing element** / **Wrong element**. + +Only fetch `get_design_context` for sections with layout deviations needing exact values. + +### 7d. Triage priority + +1. Wrong layout or structure — fix immediately +2. Wrong copy — fix immediately +3. Missing element — fix immediately +4. Minor spacing deviation (1–4px) — fix if visible; skip if within Tailwind rounding +5. Pixel-perfect padding differences with no visual impact — skip + +### 7e. Batch all edits, verify once + +Make all fixes, then run typecheck/build once. Update catalogue if any description was wrong. + +## Catalogue File + +`.figma/[fileKey].md` — relative to project root. +- Add to `.gitignore` — generated, may go stale +- `mkdir -p .figma/` on first use in a project +- Shared across agents — avoids re-fetching + +## Key Rules (do / don't) + +| Don't | Do | +|-------|----| +| Fetch `0:1` (page root) | Start from URL's `node-id` | +| Call `get_metadata` in main session | Route through subagent | +| Name sections from visual guesses when layer names exist | Use XML `name` attribute | +| Use layer names when frames are generic | Screenshot each child; name from visual content | +| Fetch `get_design_context` for every section upfront | Screenshot first; escalate only for discrepancies | +| Ignore copy when checking visual fidelity | Cross-check all text nodes explicitly | +| Check only component JSX for copy | Also check config/data layer | +| Leave Figma asset URLs in code | Download and commit before writing code | +| Use expiring URLs for connector lines/dividers | Reconstruct with CSS | +| Assume repeated elements are identical | Screenshot each child to confirm | +| Force a shared component to fit the layout | Inline markup when fidelity and DRY conflict | +| Hardcode a colour without checking tokens | Cross-reference against design system | +| Run typecheck after each edit | Batch edits; verify once at the end | +| Re-fetch root metadata for a missing section | Screenshot root first to visually search | +| Implement a section not found in Figma | Ask user for the specific node URL | +| Implement a sub-component node in isolation | Fetch parent metadata first | +| Re-fetch a node before downloading assets | Download immediately after each fetch | +| Move on without visual verification | Step 12 is a hard gate — screenshot, compare, fix HIGH priority issues first | From 050bea1183357825427fec09d48794ae721e0855 Mon Sep 17 00:00:00 2001 From: Barry Earsman Date: Sun, 26 Apr 2026 20:52:58 +1000 Subject: [PATCH 04/14] feat: tighten visual QA in figma-driven-development skill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Delegate screenshot comparison to a skeptical subagent in both Phase 5 and Phase 7, with an explicit adversarial prompt covering 13 diff categories including gradients, charts, and visual effects - Warn not to assume asset file format — check content-type before downloading, as Figma images are frequently SVGs Co-Authored-By: Claude Sonnet 4.6 --- skills/figma-driven-development/SKILL.md | 51 +++++++++++++++++++++--- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/skills/figma-driven-development/SKILL.md b/skills/figma-driven-development/SKILL.md index d21948e..2fb0c2c 100644 --- a/skills/figma-driven-development/SKILL.md +++ b/skills/figma-driven-development/SKILL.md @@ -103,7 +103,8 @@ Before implementing, scan for: repeated background layers, shared button variant - Responsive variants: Mobile / Tablet / Desktop frames 6. **Check the config/data layer** (e.g. `site-config.ts`) for copy — a mismatch may live entirely in config, invisible in JSX. 7. **Download assets immediately after fetching design context — before writing any code.** Asset URLs (`figma.com/api/mcp/asset/...`) expire in 7 days. Each new `get_design_context` call returns new URLs — do not mix URLs from different fetches. - - Images/illustrations → `curl -o public/images/[name].[ext] "[url]"` + - **Do not assume file format from context** — inspect the URL or run `curl -sI "[url]" | grep content-type` to confirm. Figma assets labelled as images are frequently SVGs, not PNGs or JPEGs. + - Images/illustrations → `curl -o public/images/[name].[ext] "[url]"` (use confirmed extension, e.g. `.svg`, `.png`, `.jpg`) - Icons (SVG) → `curl -o public/icons/[name].svg "[url]"` — check for existing equivalents first - Structural elements (connector lines, dividers, shapes) → **do not download** — reconstruct with CSS (`border`, `linear-gradient`, inline SVG). Never use expiring URLs for UI elements. - A static asset approximating a Figma vector is technical debt — flag it; correct impl is CSS. @@ -115,7 +116,28 @@ Before implementing, scan for: repeated background layers, shared button variant - Navigate and screenshot the live browser: `mcp__chrome-devtools__navigate_page(url: "http://localhost:3000")` then `mcp__chrome-devtools__take_screenshot()` - Crop to the section — read its bounding box: `mcp__chrome-devtools__evaluate_script(script: "JSON.stringify(document.querySelector('[data-section=\"NAME\"]').getBoundingClientRect())")` - Fetch the Figma screenshot for the same node: `get_screenshot(fileKey, sectionNodeId)` - - Diff the two. Triage using the priority order in Phase 7d. **Fix all layout, copy, and missing-element issues before proceeding to the next section.** + - **Delegate the visual diff to a skeptical subagent.** Do not review it yourself — your first pass will miss things. Spawn an Agent with the following prompt, passing both screenshots as context: + + > You are a meticulous visual QA reviewer. Your job is to find mistakes — assume they are there, because they almost always are. You will be shown two images: a Figma design and a browser implementation. Your disposition is skeptical and critical. Do not give the benefit of the doubt. + > + > Go through every category below. For each one, describe what you see in both images and call out any discrepancy, no matter how small: + > - **Layout**: flex direction, alignment (horizontal and vertical), gap, padding, margin — compare every axis + > - **Typography**: font size, weight, line height, letter spacing, colour, text-transform, text-decoration — read each text node character by character + > - **Copy**: every word, punctuation mark, and line break — do not skim + > - **Colour**: backgrounds, borders, text, icon fills — flag anything that looks even slightly off + > - **Spacing**: internal padding, gaps between elements, outer margins + > - **Sizing**: widths, heights, aspect ratios — flag anything that looks proportionally off + > - **Borders & shadows**: radius, width, colour, box-shadow offsets and blur + > - **Visual effects**: gradients (direction, stops, colours), opacity, blur, overlay effects — these are the most commonly wrong + > - **Charts & data visualisations**: bar heights, line paths, colours, labels, axes, legends — treat every detail as suspect + > - **Icons & images**: correct asset, correct size, correct colour/fill, correct orientation + > - **Missing elements**: scan the Figma image for anything absent from the browser — decorative lines, badges, indicators, overlays, subtle background patterns + > - **Extra elements**: scan the browser image for anything not present in Figma + > - **Responsive state**: confirm the viewport matches the intended breakpoint variant + > + > Output a numbered diff list. An empty list is almost certainly wrong — if you find nothing, re-examine. Justify an empty list explicitly. + + - Read the subagent's diff list. Triage using the priority order in Phase 7d. **Fix all layout, copy, and missing-element issues before proceeding to the next section.** ## Phase 6: Zooming Into Child Nodes @@ -150,9 +172,28 @@ get_screenshot(fileKey, sectionNodeId) — all sections at once ### 7c. Build a diff list before touching code -For each section: **Correct** / **Layout deviation** / **Copy mismatch** / **Missing element** / **Wrong element**. - -Only fetch `get_design_context` for sections with layout deviations needing exact values. +**Delegate the visual diff to a skeptical subagent — do not review it yourself.** Spawn an Agent per section (run in parallel) with the following prompt, passing both the Figma screenshot and the browser screenshot as context: + +> You are a meticulous visual QA reviewer. Your job is to find mistakes — assume they are there, because they almost always are. You will be shown two images: a Figma design and a browser implementation. Your disposition is skeptical and critical. Do not give the benefit of the doubt. +> +> Go through every category below. For each one, describe what you see in both images and call out any discrepancy, no matter how small: +> - **Layout**: flex direction, alignment (horizontal and vertical), gap, padding, margin — compare every axis +> - **Typography**: font size, weight, line height, letter spacing, colour, text-transform, text-decoration — read each text node character by character +> - **Copy**: every word, punctuation mark, and line break — do not skim +> - **Colour**: backgrounds, borders, text, icon fills — flag anything that looks even slightly off +> - **Spacing**: internal padding, gaps between elements, outer margins +> - **Sizing**: widths, heights, aspect ratios — flag anything that looks proportionally off +> - **Borders & shadows**: radius, width, colour, box-shadow offsets and blur +> - **Visual effects**: gradients (direction, stops, colours), opacity, blur, overlay effects — these are the most commonly wrong +> - **Charts & data visualisations**: bar heights, line paths, colours, labels, axes, legends — treat every detail as suspect +> - **Icons & images**: correct asset, correct size, correct colour/fill, correct orientation +> - **Missing elements**: scan the Figma image for anything absent from the implementation — decorative lines, badges, indicators, overlays, subtle background patterns +> - **Extra elements**: scan the implementation for anything not present in Figma +> - **Responsive state**: confirm the viewport matches the intended breakpoint variant +> +> Classify each finding: **Layout deviation** / **Copy mismatch** / **Missing element** / **Wrong element** / **Correct**. Output a numbered diff list. An empty list is almost certainly wrong — if you find nothing, re-examine. Justify an empty list explicitly. + +Only fetch `get_design_context` for sections where the subagent identified layout deviations needing exact values. ### 7d. Triage priority From 235668960a0bbc59fd2d8e948a01b6bc3e032dda Mon Sep 17 00:00:00 2001 From: Barry Earsman Date: Sun, 26 Apr 2026 21:20:37 +1000 Subject: [PATCH 05/14] feat: pass catalogue context to visual QA subagents Both Phase 5 and Phase 7 subagent prompts now include the section name, node ID, expected size, and catalogue description so subagents can anchor their diff against what was documented, and flag missing elements with confidence. Co-Authored-By: Claude Sonnet 4.6 --- skills/figma-driven-development/SKILL.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/skills/figma-driven-development/SKILL.md b/skills/figma-driven-development/SKILL.md index 2fb0c2c..5a70345 100644 --- a/skills/figma-driven-development/SKILL.md +++ b/skills/figma-driven-development/SKILL.md @@ -116,10 +116,18 @@ Before implementing, scan for: repeated background layers, shared button variant - Navigate and screenshot the live browser: `mcp__chrome-devtools__navigate_page(url: "http://localhost:3000")` then `mcp__chrome-devtools__take_screenshot()` - Crop to the section — read its bounding box: `mcp__chrome-devtools__evaluate_script(script: "JSON.stringify(document.querySelector('[data-section=\"NAME\"]').getBoundingClientRect())")` - Fetch the Figma screenshot for the same node: `get_screenshot(fileKey, sectionNodeId)` - - **Delegate the visual diff to a skeptical subagent.** Do not review it yourself — your first pass will miss things. Spawn an Agent with the following prompt, passing both screenshots as context: + - **Delegate the visual diff to a skeptical subagent.** Do not review it yourself — your first pass will miss things. Spawn an Agent with the following prompt, passing both screenshots and the catalogue entry for this section as context: > You are a meticulous visual QA reviewer. Your job is to find mistakes — assume they are there, because they almost always are. You will be shown two images: a Figma design and a browser implementation. Your disposition is skeptical and critical. Do not give the benefit of the doubt. > + > **Section context from the Figma catalogue:** + > - Section name: [name from catalogue] + > - Node ID: [nodeId] + > - Expected size: [width×height from catalogue] + > - Catalogue description: [description field verbatim] + > + > Use this context to understand what elements should be present and to anchor your diff. If the implementation is missing something the catalogue describes, that is a confirmed missing element. + > > Go through every category below. For each one, describe what you see in both images and call out any discrepancy, no matter how small: > - **Layout**: flex direction, alignment (horizontal and vertical), gap, padding, margin — compare every axis > - **Typography**: font size, weight, line height, letter spacing, colour, text-transform, text-decoration — read each text node character by character @@ -176,6 +184,14 @@ get_screenshot(fileKey, sectionNodeId) — all sections at once > You are a meticulous visual QA reviewer. Your job is to find mistakes — assume they are there, because they almost always are. You will be shown two images: a Figma design and a browser implementation. Your disposition is skeptical and critical. Do not give the benefit of the doubt. > +> **Section context from the Figma catalogue:** +> - Section name: [name from catalogue] +> - Node ID: [nodeId] +> - Expected size: [width×height from catalogue] +> - Catalogue description: [description field verbatim] +> +> Use this context to understand what elements should be present and to anchor your diff. If the implementation is missing something the catalogue describes, that is a confirmed missing element. +> > Go through every category below. For each one, describe what you see in both images and call out any discrepancy, no matter how small: > - **Layout**: flex direction, alignment (horizontal and vertical), gap, padding, margin — compare every axis > - **Typography**: font size, weight, line height, letter spacing, colour, text-transform, text-decoration — read each text node character by character From a6ff0b906a67df2a82723d94b1e47283330d7f79 Mon Sep 17 00:00:00 2001 From: Barry Earsman Date: Sun, 26 Apr 2026 21:45:59 +1000 Subject: [PATCH 06/14] feat: warn QA subagents about scale errors in visual diff Adds a prominent scale warning to both Phase 5 and Phase 7 subagent prompts, and elevates sizing to a high-risk category with an explicit proportional comparison check. Co-Authored-By: Claude Sonnet 4.6 --- skills/figma-driven-development/SKILL.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/skills/figma-driven-development/SKILL.md b/skills/figma-driven-development/SKILL.md index 5a70345..7f41e38 100644 --- a/skills/figma-driven-development/SKILL.md +++ b/skills/figma-driven-development/SKILL.md @@ -128,13 +128,15 @@ Before implementing, scan for: repeated background layers, shared button variant > > Use this context to understand what elements should be present and to anchor your diff. If the implementation is missing something the catalogue describes, that is a confirmed missing element. > + > **Scale warning:** Scale errors are extremely common and easy to miss — elements that are too small, too large, or incorrectly proportioned relative to their surroundings. Do not trust that something "looks about right." Actively compare the relative size of every element (icons, images, text blocks, buttons, cards) against the Figma design. Ask yourself: does this element occupy the same proportion of the section as it does in the design? + > > Go through every category below. For each one, describe what you see in both images and call out any discrepancy, no matter how small: > - **Layout**: flex direction, alignment (horizontal and vertical), gap, padding, margin — compare every axis > - **Typography**: font size, weight, line height, letter spacing, colour, text-transform, text-decoration — read each text node character by character > - **Copy**: every word, punctuation mark, and line break — do not skim > - **Colour**: backgrounds, borders, text, icon fills — flag anything that looks even slightly off > - **Spacing**: internal padding, gaps between elements, outer margins - > - **Sizing**: widths, heights, aspect ratios — flag anything that looks proportionally off + > - **Scale & sizing**: widths, heights, aspect ratios — this is a high-risk category. Elements are frequently too small or too large. Compare proportions carefully against the Figma design, not just against your expectations. > - **Borders & shadows**: radius, width, colour, box-shadow offsets and blur > - **Visual effects**: gradients (direction, stops, colours), opacity, blur, overlay effects — these are the most commonly wrong > - **Charts & data visualisations**: bar heights, line paths, colours, labels, axes, legends — treat every detail as suspect @@ -192,13 +194,15 @@ get_screenshot(fileKey, sectionNodeId) — all sections at once > > Use this context to understand what elements should be present and to anchor your diff. If the implementation is missing something the catalogue describes, that is a confirmed missing element. > +> **Scale warning:** Scale errors are extremely common and easy to miss — elements that are too small, too large, or incorrectly proportioned relative to their surroundings. Do not trust that something "looks about right." Actively compare the relative size of every element (icons, images, text blocks, buttons, cards) against the Figma design. Ask yourself: does this element occupy the same proportion of the section as it does in the design? +> > Go through every category below. For each one, describe what you see in both images and call out any discrepancy, no matter how small: > - **Layout**: flex direction, alignment (horizontal and vertical), gap, padding, margin — compare every axis > - **Typography**: font size, weight, line height, letter spacing, colour, text-transform, text-decoration — read each text node character by character > - **Copy**: every word, punctuation mark, and line break — do not skim > - **Colour**: backgrounds, borders, text, icon fills — flag anything that looks even slightly off > - **Spacing**: internal padding, gaps between elements, outer margins -> - **Sizing**: widths, heights, aspect ratios — flag anything that looks proportionally off +> - **Scale & sizing**: widths, heights, aspect ratios — this is a high-risk category. Elements are frequently too small or too large. Compare proportions carefully against the Figma design, not just against your expectations. > - **Borders & shadows**: radius, width, colour, box-shadow offsets and blur > - **Visual effects**: gradients (direction, stops, colours), opacity, blur, overlay effects — these are the most commonly wrong > - **Charts & data visualisations**: bar heights, line paths, colours, labels, axes, legends — treat every detail as suspect From d298c9e8f4c69861576ba4f903f18e059c3f5ac6 Mon Sep 17 00:00:00 2001 From: Barry Earsman Date: Sun, 26 Apr 2026 21:52:40 +1000 Subject: [PATCH 07/14] feat: complexity-based multi-pass QA for visual diff subagents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before handing off to the skeptical subagent, the implementing agent now scores section complexity 1–3 and runs the subagent that many times sequentially. Each pass receives the cumulative findings from prior passes and is instructed to re-examine independently, not just confirm. Applied to both Phase 5 (visual gate) and Phase 7 (audit). Co-Authored-By: Claude Sonnet 4.6 --- skills/figma-driven-development/SKILL.md | 40 +++++++++++++++++++++--- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/skills/figma-driven-development/SKILL.md b/skills/figma-driven-development/SKILL.md index 7f41e38..d8a460a 100644 --- a/skills/figma-driven-development/SKILL.md +++ b/skills/figma-driven-development/SKILL.md @@ -116,7 +116,19 @@ Before implementing, scan for: repeated background layers, shared button variant - Navigate and screenshot the live browser: `mcp__chrome-devtools__navigate_page(url: "http://localhost:3000")` then `mcp__chrome-devtools__take_screenshot()` - Crop to the section — read its bounding box: `mcp__chrome-devtools__evaluate_script(script: "JSON.stringify(document.querySelector('[data-section=\"NAME\"]').getBoundingClientRect())")` - Fetch the Figma screenshot for the same node: `get_screenshot(fileKey, sectionNodeId)` - - **Delegate the visual diff to a skeptical subagent.** Do not review it yourself — your first pass will miss things. Spawn an Agent with the following prompt, passing both screenshots and the catalogue entry for this section as context: + - **Before spawning the QA subagent, assess review complexity** and assign a pass count (1–3): + + | Score | Criteria | Passes | + |-------|----------|--------| + | 1 — Simple | Mostly text and basic layout; few or no images, charts, gradients, or overlapping elements | 1 | + | 2 — Moderate | Mix of text and visual elements; some gradients, icons, images, or layered components | 2 | + | 3 — Complex | Data visualisations, charts, complex gradients, overlapping layers, many small elements, dense information, or anything that challenges AI vision models | 3 | + + State your score and reasoning before proceeding. + + - **Spawn the QA subagent N times sequentially** (where N = your pass count). Each pass receives the same two screenshots and catalogue context, plus a growing cumulative diff list from prior passes. Instruct each pass to: (a) re-examine everything independently, not just confirm prior findings; (b) specifically hunt for issues the prior pass may have missed; (c) add new findings to the cumulative list without removing prior ones. + + Subagent prompt (adapt for pass number — pass 1 has no prior findings; passes 2+ include them): > You are a meticulous visual QA reviewer. Your job is to find mistakes — assume they are there, because they almost always are. You will be shown two images: a Figma design and a browser implementation. Your disposition is skeptical and critical. Do not give the benefit of the doubt. > @@ -128,6 +140,10 @@ Before implementing, scan for: repeated background layers, shared button variant > > Use this context to understand what elements should be present and to anchor your diff. If the implementation is missing something the catalogue describes, that is a confirmed missing element. > + > **[Pass 2/3 only] Prior findings to build on:** + > [paste cumulative diff list from previous passes] + > Do NOT simply confirm these — re-examine the images independently first. Then add any new findings. Prior findings may also be wrong; correct them if needed. + > > **Scale warning:** Scale errors are extremely common and easy to miss — elements that are too small, too large, or incorrectly proportioned relative to their surroundings. Do not trust that something "looks about right." Actively compare the relative size of every element (icons, images, text blocks, buttons, cards) against the Figma design. Ask yourself: does this element occupy the same proportion of the section as it does in the design? > > Go through every category below. For each one, describe what you see in both images and call out any discrepancy, no matter how small: @@ -145,9 +161,9 @@ Before implementing, scan for: repeated background layers, shared button variant > - **Extra elements**: scan the browser image for anything not present in Figma > - **Responsive state**: confirm the viewport matches the intended breakpoint variant > - > Output a numbered diff list. An empty list is almost certainly wrong — if you find nothing, re-examine. Justify an empty list explicitly. + > Output a numbered diff list (cumulative across all passes). An empty list is almost certainly wrong — if you find nothing, re-examine. Justify an empty list explicitly. - - Read the subagent's diff list. Triage using the priority order in Phase 7d. **Fix all layout, copy, and missing-element issues before proceeding to the next section.** + - After all passes, merge findings into a final cumulative diff list. Triage using the priority order in Phase 7d. **Fix all layout, copy, and missing-element issues before proceeding to the next section.** ## Phase 6: Zooming Into Child Nodes @@ -182,7 +198,17 @@ get_screenshot(fileKey, sectionNodeId) — all sections at once ### 7c. Build a diff list before touching code -**Delegate the visual diff to a skeptical subagent — do not review it yourself.** Spawn an Agent per section (run in parallel) with the following prompt, passing both the Figma screenshot and the browser screenshot as context: +**Delegate the visual diff to a skeptical subagent — do not review it yourself.** + +For each section, first assess review complexity and assign a pass count (1–3): + +| Score | Criteria | Passes | +|-------|----------|--------| +| 1 — Simple | Mostly text and basic layout; few or no images, charts, gradients, or overlapping elements | 1 | +| 2 — Moderate | Mix of text and visual elements; some gradients, icons, images, or layered components | 2 | +| 3 — Complex | Data visualisations, charts, complex gradients, overlapping layers, many small elements, dense information, or anything that challenges AI vision models | 3 | + +Spawn sections in parallel (one pipeline per section), but within each section run passes **sequentially** — each pass feeds its findings into the next. Subagent prompt (adapt for pass number): > You are a meticulous visual QA reviewer. Your job is to find mistakes — assume they are there, because they almost always are. You will be shown two images: a Figma design and a browser implementation. Your disposition is skeptical and critical. Do not give the benefit of the doubt. > @@ -194,6 +220,10 @@ get_screenshot(fileKey, sectionNodeId) — all sections at once > > Use this context to understand what elements should be present and to anchor your diff. If the implementation is missing something the catalogue describes, that is a confirmed missing element. > +> **[Pass 2/3 only] Prior findings to build on:** +> [paste cumulative diff list from previous passes] +> Do NOT simply confirm these — re-examine the images independently first. Then add any new findings. Prior findings may also be wrong; correct them if needed. +> > **Scale warning:** Scale errors are extremely common and easy to miss — elements that are too small, too large, or incorrectly proportioned relative to their surroundings. Do not trust that something "looks about right." Actively compare the relative size of every element (icons, images, text blocks, buttons, cards) against the Figma design. Ask yourself: does this element occupy the same proportion of the section as it does in the design? > > Go through every category below. For each one, describe what you see in both images and call out any discrepancy, no matter how small: @@ -211,7 +241,7 @@ get_screenshot(fileKey, sectionNodeId) — all sections at once > - **Extra elements**: scan the implementation for anything not present in Figma > - **Responsive state**: confirm the viewport matches the intended breakpoint variant > -> Classify each finding: **Layout deviation** / **Copy mismatch** / **Missing element** / **Wrong element** / **Correct**. Output a numbered diff list. An empty list is almost certainly wrong — if you find nothing, re-examine. Justify an empty list explicitly. +> Classify each finding: **Layout deviation** / **Copy mismatch** / **Missing element** / **Wrong element** / **Correct**. Output a cumulative numbered diff list. An empty list is almost certainly wrong — if you find nothing, re-examine. Justify an empty list explicitly. Only fetch `get_design_context` for sections where the subagent identified layout deviations needing exact values. From d96aeb62879ecfd2fa0391c1484ed1f435475b9f Mon Sep 17 00:00:00 2001 From: Barry Earsman Date: Mon, 27 Apr 2026 12:18:32 +1000 Subject: [PATCH 08/14] feat: enrich figma catalogue with code, split into per-section files - Catalogue now stores CSS layout, typography tables, colour tokens, spacing, component mappings, assets, copy, interactive states, transitions, responsive variants, and complexity/error-likelihood scores - Split catalogue into index + shared-styles + per-section files so each subagent loads only what it needs - QA subagent prompts adapt analysis depth based on complexity score (score 3 triggers quadrant decomposition, per-element chart checks, etc.) - Trimmed Key Rules table to a compact Hard Rules list; collapsed verbose gate explanation Co-Authored-By: Claude Sonnet 4.6 --- CLAUDE.md | 37 +++ skills/figma-driven-development/SKILL.md | 356 ++++++++++++++++++----- 2 files changed, 315 insertions(+), 78 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index dd57f97..02794af 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -49,3 +49,40 @@ When modifying this repo: - Skills should be self-contained instructions that work without user interaction where possible - Agents should encode domain knowledge that would take multiple files to discover, not generic advice - Keep specialist agents in `agents/example-specialists/` to separate them from the generic set + + +## CodeGraph + +CodeGraph builds a semantic knowledge graph of codebases for faster, smarter code exploration. + +### If `.codegraph/` exists in the project + +**Use codegraph tools for faster exploration.** These tools provide instant lookups via the code graph instead of scanning files: + +| Tool | Use For | +|------|---------| +| `codegraph_search` | Find symbols by name (functions, classes, types) | +| `codegraph_context` | Get relevant code context for a task | +| `codegraph_callers` | Find what calls a function | +| `codegraph_callees` | Find what a function calls | +| `codegraph_impact` | See what's affected by changing a symbol | +| `codegraph_node` | Get details + source code for a symbol | + +**When spawning Explore agents in a codegraph-enabled project:** + +Tell the Explore agent to use codegraph tools for faster exploration. + +**For quick lookups in the main session:** +- Use `codegraph_search` instead of grep for finding symbols +- Use `codegraph_callers`/`codegraph_callees` to trace code flow +- Use `codegraph_impact` before making changes to see what's affected + +### If `.codegraph/` does NOT exist + +At the start of a session, ask the user if they'd like to initialize CodeGraph: + +"I notice this project doesn't have CodeGraph initialized. Would you like me to run `codegraph init -i` to build a code knowledge graph?" + +# graphify +- **graphify** (`~/.claude/skills/graphify/SKILL.md`) - any input to knowledge graph. Trigger: `/graphify` +When the user types `/graphify`, invoke the Skill tool with `skill: "graphify"` before doing anything else. diff --git a/skills/figma-driven-development/SKILL.md b/skills/figma-driven-development/SKILL.md index d8a460a..97bd65f 100644 --- a/skills/figma-driven-development/SKILL.md +++ b/skills/figma-driven-development/SKILL.md @@ -33,14 +33,22 @@ Use the URL's `node-id` directly — it's the designer's intended frame. Never s ## Phase 3: Check for Existing Catalogue -Catalogue lives at `.figma/[fileKey].md`. +Catalogue index lives at `.figma/[fileKey].md`. Section files live at `.figma/[fileKey]/[section-slug].md`. Shared styles live at `.figma/[fileKey]/shared-styles.md`. -- **Exists + section present** → Phase 5 (build) or Phase 7 (audit) -- **Exists + section missing** → Check for naming mismatch first. Then `get_screenshot(fileKey, rootNodeId)` to visually search. If still not found, ask the user for the specific node URL — do not guess. +- **Index exists + section present** → Phase 5 (build) or Phase 7 (audit) +- **Index exists + section missing** → Check for naming mismatch first. Then `get_screenshot(fileKey, rootNodeId)` to visually search. If still not found, ask the user for the specific node URL — do not guess. - **Not exists** → Phase 4 ## Phase 4: Build the Catalogue +The catalogue is split into three file types so each subagent loads only what it needs: + +| File | Purpose | Who reads it | +|------|---------|--------------| +| `.figma/[fileKey].md` | Index: section list, node IDs, slugs, one-line descriptions | Every agent at the start | +| `.figma/[fileKey]/shared-styles.md` | CSS tokens, typography scale, shared spacing | Every implementation agent | +| `.figma/[fileKey]/[section-slug].md` | Full detail for one section: layout, colours, copy, assets | Only the agent implementing/auditing that section | + ### 4a. Fetch root metadata via subagent Always route `get_metadata` through a subagent — root frames for full pages predictably exceed context. Copy the exact file path from the tool result verbatim (UUID paths are easy to mistype). @@ -58,9 +66,9 @@ get_screenshot(fileKey, sectionNodeId) — one per section, all at once A full-page overview is too small to read — screenshot sections individually. -### 4c. Write the catalogue +### 4c. Write the catalogue index -Save to `.figma/[fileKey].md`: +Save to `.figma/[fileKey].md`. This file must stay small — it is loaded into every agent's context. No style values, no copy, no code blocks here. ```markdown # Figma Catalogue — [File Name] @@ -68,39 +76,219 @@ File key: [key] Root node: `[nodeId]` ("[name]" — [width]×[height]px) Catalogued: [date] +Shared styles: `.figma/[fileKey]/shared-styles.md` + ## Sections -### [Layer name] -- Node ID: `9936:51` -- Size: 1440×803px -- Description: [layout, key elements, purpose — from screenshot] -## Shared Styles -| Token | Observed value | Notes | -|-------|---------------|-------| -| Background | #?????? | Verify via get_design_context | -> Exact values must be confirmed by fetching design context. +| Section | Node ID | Size | Slug | Description | +|---------|---------|------|------|-------------| +| Hero | `9936:51` | 1440×803px | `hero` | Full-width hero with gradient background, heading, subheading, two CTAs, and hero illustration | +| Features | `9936:102` | 1440×960px | `features` | Three-column feature grid with icon cards | +| Pricing | `9936:188` | 1440×720px | `pricing` | Two-tier pricing cards with CTA buttons | ## DRY Opportunities -- **[Pattern]**: Appears in [Section A] ([nodeId]), [Section B] ([nodeId]) — candidate for `` or `.class` +- **[Pattern]**: Appears in [Section A] (`hero`), [Section B] (`features`) — candidate for `` or `.class` +``` + +### 4d. Write the shared styles file + +Save to `.figma/[fileKey]/shared-styles.md`. Include every value that appears in two or more sections. Values observed only from screenshots are flagged `[confirm]` — verify via `get_design_context` before use. + +```markdown +# Shared Styles — [File Name] +File key: [key] + +> Values marked `[confirm]` were observed from screenshots — verify exact values via get_design_context before use. + +## Colours +```css +--color-bg-primary: #0F0F1A; /* Page background */ +--color-bg-card: rgba(255,255,255,0.04); /* Card surface */ +--color-accent-start: #6C63FF; /* Gradient start [confirm] */ +--color-accent-end: #48CAE4; /* Gradient end [confirm] */ +--color-text-primary: #FFFFFF; +--color-text-secondary: #8B8BA7; +--color-border: rgba(255,255,255,0.08); +``` + +## Typography +```css +--font-family: 'Inter', sans-serif; +--text-xs: 12px / 16px; +--text-sm: 14px / 20px; +--text-base: 16px / 24px; +--text-lg: 20px / 28px; +--text-2xl: 24px / 32px; +--text-4xl: 36px / 44px; +--text-5xl: 48px / 56px; +``` + +## Spacing +```css +--section-padding-y: 80px; +--section-padding-x: 120px; +--card-padding: 32px; +--card-gap: 24px; +--card-radius: 16px; +``` +``` + +### 4e. Write each section file + +**Write ALL section files before fetching `get_design_context` for any section.** Screenshots from 4b are enough to write the stub — design context is fetched later, per-section, during Phase 5. If you fetch design context before the section files are on disk, you will rationalise skipping the write ("I already have the values in context") and the catalogue will be incomplete. + +Save to `.figma/[fileKey]/[section-slug].md`. One file per section. Include all concrete detail — layout code, typography values, colours, copy, assets, component mappings. An implementer should be able to start without re-fetching Figma. + +```markdown +# [Section Name] — [File Name] +File key: [key] +Node ID: `9936:51` +Size: 1440×803px +Slug: `hero` + +See shared styles: `shared-styles.md` + +## Complexity +**Score: [1–3]** — [Simple / Moderate / Complex] + +| Factor | Assessment | +|--------|------------| +| Layout complexity | [e.g. Single-column text — low] | +| Visual effects | [e.g. Two gradients, one with opacity overlay — medium] | +| Assets | [e.g. One SVG illustration — low] | +| Interactive states | [e.g. Three button variants with transitions — medium] | +| Responsive variants | [e.g. Three breakpoints with layout changes — medium] | +| Data / charts | [e.g. None — low] | +| Overlapping / absolute elements | [e.g. Decorative blobs positioned with negative insets — high] | + +**Error likelihood: [1–3]** — [Low / Medium / High] + +Key risks on first pass: +- [e.g. Gradient direction is subtle — easy to get wrong from screenshot alone] +- [e.g. Illustration size uses absolute px that collapses at tablet — confirm parent has explicit width] +- [e.g. CTA hover state not visible in static design — requires prototype inspection] + +> Complexity score drives the number of QA passes at the visual gate (1 pass / 2 passes / 3 passes). Error likelihood is a signal to the implementer about where to spend extra care. + +## Layout +```css +/* Outer wrapper */ +display: flex; +flex-direction: column; +align-items: center; +padding: 80px 120px; +gap: 48px; +max-width: 1440px; +``` + +## Typography +| Role | Font | Size | Weight | Line-height | Colour | +|------|------|------|--------|-------------|--------| +| Heading | Inter | 48px | 700 | 56px | #FFFFFF | +| Subheading | Inter | 20px | 400 | 28px | #8B8BA7 | +| CTA label | Inter | 16px | 600 | 24px | #FFFFFF | + +## Colours +| Token | Hex / gradient | Usage | +|-------|---------------|-------| +| Background | `linear-gradient(180deg, #1A0F3C 0%, #0F0F1A 100%)` | Section background [confirm] | +| CTA button | `linear-gradient(135deg, #6C63FF 0%, #48CAE4 100%)` | Primary button fill | +| Border | `rgba(255,255,255,0.08)` | Card border | + +## Spacing & Sizing +| Element | Value | +|---------|-------| +| Section padding (vertical) | `80px` | +| Section padding (horizontal) | `120px` | +| CTA gap | `16px` | +| Illustration width | `560px` | + +## Component Mapping +| Figma layer | Codebase component | Notes | +|-------------|--------------------|-------| +| `Button/Primary` | `