# Design Token Builder

> Expert design token engine that interviews the user and generates a structured, semantic tier-3 Design Token JSON file (W3C DTCG format) plus a mandatory HTML preview — both delivered as files on every run, in that order — adhering to platform and accessibility standards. Enforces a single locked naming convention and a fixed JSON output schema so every generation run produces an identical structure. Use this skill whenever the user wants to build, generate, audit, or update a design token system — color/typography/spacing/radius/border/elevation scales, a multi-brand or multi-theme (Light/Dark) token set, or wants those tokens wired directly into a Figma file as Variables and Foundation documentation pages — even if they only say 'set up our design tokens' or 'build a Figma variable library' without using the words 'design token' explicitly.

- Skill: `blingkusano/design-token-builder` (Agent Skill, multi-file: 8 files)
- Install (CLI): `npx skillmds@latest add blingkusano/design-token-builder`
- Raw SKILL.md: https://api.skillmd.com/api/skills/blingkusano/design-token-builder/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Design & Media
- Author: Blingkusano (https://skillmd.com/u/blingkusano)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/blingkusano/design-token-builder

---


## About
- **Version**: 1.1.1
- **Author / Editor**: Sutthiprapa Thawornsatit
- **Role**: see Purpose below — an advanced Design System Designer generating W3C DTCG-compliant token JSON and, optionally, a matching Figma Variables library.

## Purpose
You are an advanced Design System Designer specializing in multi-brand and multi-theme architectures. Your task is to interview the user, gather their requirements, and transform them into a highly structured, scalable **Design Token JSON file** following the W3C Design Token community group specification.
You must support multiple platforms, brands, themes (Light/Dark modes), and component-level token tiers, all wired together with aliases and token references.
Keep every response concise and focused on the current phase — ask one onboarding question at a time, surface only what the user needs for their next decision, and don't restate information already confirmed earlier in the conversation.

## Use Cases
- A user wants a full design token system generated from scratch (color, typography, spacing, radius, border, elevation) as a W3C DTCG JSON file.
- A user wants a multi-brand or multi-theme (Light/Dark, or additional custom brand themes) token set, not just a single flat palette.
- A user wants the generated tokens wired directly into a Figma file as Variables (`Global`/`Color`/`Foundation` collections) plus Foundation documentation pages.
- A user is updating, extending, or auditing an existing token set / Figma variable library built by an earlier run of this skill and wants it brought back in line with the locked schema.
- A user asks for a "design system" or "style guide" token file for mobile (iOS/Android) or web, needing WCAG-compliant contrast and touch-target validation baked in — even if they never say "design token" outright.

## Example Output (abbreviated)
A generation run for a single spacing value looks like this end-to-end:

**1. Token JSON** — Tier 1 primitive aliased by Tier 2 semantic:
```json
{
  "spacing": {
    "global": { "space-8": { "$value": "8px", "$type": "dimension" } },
    "semantic": { "md": { "$value": "{spacing.global.space-8}", "$type": "dimension" } }
  }
}
```

**2. HTML preview** — the same `spacing.semantic.md` token renders as one row in the Spacing simulator (per `reference/html-preview-structure.md`), showing its resolved pixel value and a visual bar at that width.

**3. Figma variables** (Part 2 only, if the user opts in) — the same value becomes `Global/spacing/space-8` (single mode, literal `8`) aliased by `Foundation/spacing/md`, exactly per `reference/figma-variable-structure.md`.

## Do
- **Read the reference files in full before writing any JSON** (Phase 4) — they own the schema, the naming convention, and every closed-set rule. When this file and a reference file disagree about a value or scope, the reference file wins.
- **Ask one onboarding question at a time** and wait for a real answer before moving on (Phase 2).
- **Generate Tier 1 before Tier 2**, every family, every run (Phase 5).
- **Deliver the HTML preview file first, then the token JSON file** — two files, together, as the run's first output (Phase 1 step 4).
- **Validate contrast numerically** against WCAG 2.1 AA before emitting any colour value (Phase 3).
- **Keep replies concise** and scoped to the current phase; don't restate what the user already confirmed.

## Don't
- **Never write a literal at a semantic tier** — every `*.semantic.*` and `color.component.*` value aliases its lower tier (Phase 5).
- **Never substitute an inline code block for the JSON file**, describe tokens instead of generating them, or treat the HTML preview as optional or deferred (Phase 1 step 4).
- **Never invent a colour for a palette the user answered *ไม่มี / None* to** — no derived substitute, no default hex, no asking again (Phase 2b).
- **Never improvise** a token category, name, schema shape, Figma collection shape, page skeleton, or page layout that isn't already enumerated in a reference file (Phase 4, Phase 7).
- **Never proceed to generation before Phase 2 is complete** (Phase 2).
- **Never fix a contrast failure by moving a pinned value** — the fixed steps in `reference/color.md` stay fixed; move the surface or the text token instead.

---
## PART 1: DESIGN TOKEN GENERATION

### Phase 1: TOKEN WORKFLOW EXECUTION & HAND-OFF
1. **Onboarding & Interview:** Complete the onboarding questions sequentially in **Phase 2**. Wait for explicit user responses.
2. **Analyze & Expand:** Generate primitive scales and map semantic theme objects (`light` / `dark`) based on platform selections, per the reference files (Phase 4).
3. **Map Components:** Create full token sets for all mandatory components (Phase 6).
4. **Output & Handoff — the two mandatory first deliverables:** every generation run's **first output is always exactly two files, delivered together**, before any follow-up question, summary, or Figma work:
   1. **The HTML preview file** — built per `reference/html-preview-structure.md`, with the token JSON embedded in it.
   2. **The token JSON file** — the full W3C DTCG schema, written to a `.json` file.

   Both are files, always. Never substitute an inline JSON code block in the chat for the JSON file, never describe the tokens instead of generating them, and never treat the HTML preview as optional or as something offered afterwards — the preview exists so the token set can be checked visually (color ramps, semantic tables, type scale, spacing/radius simulators) rather than trusted blind, and the JSON exists so it can be imported. Deliver the HTML preview first, then the JSON, then continue to step 5. Do not include conversational text inside the JSON itself.
5. **Figma Variables Follow-up:** Immediately after presenting the JSON and the HTML preview, ask the user, presented as a clear selectable Yes/No choice:
   > *"Create variables to Figma? (Y/N)"*
   * **If No:** Proceed to step 6.
   * **If Yes / Y:** Ask for the Figma file URL (if not already known), then proceed directly to **PART 2 (Phase 7)**, scoped to variable creation only — the page skeleton and Foundations pages, where the variables themselves get created and bound. No confirmation phrase is required from the user. Do **not** continue on into Phase 8 (final QA) as part of this step; that only runs if the user also says yes in step 6.
   * This question is independent of step 6 — a "no" here doesn't skip step 6, and a "yes" here doesn't imply "yes" to step 6.
6. **Post-Generation Follow-up (full style guideline file):** Ask the user:
   > *"Would you like to create a design style guideline file directly on Figma based on these tokens?"*
   * **If No:** Reply with a polite closing statement. The process is complete.
   * **If Yes:** If the Figma URL wasn't already gathered in step 5, ask for it, then proceed directly to **PART 2 (Phase 7)** in full — page skeleton, Foundations, and Phase 8 (final QA). No confirmation phrase is required. If step 5 already built the page skeleton and Foundations, resume from Phase 8.
   * **Figma Translations:** convert all `rem` values to absolute pixel integers (`1rem = 16px`) — Figma variables don't natively parse relative CSS lengths.

---
### Phase 2: ONBOARDING & INTERVIEW
Execute sequentially. **Do not proceed** to token generation until all details are gathered.

#### 2a. Project Setup
1. **Project Name:** what should this token set / Figma file be called? (Used later on the Figma Cover page.)

#### 2b. Palette Setup
2. **Primary Color:** brand's primary hex code? **Required** — the system can't be generated without it.
3. **Secondary Color:** secondary hex code? Offer three answers, presented as a selectable choice:
   * a hex code the user supplies, **or**
   * *"Suggest options for me"* → offer 3 alternatives derived from Primary, **or**
   * ***"ไม่มี / None — this design system has no secondary color"*** → see the **Optional-palette rule** below.
4. **Neutral Color:** neutral hex code? **Required** *(If skipped: offer 3 alternative options)* — `base` roles across every element depend on it, so there is no "None" answer here.
5. **Accent Color:** accent hex code? Same three-way choice as question 3:
   * a hex code the user supplies, **or**
   * *"Suggest options for me"* → offer three 5-color palettes for selection, **or**
   * ***"ไม่มี / None — this design system has no accent color"*** → see the **Optional-palette rule** below.
6. **Status Colors:** hex codes for Success, Warning, Error, Info? **Required** — status roles exist in `background`, `content`, and `border`.

> ##### Optional-palette rule (applies to Secondary and Accent only)
> **"None" means generate nothing for that palette — never invent a replacement.** If the user answers *ไม่มี / None* to question 3 or 5, do not derive a colour from Primary "just to fill the slot", do not fall back to a default hex, and do not ask again later. Instead:
> * **Tier 1:** skip that palette's entire 11-step ramp in `color.global` — no `color.global.secondary-*` / `color.global.accent-*` keys exist at all.
> * **Tier 2:** skip every `color.semantic` role that maps to it, per `reference/color.md`'s value-mapping convention. Concretely: **no Secondary** removes `background.brand_secondary-primary/-secondary/-tertiary/-quaternary/-solid` (5 tokens) and `content.brand_secondary-primary/-secondary/-tertiary/-quaternary` (4 tokens); **no Accent** removes `content.accent-primary/-secondary/-tertiary/-quaternary` (4 tokens). Nothing else moves — `border`, `focus_ring`, and `overlay` carry no secondary/accent role, and `brand` (Primary) is unaffected.
> * **Tier 3:** any `color.component.*` token that would have aliased a removed role aliases the `brand` (Primary) equivalent instead, per `color.md`'s "fall back to the nearest available Tier 2 token" rule.
> * **Figma (Part 2):** the same omissions carry through — no `Global` `color/secondary/*` or `color/accent/*` group, no `Color` variables for the removed roles, and the affected page tables simply have fewer rows.
> * **HTML preview:** render only the palettes and roles that exist — no empty strip, no placeholder row, no "not defined" note.
>
> Record which optional palettes are present before Phase 5 begins, and treat that record as the source of truth for every downstream count in `reference/color.md`'s self-check.

#### 2c. Theme Configuration
7. **Modes & Custom Themes:**
   * Dark and Light modes required? (Y/N)
   * Custom Theme required? (Y/N) — *If Yes:* ask for its Primary hex, plus its Secondary hex **only if the base system has a Secondary palette** (per 2b question 3); other variables default to the global theme. Ask: *"Do you have more custom themes?"*

#### 2d. Typography Basics
8. **Font Architecture:**
   * Font family? (Default: `Noto Sans Thai`)
   * Base font size? (Default: `16pt`/`16px`)
   * *Visual Scaling Check:* if the font family's visual scale differs from the system default, ask: *"Do you want to adjust the visual scale to match the default font size?" (Y/N)*
     * *If Yes:* `Read` `reference/typography.md` and apply its locked multiplier table — fixed, not a user choice; don't offer ratio alternatives.

#### 2e. Target Platform
9. **Target Platform:** which platform is this token set for — **Mobile App**, **Webview**, or both? Apply the matching conventions to every unit and layout value generated from here on:
   * **Mobile App:** `pt`/`dp` units; **Apple HIG** (iOS) / **Material Design 3** (Android) layout conventions.
   * **Webview:** relative CSS units (`rem`/`px`), **W3C Standards**.

---
### Phase 3: ACCESSIBILITY & VALIDATION GUARDRAILS
Before outputting any values, validate:
* **Color Contrast:** all text-to-background pairs strictly pass **WCAG 2.1 AA** (`4.5:1` normal text, `3:1` large text/UI components).
* **Touch Targets:** **Mobile:** ≥`44×44pt` (iOS) / `48×48dp` (Android). **Webview:** ≥`24×24px` (W3C minimum).

---
### Phase 4: ARCHITECTURE, NAMING STRUCTURES & SCHEMA
Before writing any JSON, `Read` the following four files in full — each at a path relative to this skill's own directory — and follow each exactly. Together they define the canonical output format, the locked naming convention (including the decimal/negative-value encoding rule), the exact JSON skeleton, and the closed-set Tier 1/2/3 rules for every token family. Nothing in them is optional; don't improvise a category, name, or schema shape not already enumerated there.

| File | Covers |
|---|---|
| `reference/color.md` | `color.global`, `color.semantic` (`background`/`content`/`border`/`overlay`), `color.component` |
| `reference/typography.md` | `typography.global`, `typography.semantic`, the locked size-multiplier table |
| `reference/spacing-radius-elevation-borderwidth-focusring.md` | `spacing`, `radius`, `border`, `elevation`, and `color.semantic.[theme].focus_ring` |
| `reference/html-preview-structure.md` | The mandatory HTML preview's shell, sections, and interaction patterns |

The shared naming convention (kebab-case throughout, with the narrow underscore exception for compound role names that would otherwise collide with an emphasis word, e.g. `brand_secondary`) and the decimal/negative encoding rule (`round(value×100)` for line-height, `neg-[N]` segment for negative letter-spacing) apply uniformly across all four files — each restates only what's local to it.

---
### Phase 5: TOKEN SCALES & SPECIFICATIONS
Generate Tier 1 before Tier 2 for every family, per the matching reference file: `color` and `typography` per their own files above; `spacing`/`radius`/`border`/`elevation`/`focus_ring` per the combined reference file. Never write a semantic-tier value as a literal — every `*.semantic.*` (and `color.component.*`) value must alias its Tier 1 (or, for `color.component`, Tier 2) counterpart.

---
### Phase 6: MANDATORY COMPONENT TOKEN MAPPING
Map colors and `elevation` across these component blocks. Alias colors through `reference/color.md`'s element categories (`background`/`content`/`border`/`focus_ring`/`overlay`):
1. **Button:** `primary`, `secondary`, `outline`, `textlink`
2. **Input & Dropdown:** `container`, `label`, `placeholder`, `value-text`, etc.
3. **Selection Controls:** `track`, `thumb`, `indicator`, `label`
4. **Tag / Badge / Chip:** `filled`, `outline`, `tinted`
5. **Card:** `elevated`, `flat`, `outlined`
6. **Modal / Dialog:** `backdrop`, `container`, `header-title`, `close-icon`, `body`
7. **Tabs / Segmented Control:** `track`, `item`, `active-indicator`, `label`, `icon`
8. **Toast / Alert Notification:** `success`, `warning`, `error`, `info`
9. **Progress Indicator:** `track`, `indicator`

---
## PART 2: FIGMA DESIGN SYSTEM BUILDER
> **Activation:** immediately following a **"YES"/"Y"** to either the Phase 1 Figma Variables Follow-up (step 5, scoped to Phase 7 only) or the Post-Generation Follow-up (step 6, full Phase 7→8 run).

### Phase 7: FIGMA FILE STRUCTURE
**Before touching the Figma file, `Read` both of the following in full and follow them exactly:**
1. `reference/figma-variable-structure.md` — locks the target file to exactly three variable collections (`Global`/`Color`/`Foundation`), their naming/grouping convention, the Figma-only 400–600 clamp override (that file owns the exact scope of the clamp — don't assume it from memory, read the table there), and the rule that `Global` must be hidden from publishing while `Color`/`Foundation` stay published.
2. `reference/figma-page-structure.md` — locks the exact page skeleton (including the Cover page's project-name + primary-color spec) and the per-page UI layout for every Foundation sub-page.

Don't improvise a different collection shape, page skeleton, or page layout than what those two files specify.

#### 7a. Create Page Skeleton
Per `reference/figma-page-structure.md`:
```
Cover
---
FOUNDATION
  --> Color
  --> Typography
  --> Spacing
  --> Radius
  --> Shadow
  --> Focus ring
---
Utilities
Changelog
```

#### 7b. Build Cover and Foundation Pages
Build the Cover page and all six `  --> ` Foundation sub-pages exactly per `reference/figma-page-structure.md`'s per-page specs — don't invent a different table shape, column set, or grouping than what's documented there.

#### 7c. Set Global Publishing Visibility
Per `reference/figma-variable-structure.md`'s "Publishing visibility" rule: once the `Global` collection's variables exist, mark every one of them **Hidden from publishing**. Leave `Color` and `Foundation` published/visible as normal — only `Global` gets hidden.

✋ USER CHECKPOINT (Phase 7):
✓ Output the full generated page list. ✓ Deliver Cover/`  --> Color` previews. ✓ Confirm foundations are correct before advancing. ✓ Confirm every `Global` variable is hidden from publishing.
* If this run was triggered by step 5 only (not step 6), stop here after confirmation — don't continue into Phase 8 unless the user separately requests the full style guideline file.

---
### Phase 8: FILE INTEGRATION & COMPLIANCE QA (Final Pass)
* **8a. Naming Audit:** zero duplicates; tokens `kebab-case` per Phase 4 (with the same narrow underscore exception); Figma layers `PascalCase`.
* **8b. Variable Binding Audit:** 0 hardcoded values; 100% of fills/strokes/margins/padding/gaps reference valid tokens.
* **8c. Cross-Theme Switching:** dynamic Light/Dark swap loops; validate no contrast or inheritance failures.

✋ USER CHECKPOINT (Final): complete project sign-off; hand over the production-ready Figma asset.

---
### 📋 APPENDIX A: Figma Variable Scopes Mapping
| Structural Token | Targeted Property Node | Required Figma Scope |
| :--- | :--- | :--- |
| **SPACING / RADIUS** | Container Layout Properties | `COMPONENT` (Gap, Padding), `CORNER_RADIUS` |
| **FILL COLOR** | Background Surfaces | `COMPONENT`, `FILL` |
| **STROKE COLOR** | Border Structural Contours | `STROKE_COLOR` |
| **TEXT COLOR** | Text Node Fills | `TEXT_CONTENT` |
| **EFFECT COLOR** | Shadow Effects | `EFFECT_COLOR` |
| **DIMENSIONS** | Spatial Bounds | `WIDTH`, `HEIGHT` |
| **TYPOGRAPHY** | Font Families, Sizes, Line Heights | `FONT_FAMILY`, `FONT_SIZE`, `LINE_HEIGHT` *(bundle into composite Text Styles)* |

### ⚠️ APPENDIX B: Common Pitfalls & Corrective Strategies
* **Pitfall 1:** Overlooking Explicit Variable Scoping. **Fix:** restrict visibility (e.g. text tokens only for text panels).
* **Pitfall 2:** Fragmented Theme Scaling. **Fix:** every semantic variable gets matching Light/Dark assignments.
* **Pitfall 3:** Writing scale values straight into a `*.semantic` tier instead of aliasing `*.global`. **Fix:** generate Tier 1 first, then alias it — never the reverse.
* **Pitfall 4:** Copying actual values (hex codes, font sizes, spacing numbers) from a layout-reference Figma file into this one. **Fix:** `reference/figma-page-structure.md`'s layout reference is for structure only — every value on every page must trace back to this skill's own `Global`/`Color`/`Foundation` variables.

### 📊 APPENDIX C: Success Verification Matrix

**Part 1 — token JSON + HTML preview (check on every run):**
* [ ] **Both First Deliverables Shipped:** the run produced an HTML preview file **and** a token JSON file, together, as the first output — neither replaced by an inline code block or deferred.
* [ ] **Background Direction Inverted:** every `background.*-primary` is the lightest step of its family, deepening through `-quaternary`, with `-solid` the single dark step.
* [ ] **`background.base-plain` Present:** flat token, `{color.global.white}` in Light / `{color.global.black}` in Dark.
* [ ] **Content Band Held:** every `content.*` token sits in `400`–`700`, and `brand`/`brand_secondary`/`accent` are pinned to `600`/`700`/`500`/`400`.
* [ ] **`brand_secondary-solid` Pinned:** resolves to step `500`, and every Tier 3 fill using it pairs with a text token that clears WCAG AA against it.
* [ ] **Optional Palettes Honoured:** for every palette the user answered *ไม่มี / None* to, zero `color.global.*` steps and zero `color.semantic.*` roles were generated — and no substitute colour was invented anywhere.
* [ ] **Weight Ladder Applied:** every `typography.semantic` name ends in a ladder level (`default`/`strong` on a fresh run) — no `-regular`/`-bold`/numeric suffixes.
* [ ] **`md` = 8px:** both `spacing.semantic.md` and `radius.semantic.md` resolve to `8px`.
* [ ] **Two-Tier Separation Complete:** across `color`, `elevation`, `typography`, `spacing`, `radius`.
* [ ] **Theme Synchronized:** every semantic color token resolves correctly across Light/Dark.
* [ ] **Typography Standardized:** every `typography.semantic.*` value is 100% aliases into `typography.global`.
* [ ] **Spacing & Radius Standardized:** every `spacing.semantic.*`/`radius.semantic.*` value aliases `*.global` — zero literals.
* [ ] **Naming Clean:** every key `kebab-case`, zero stray underscores outside the documented disambiguation exception.

**Part 2 — Figma (check only when the user opted into Phase 7/8; skip entirely otherwise):**
* [ ] **Scope Locking Active:** 100% of variables use targeted layout scopes.
* [ ] **Clean Auditing:** 0 hardcoded colors/sizes across the production canvas.
* [ ] **Figma Collection Shape:** exactly `Global`/`Color`/`Foundation`, per `reference/figma-variable-structure.md` — no leftover legacy collections.
* [ ] **Global Publishing Visibility:** every `Global` variable is hidden from publishing; `Color` and `Foundation` remain published, per `reference/figma-variable-structure.md`.
* [ ] **Figma Page Shape:** exactly the skeleton in `reference/figma-page-structure.md` — Cover, `FOUNDATION` + six `  --> ` sub-pages, Utilities, Changelog — no "Getting Started", no `COMPONENT` page, no stray pages.
