mcpbeat

Token Map

nexu-io/token-map

Map an extracted Figma / source-code token bag onto the active OD design system, producing a deterministic mapping the generate stage can consume.

3k tokens
context cost
the whole folder, loaded on every use
3
files
instructions only
0
copies elsewhere
how many repositories repackaged it
83386
stars on the repo
on the repository, not the skill itself

Install

one command, takes just this skill from the repository
npx skills add https://github.com/nexu-io/open-design --skill token-map

What comes with it

5 696 bytes besides the instruction
examples/semantic-inference-before-after.json
open-design.json

The instruction itself

8 sections, as written by the author

Token map

Spec §10 / §21.3.1: every figma-migration / code-migration run

crosses the same boundary — "the source has its own tokens; the

target uses the active OD design system; we need a deterministic

mapping". This atom produces that mapping.

Inputs

  • figma/tokens.json from figma-extract (figma-migration), OR
  • code/tokens.json from design-extract (code-migration).
  • The active design system DESIGN.md (already injected into the

prompt; the atom reads from the staged design-system context).

Output

project-cwd/
└── token-map/
    ├── colors.json     # { source: '#hex' | 'tokenName', target: '--ds-token' }[]
    ├── typography.json # font + size + weight pairings
    ├── spacing.json    # spacing scale crosswalk
    ├── unmatched.json  # { source: ..., reason: 'no-target-equivalent' }[]
    └── meta.json       # { sourceKind: 'figma' | 'code', generatedAt, atomDigest }

unmatched.json is the audit list a human reviews; the agent must

not invent target tokens silently.

Semantic token inference

Figma often exports anonymous source names such as color-3,

paint/17, or raw #5B8DEF. Do not ask the user to rename those

before mapping. First infer the semantic role from usage evidence:

  • Node path, component name, instance overrides, variant/state labels,

frame name, layer name, and nearby text such as Primary,

Selected, Link, Error, Focus, Nav, Button, or CTA.

  • CSS-like position in the rendered tree: background fill, foreground

text/icon, border, divider, overlay, shadow tint, focus ring, status

badge, chart series, or brand/accent treatment.

  • Contrast relationships: a color paired repeatedly with the main

canvas is likely foreground; one paired with foreground inside CTA

components is likely primary/accent background; a thin outline around

interactive elements is likely border or focus-ring.

  • Reuse topology: a value that appears across primary buttons,

selected tabs, and active nav items is stronger evidence for

--ds-color-primary than a value that appears once in an illustration.

Use that role evidence to choose among existing active design-system

tokens and to decide whether an anonymous token should be renamed or

left unmatched before the executable mapping pass. Keep the on-disk

token-map contract unchanged: the atom still writes the existing bucket

files, unmatched.json, and meta.json only.

For example, this is a useful reasoning note for deciding whether

color-3 should map to the active primary token:

{
  "source": "color-3",
  "value": "#5B8DEF",
  "role": "primary",
  "targetCandidates": ["--ds-color-primary", "--ds-color-link"],
  "evidence": [
    "Button/Primary fill",
    "Selected tab indicator",
    "Link text in Settings frame"
  ]
}

Then map to an active design-system token only when the evidence is

role-based, not value-only. If the top candidates are too close to

call, or if the evidence points to conflicting roles (primary vs

link vs focus-ring), leave the source token unmatched using the

existing no-target-equivalent reason and include the competing

candidates in the hint. This keeps automation useful for common

anonymous-token cases while preserving human review for ambiguous

brand decisions.

Before / after expectation

Without semantic inference, an anonymous Figma token can only produce

an uncertain value-level mapping:

{
  "source": "color-3",
  "value": "#5B8DEF",
  "target": null,
  "reason": "no-target-equivalent"
}

With semantic inference, the same token should carry role evidence

before it is accepted:

{
  "source": "color-3",
  "value": "#5B8DEF",
  "target": "--ds-color-primary",
  "via": "name"
}

This deterministic v1 atom does not claim a measured accuracy lift by

itself. Treat the expected improvement as coverage of previously

manual anonymous-token cases when the Figma tree contains enough role

evidence. Real accuracy numbers require a fixture suite with known

source tokens, expected semantic roles, and a before/after agent run.

See examples/semantic-inference-before-after.json for a deterministic

same-token-batch simulation that compares the old value-level output

with the semantic inference output.

Convergence

The atom completes when every input token is either mapped or

explicitly recorded under unmatched.json with a non-empty

reason. The until evaluator reads tokens.unmatched.length === 0

on strict mode; default is "soft converge" (proceed with

unmatched.json populated).

Anti-patterns the prompt fragment forbids

  • Injecting a new token into DESIGN.md without explicit user

approval (use a confirmation GenUI surface for that).

  • Mapping hex colours by visual proximity alone; perceptual ΔE

thresholds belong in the visual-diff evaluator (Phase 7).

  • Collapsing distinct source tokens onto the same target token

silently; record collisions in unmatched.json with reason

target-collision.

Status

Implemented by the daemon runner in

apps/daemon/src/plugins/atoms/token-map.ts. It parses design-system tokens,

performs deterministic mapping, and writes the mapped and unmatched outputs.

How to use it

Copy the folder

Take nexu-io/token-map from the repository into ~/.claude/skills for personal use, or into .claude/skills inside a project.

Check the name does not clash

The agent identifies a skill by the name field in its header. Two skills with the same name cannot sit side by side — one of them will be ignored.