Add a new design token (or token family) to the system, with every home it needs to reach. Use when asked to add a token, a new colour or motion token, or a token category.
Installs into .claude/skills of the current project.
Sponsors
SSkills DirectorySkills Directory
Know which skills are safe — weekly.
SSkills DirectorySkills Directory
Is that skill safe to install?
Are you the author of New Token?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/robritacca-dotcom-new-token)
---
name: new-token
description: Add a new design token (or token family) to the system, with every home it needs to reach. Use when asked to add a token, a new colour or motion token, or a token category.
icon: palette
displayDescription: "Walks a new design token through every surface it must reach: the token file its category lives in (both theme files for colour), the generated registry, the foundations pages, the Storybook token docs, and design.md. Covers the extra packaging steps a TypeScript-side token needs, and the validators that hold each home in sync."
invoke: ["add a token","add a [name] token","new token family","add a colour token"]
---
# new-token
Add a design token so it exists in every home the system requires — a token that exists only in CSS is incomplete.
## When invoked
Use this skill when asked to add or change a design token or token family — phrases like "add a token", "add a `--color-…` token", "new motion duration", "extend the chart ramp".
## Instructions
CLAUDE.md's **How to Add a New Token** section is the authoritative checklist — read it first and follow its numbered steps. This skill adds the operational detail the checklist compresses.
1. **Decide the tier.** A primitive (`--primitive-*` in `tokens-primitives.css`) is a raw value; a semantic token is a role. New roles reference existing primitives via `var()` — add a primitive first only when no suitable one exists. Semantic colour tokens must chain to a primitive or another `--color-*` token; `scripts/validate-token-references.mjs` fails the build on a literal.
2. **Put it in the file its category lives in** — `SEMANTIC_FILES` in `scripts/generate-token-registry.mjs` is the authoritative list of what the registry reads. Colour: both `src/tokens/tokens-light.css` and `src/tokens/tokens-dark.css`, always; the registry validator enforces light/dark parity for colour, so identical values in both is fine and a missing side is not. Shadow: both files too — the elevation tokens carry different values per theme — but parity is build-enforced for **colour only**, so a shadow token added to the light file alone ships silently unchanged in dark mode; check `tokens-dark.css` yourself. Spacing, radius, border, icon size, control height: `tokens-light.css` alone. A control-height step is also a row of `CONTROL_HEIGHT_STEPS` in `website/src/lib/theme/theme-overrides.ts`, which the density lever scales and `scripts/validate-theme-mirrors.mjs` holds to the primitives in both directions. Typography: `tokens-typography.css`. Motion: `tokens-motion.css`. Stacking (`--layer-*`): `tokens-light.css`, in its ladder lowest to highest, with a trailing comment saying what sits on the layer (`/foundations/layout` prints it; `scripts/validate-stacking.mjs` requires it and the order). Nothing but colour and shadow is theme-split; a typography or spacing token copied into `tokens-dark.css` registers from the light file anyway and leaves a dead duplicate no validator reports. A colour token that carries a **state** a reader must see (a checked or selected fill, a count, anything whose meaning is its fill) also needs a value in `src/tokens/tokens-forced-colors.css`, a system colour (`Highlight`, `Mark`…): high contrast modes flatten every other fill to the page, and design.md's Forced colors section owns which roles are re-pointed. The page-level check in `scripts/validate-website-a11y.mjs` (`FORCED_CHECKS`) proves the ones on the table bench; a new state outside it needs a row there.
3. **Check the prefix.** If the token starts a *new* prefix, generation fails until the prefix is added to `CATEGORY_PREFIXES` in `scripts/generate-token-registry.mjs` — deliberately, so a new category gets a display home at the same time. An existing prefix (`--color-`, `--motion-`, `--radius-`, …) needs nothing here; the registry regenerates on every build.
4. **Give it its documentation homes** (the build enforces the first, a drift audit catches the rest):
- Colour tokens need a swatch on `/foundations/colour-mode` — build-enforced in both directions by `scripts/validate-website-surfaces.mjs`. The values those pages print beside a swatch are build-checked too (`scripts/validate-foundation-mirrors.mjs`), so a caption must state what the token actually resolves to. Other categories go on their matching foundations page (CLAUDE.md's checklist maps category → page).
- The matching Storybook doc: `src/stories/Tokens.stories.tsx`, whose story exports are the list (spacing's story carries the control heights too); `src/stories/Typography.stories.tsx` for a type style (add it to the matching tier story, `DisplayStyles`, `HeadingStyles` or `BodyTextStyles`, and to `AllStyles`). A new type style also needs a `TYPE_STYLES` row in `website/src/lib/theme/theme-overrides.ts` (style, tier, weight, tracking): `scripts/validate-theme-mirrors.mjs` holds the table to the CSS in both directions and requires the display and heading tiers to hold one weight each, so decide the tier before picking the weight; a body-tier row is shifted by the body weight lever along with the paragraph, so its shipped weight is its distance from the paragraph's, not a fixed value.
- A sentence in `design.md` recording the role and how it relates to its neighbours (never a colour value: design.md is theme-agnostic), in the section that owns the token's subject. If that section states the family's size in words ("a four-step size scale"), `scripts/validate-design-counts.mjs` holds the words to the token files, so a new step fails the build until the sentence moves with it.
5. **A TypeScript-side token** (a shared constant, like the JS timing constants in `src/tokens/motion.ts`) has packaging steps CSS tokens do not:
- A subpath entry in `SUBPATHS` in `scripts/package-manifest.mjs`, mirrored by hand into the root `package.json` `exports` (`scripts/validate-package-exports.mjs` fails the build if they drift), plus a matching entry in `vite.lib.config.ts`.
- Or, if it is internal-only, an entry in `INTERNAL_MODULES` in `scripts/validate-package-exports.mjs` with the reason.
- If component code mirrors the token's value outside CSS (a `var()` fallback, a serialized config), route the mirror through a validator so it cannot drift — the chart palette guard in `scripts/validate-token-references.mjs` is the pattern to copy.
6. **Verify**: `npm run validate-registry` must pass end to end (it regenerates `src/tokens/registry.json`, `src/tokens/values.json` with the DTCG files under `website/public/schema/tokens/` (`scripts/validate-token-values.mjs` holds them; CLAUDE.md's How to Add a New Token step 5 says what fails when a token has no family or its value no mapper) and the other derived surfaces that carry token names or values, the consumer skills' token reference among them, and re-checks every home; the generator scripts at the front of the `validate-registry` entry in the root `package.json` are the authoritative list, so commit every file the chain rewrites), then `npm run build` for the type-check. Displayed counts update themselves — never hardcode one.
## Then Figma
The Figma kit's variables do not follow on their own. Ask the owner whether to run the `figma-tokens` skill now or in a separate session, so the kit picks up the change.
## Guardrails
- Never hand-edit `src/tokens/registry.json`, `src/tokens/values.json` or `website/public/schema/tokens/` — they regenerate from the CSS
- Never skip a tier: components reference semantic tokens, semantic tokens reference primitives
- A token with no consumer is not a token — if nothing will reference it, don't add it