---
name: library-builder
description: "End-to-end design library builder: intake questionnaire adapts to what the user knows (colors, typography, icons, or nothing), auto-detects existing file state, and orchestrates four phases — color system, typography, components, icons — pausing for review between each. Replaces running the individual skills manually."
---

# Library Builder

Build a complete design library end-to-end: color system → typography → components → icons. Adapts to what the user already has, asks the right questions at the right time, and pauses between phases for review.

---

## Running this with Claude and the Figma MCP

Written for Figma's built-in agent, adapted for Claude (Claude Code, Claude Desktop or claude.ai) connected to the official Figma MCP server.

- **Get the file.** If you don't have a Figma link, ask for one. The file key is the segment after `/design/`; a `node-id=1-2` parameter means node `1:2`.
- **Start a session.** Call `create_session` with the file key before any other Figma tool, and pass the returned session ID on every later call.
- **Read before writing.** `get_metadata` shows the structure and the user's current selection, `get_variable_defs` lists the variables on a node, `search_design_system` finds published components, variables and styles, and `get_screenshot` shows what's on the canvas.
- **Write with `use_figma`.** It runs Plugin API JavaScript in the file. Load the `figma-use` skill first (plus `figma-generate-library` when you create variables, styles or components) and list them in `skillNames`. Scripts use top-level `await` and `return` everything they create: nothing persists between calls, so pass node and variable IDs forward as string literals. Colors are 0–1, not 0–255. Switch pages with `await figma.setCurrentPageAsync(page)`, at most once per call; for multi-page work, run one call per page in parallel. `figma.notify()` isn't available.
- **Ask, then wait.** Wherever a step says to ask the user, ask in chat (in Claude Code, use the AskUserQuestion tool) and wait for the answer before building.
- **Clear helper fills.** `figma.createAutoLayout()` frames start with a white fill. Set `fills = []` on rows and wrappers that should be transparent, or they show up as white bars (most visibly in dark-mode previews).
- **Check the result.** After a build step, take one screenshot (`await node.screenshot()` inside `use_figma`, or `get_screenshot`) and fix only what's wrong.

## Intake: Big-Picture Questionnaire

Before touching the file, gather high-level context. Ask each question in turn (in Claude Code, with the AskUserQuestion tool). Skip any question the user already answered in conversation.

### I-1. Project purpose
Ask: "What kind of project is this library for?"
Examples: portfolio site, SaaS dashboard, e-commerce app, fintech platform, healthcare portal, communications tool, internal tool, marketing site, mobile app.
This drives component selection, type scale, and information density later.

### I-2. Design direction
Ask: "What's the stylistic direction?"
Examples: modern minimal, retro-futurist, editorial luxury, brutalist, organic/natural, geometric, playful consumer, corporate professional, dark mode-first, glass/translucent.
This influences color saturation, typography pairing, component styling, and spacing.

### I-3. Starting inventory
Ask: "What do you already have ready, if anything?"
Options:
- Base color swatches (filled shapes on the canvas)
- A complete or partial variable/token system
- Typography preferences or fonts in mind
- An icon set ready to integrate
- Nothing yet — starting from scratch

Record answers. The auto-detect in each phase will verify and fill gaps.

### I-4. Scope
Ask: "Do you want the full pipeline (colors → typography → components → icons), or specific phases?"
Let the user pick. Default is full pipeline. Record which phases to run.

---

## Auto-Detect: File State Assessment

Before starting any phase, inspect the file with read-only `use_figma` scripts (one per page, run in parallel) and `get_metadata`:

1. **Variable collections** — look for Primitives (raw color scales) and Semantic (aliased tokens with Light/Dark modes)
2. **Text styles** — catalog existing text styles by role
3. **Component pages** — list pages with components and what component types exist
4. **Icon organization** — check for an Icons page, icon components, naming conventions
5. **Enabled libraries** — note external library subscriptions
6. **Font usage** — catalog fonts, weights, and sizes currently in use

Present findings as a status dashboard:

| Phase | Status | Details |
|-------|--------|---------|
| Colors | ✅ Complete / ⚠️ Partial / ❌ Missing | e.g. "Primitives exist, no semantic layer" |
| Typography | ✅ Complete / ⚠️ Partial / ❌ Missing | e.g. "Inter used throughout, no text styles" |
| Components | ✅ Complete / ⚠️ Partial / ❌ Missing | e.g. "Buttons and inputs exist, no cards" |
| Icons | ✅ Complete / ⚠️ Partial / ❌ Missing | e.g. "No icon page found" |

Ask: "Here's what I found. Want to proceed with the planned phases, adjust, or redo any completed phase?"

---

## Phase 1: Color System

**Goal:** Primitive shade ramps + semantic tokens with Light/Dark modes + emphasis tokens.

### 1.1 — Phase-specific questions

If the user has base color swatches selected or on the canvas:
- Extract fill colors, log hex/RGB/HSL
- Check layer names — if generic ("Rectangle 1"), suggest renaming since names become variable group names (e.g., `sage/500`)

If starting from scratch:
- Ask for brand colors, mood, or palette inspiration

Ask about **palette tone** (affects saturation curve for all ramps):
- **Muted / Earthy** — low saturation, dusty and soft (peak sat ~20-30%)
- **Balanced** — moderate saturation, clear but not loud (peak sat ~40-50%)
- **Vibrant** — high saturation, bold and energetic (peak sat ~60-75%)

### 1.2 — Generate primitive shade ramps

For each base color, generate 11 steps: 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950.
- Step 50: near-white with hue hint
- Step 500: close to base color's lightness
- Step 950: near-black with hue hint
- Saturation follows the user's tone choice

Generate a **neutral ramp** (same 11 steps) warm- or cool-tinted to complement the palette's temperature.

### 1.3 — Derive status & alert colors

Create colors for **Success, Warning, Error, Info**.

Ask the user which base colors (if any) should map to status roles. For mapped statuses, reuse the base color's ramp — no new primitives needed.

For unmapped statuses, find complementary hues that fill gaps without clashing. Match the saturation character. Ask before generating if possible; proceed with best judgment if the user defers.

### 1.4 — Create variable collections

**Primitives** (single "Default" mode):
- One COLOR variable per shade step per ramp (e.g., `sage/500`, `cream/200`)
- Skip primitives for statuses that alias a base ramp

**Semantic** (two modes: "Light" and "Dark"):
Each variable aliases a primitive, switching per mode. Set `scopes` on every variable you create (for example `FRAME_FILL` and `SHAPE_FILL` for backgrounds, `TEXT_FILL` for text, `STROKE_COLOR` for borders). The default exposes each variable in every property picker.

| Category | Tokens |
|----------|--------|
| Background | `bg/primary`, `bg/secondary`, `bg/tertiary`, `bg/inverse` |
| Surface | `surface/default`, `surface/raised`, `surface/overlay` |
| Text | `text/primary`, `text/secondary`, `text/tertiary`, `text/inverse`, `text/on-accent` |
| Border | `border/default`, `border/strong`, `border/subtle` |
| Brand accents | Per color: `{color}/default`, `{color}/subtle`, `{color}/strong` |
| Status | Per status: `status/{name}/default`, `status/{name}/subtle`, `status/{name}/strong`, `status/{name}/text`, `status/{name}/border` |

Light/dark mapping pattern:
- Light: lighter primitives for backgrounds (50-200), darker for text (700-900)
- Dark: inverted — darker for backgrounds (800-900), lighter for text (200-400)

### 1.5 — Emphasis tokens

**CRITICAL: Never modify existing token values. Always create NEW dedicated tokens.**

Changing a token's value breaks every component referencing it. Instead, create parallel tokens.

Ask the user which components should use emphasis (inverted) treatment vs. standard:
- **Standard**: Light fills in light mode, dark fills in dark mode. Subtle, understated.
- **Emphasis**: Dark fills in light mode, light fills in dark mode. Bold, prominent.

Common patterns:
- Badges, Tags, Alerts, Toasts → often emphasis
- Inputs, Cards, Navigation → typically standard
- Buttons → either way depending on direction

For each accent/status needing emphasis:
- `{color}/emphasis` — dark fill in light mode, light fill in dark mode (*/700 light, */200 dark)
- `{color}/on-emphasis` — contrasting foreground (*/100 light, */800 dark)

### 1.6 — Contrast validation at the token level

Before building components, validate every token pairing in BOTH modes.

**Text pairings (target AAA 7:1, accept AA 4.5:1):**
- `text/primary` on `bg/primary`, `surface/default`, `surface/raised`
- `text/secondary` on same backgrounds
- `{color}/strong` on `{color}/subtle`
- `{color}/on-emphasis` on `{color}/emphasis`
- `status/{name}/text` on `status/{name}/subtle`
- `status/{name}/on-emphasis` on `status/{name}/emphasis`
- `text/inverse` on accent fills

**Non-text / graphic pairings (target AAA 4.5:1, accept AA 3:1):**
- `border/default` and `border/strong` on backgrounds
- Component fills vs. page background (boundary contrast)
- Icon circles, dots, close buttons against container fills
- Focus rings on input surfaces

Contrast formula — sRGB relative luminance:
`luminance(rgb) = 0.2126 * linearize(r) + 0.7152 * linearize(g) + 0.0722 * linearize(b)`
`contrastRatio = (lighter + 0.05) / (darker + 0.05)`

If a pairing fails AA, adjust the primitive step BEFORE building components.

### 1.7 — Build canvas swatches

Create a visual reference frame:
1. Title and description
2. Primitive ramp rows — labeled horizontal rows of 11 swatches (64×64px, 8px radius), each bound to its variable
3. Status section — only unique ramps, noting which reuse base colors
4. Semantic token preview — grouped by category, light/dark pairs side by side

### 1.8 — Phase checkpoint

**STOP. Present results to the user.** Show the swatch frame, report variable counts, and ask:
- "How does the color system look? Want to adjust anything before moving on?"
- Do NOT proceed to Phase 2 until the user approves.

---

## Phase 2: Typography

**Goal:** Typeface pairing, text styles, component font updates, and a standards page.

### 2.1 — Phase-specific questions

- **Design direction** (if not already covered): What mood should drive type choices?
- **Number of typefaces**: 1 versatile family, 2 complementary, 3 with monospace accent?
- **Font sourcing**: Browser-native/system only, Google Fonts/open-source, or any?
- **Specimen color scheme**: Dark background, light, or match existing file colors?
- **Legibility concerns**: Small-size readability, data density, thin strokes, etc.?

### 2.2 — Inventory current type usage

- Catalog fonts, weights, and sizes across all components
- Note text roles: heading, body, label, button, caption, input, kicker, etc.
- Check existing text styles

### 2.3 — Check available fonts

Run `await figma.listAvailableFontsAsync()` in a `use_figma` script and filter by sourcing constraint. Use the exact style names it returns: they differ by family (Inter uses "Semi Bold", while Lexend, Nunito and Atkinson Hyperlegible Next use "SemiBold"). Build a shortlist matching the design direction.

### 2.4 — Create specimen pairings

Create **3 specimen cards** side by side showing different typeface pairings. Each displays:
- Pairing name and character description
- Heading, subheading, label, and body samples
- Font metadata (family, weight, size)
- CSS fallback stack

Use the user's preferred color scheme for specimens.

### 2.5 — Iterate on pairings

Present specimens, gather feedback. Create alternatives or mix-and-match combinations based on reactions. Repeat until the user has a clear favorite.

### 2.6 — Full-page mockup

Build a complete page layout using **actual component instances** from the library (if components exist). Override fonts on all text nodes to the chosen pairing:
- **Display font** → headings, buttons, nav links, brand text, alert titles
- **Body font** → body copy, descriptions, labels, badges, captions, input values

If no components exist yet (Phase 3 hasn't run), create a standalone type specimen layout.

### 2.7 — Apply to the library

Once the user confirms:

**a. Update all component fonts** — walk every component across all pages, swap to chosen typefaces using context-aware role mapping.

**b. Create text styles** — define styles for all discovered roles:
- Heading/H1, H2, H3
- Body/Default, Small, Emphasis
- Label/Kicker, Default, Small
- UI/Button, Nav Link, Nav Brand, Alert Title
- Caption/Default, Small
- Input/Label, Value

Each style: family, weight, size, line height, letter spacing, text case, description.

**c. Bind text styles to components** — apply styles to every text node in every component, matching by role.

**d. Let user review** — if they change fonts on specific elements, audit and update affected styles.

### 2.8 — Typography standards page

Create a documentation page with:
- Typeface overview cards (role, character sample, CSS fallback)
- Type scale specimens grouped by role category
- Usage guidelines (role separation, formatting, fallbacks, minimum sizes, color pairing)

### 2.9 — Phase checkpoint

**STOP. Present results.** Ask:
- "How does the typography look across the components? Any adjustments before moving to component construction?"
- Do NOT proceed until approved.

---

## Phase 3: Components

**Goal:** Complete, accessible component library with proper token binding and WCAG 2.2 compliance.

### 3.1 — Phase-specific questions

Ask the user to describe their project OR list specific components. Propose a set based on project type:

- **Portfolio / Marketing**: Buttons, Navigation, Content Cards, Badges & Tags, Section Headers, Testimonials, Inputs, Alerts & Toasts
- **SaaS / Dashboard**: Buttons, Navigation, Data Cards, Stat Tiles, Tables, Badges & Tags, Inputs, Alerts & Toasts, Modals, Tabs
- **E-commerce**: Buttons, Navigation, Product Cards, Badges & Tags, Inputs, Search, Alerts & Toasts, Rating Stars, Price Display

Get explicit confirmation. The user may add, remove, or adjust.

### 3.2 — Page organization

Create a dedicated page for each component type.

### 3.3 — Component variant strategy

For each component, define variant axes:
- **Visual style** (Primary, Secondary, Ghost, Destructive, etc.)
- **State** (Default, Hover, Focus, Disabled, Error)
- **Size** where applicable (Default, Small, Large)
- **Content properties** (with/without icon, with/without description)

Build variants as components within a component set (`figma.combineAsVariants(components, parent)`). Expose text as TEXT properties, optional elements as BOOLEAN properties.

### 3.4 — Token binding rules

**Standard components** (inputs, cards, nav, buttons):
- Fills → `subtle`, `surface/*`, or `bg/*` tokens
- Text → `text/*`, `strong` tokens
- Borders → `border/*`, `strong` tokens
- Focus rings → `{accent}/default`
- Error states → `status/error/strong` for borders and labels

**Emphasis components** (badges, tags, alerts, toasts — per user preference from Phase 1.5):
- Fills → `emphasis` tokens
- Text → `on-emphasis` tokens
- Borders/strokes → `on-emphasis` tokens
- Dots, decorative elements → `on-emphasis` tokens
- **Icon circles / enclosed decorative shapes** → original `subtle` token
- **Marks inside icon circles** → `emphasis` token

### 3.5 — Nested contrast awareness

Components with layered elements have multiple contrast relationships:

```
[Alert fill: emphasis] → [Icon circle: subtle] → [Checkmark: emphasis]
                       → [Title text: on-emphasis]
                       → [Close button: on-emphasis]
```

Each adjacent pair must independently meet contrast. Validate:
1. Icon circle vs. alert fill (3:1 min)
2. Checkmark vs. icon circle (3:1 min)
3. Text vs. alert fill (4.5:1 min)
4. Close button vs. alert fill (3:1 min)
5. Alert fill vs. page background (3:1 boundary min)

### 3.6 — Icon and graphic accessibility

- **Never use text characters as icons** (✓, ✕, i, !). Use vector shapes or built-in icons.
- All graphical UI elements must meet 3:1 contrast against adjacent background.
- Decorative elements exempt.

### 3.7 — Instance reuse

When one component references another (e.g., card contains badge instances), always use actual component instances — never recreate with ad-hoc frames.

### 3.8 — Per-component verification

After building each component, run contrast checks on EVERY variant × state in BOTH modes:
- Text fills vs. background (4.5:1+ AA, 7:1+ AAA)
- Non-text elements vs. adjacent backgrounds (3:1+ AA, 4.5:1+ AAA)
- Component boundary vs. page background (3:1+)
- Focus/selected states maintain contrast
- Disabled states exempt but should be perceivable

### 3.9 — Contrast failure response

1. Prefer adjusting the primitive step (*/600 → */700) over overrides
2. If a step change breaks another pairing, create a new dedicated semantic token
3. Never add hard-coded colors — all fills must be variable-bound
4. Re-check all dependent pairings after any adjustment

### 3.10 — Cross-component consistency

After all components:
- Verify shared tokens produce consistent contrast across components
- Confirm instances inherited correct tokens
- Check emphasis and standard components don't share token references

### 3.11 — Phase checkpoint

**STOP. Present results.** Show screenshots of each component set in both light and dark modes. Ask:
- "How do the components look? Any adjustments before moving to icons?"
- Do NOT proceed until approved.

---

## Phase 4: Icons

**Goal:** Organized icon set wired into library components as instance swap properties.

### 4.1 — Determine icon source

Ask how the user will provide icons:
- **Already pasted onto a page** — ask which page
- **Figma community file or link** — search, read, copy into an Icons page
- **SVGs dragged onto canvas** — raw vectors to convert
- **No icons yet** — skip this phase or suggest icon sources

### 4.2 — Audit pasted icons

1. Count and catalog all icon nodes (types: COMPONENT, FRAME, GROUP, VECTOR, INSTANCE)
2. Check sizing consistency (16×16, 20×20, 24×24 typical). Flag inconsistencies.
3. Identify categories — icons may be grouped in named frames (e.g., "General (solid)", "Arrows (outline)")
4. Detect duplicates — distinguish true copies (remove one) from solid/outline pairs (keep both). Check child vectors for fills (solid) vs. strokes (outline). Screenshot ambiguous cases.
5. Report findings to user.

### 4.3 — Convert to components (if needed)

If icons aren't already components:
1. Create a component for each icon
2. Ensure consistent sizing
3. Place into category frames

### 4.4 — Clean up and rename

1. Merge near-duplicate frames sharing most icons
2. Remove true duplicate frames
3. Rename all icon components: `Icons / {Category} / {Style} / {icon-name}`
   - Example: `Icons / General / Solid / star`, `Icons / Arrows / Outline / arrow-left`
   - If no solid/outline distinction: `Icons / Brands / github`
4. Rename parent frames to clean category names

### 4.5 — Wire icons into library components

Scan all pages for component sets that could benefit from an icon instance swap property:
- Buttons, Inputs, Alerts, Navigation, Badges, Cards, Menu items, Tabs, Tooltips, etc.

For each candidate:
1. Check if it already has an icon instance swap — skip if so
2. Present the list to the user, ask which to update

For each selected component:
1. Pick a sensible default icon
2. Add an `Icon` instance swap property
3. Add a `Show icon` boolean property
4. Insert an icon instance into every variant at a logical position
5. Match icon fill/stroke color to text color per variant for correct contrast
6. Screenshot to verify

### 4.6 — Phase checkpoint

**STOP. Present results.** Report:
- Total icons, category breakdown
- Duplicates removed
- Components updated with icon swap properties
- Ask: "How does the icon integration look? Anything to adjust?"

---

## Completion

After all phases, present a final summary:
- Total primitive variables created
- Total semantic variables (with mode counts)
- Typography: typefaces chosen, text styles created
- Components: list of component sets with variant counts
- Icons: total organized, components wired
- Remind the user to **publish the file as a library** to make everything available across files.

---

## Key Principles

1. **New tokens over modified tokens.** Never repurpose an existing token — create new ones for different behavior.
2. **Validate before you build.** Check token-pair contrast before component construction.
3. **Test both modes, every variant.** Light-passing may be dark-failing. Always check both.
4. **Aim high, accept pragmatic.** Target AAA (7:1 text, 4.5:1 non-text). Accept AA (4.5:1 text, 3:1 non-text) when AAA conflicts with design direction. Never ship below AA.
5. **Icons are graphics, not text.** Visual symbols follow 3:1 non-text rule (SC 1.4.11), not 4.5:1 text rule — but must be actual shapes, not text characters.
6. **One source of truth.** Every color is a variable binding. Every repeated element is a component instance. No ad-hoc duplicates.
7. **Every text node needs a style.** No orphaned text by the end.
8. **Show, don't tell.** Create visual specimens rather than describing fonts in text.
9. **Respect existing work.** Preserve variable collections, color tokens, and component structure. Extend, don't rebuild, unless the user explicitly requests it.
10. **The mockup is the source of truth.** If the user edits specimens or mockups, those changes override previous decisions.
