Importing Existing Tokens Without Losing Anything
Before trusting any token tool with a file you care about, run one experiment: import the file, change nothing, export it, and diff the result against the original. The whole test takes about five minutes, and the diff is the tool’s character reference — it shows exactly what the tool considers its own and what it silently rewrites.
Importing design tokens without losing anything comes down to one property: a well-behaved tool owns the sections it generates and preserves everything else, so that save→load→save is a fixpoint — the file that comes out is the file that went in, except where you asked for change. A tool with that property can be adopted incrementally; a tool without it forces an all-or-nothing migration. This piece covers the file mechanics of import and re-export; the wider fundamentals live in our design tokens guide.
Why is importing tokens scary?
Because a real tokens file is rarely just what one tool generated. Give a
file a year in production and it accumulates hand-built work: component
tokens someone added for a genuine exception, $extensions blocks carrying
platform metadata, a colleague’s animation timings that no generator has any
model of. The accumulation is the file doing its job — one source, growing
with the system.
The fear scenario is a naive tool meeting that file. Naive import reads the parts the tool understands; naive export regenerates the whole file from what was read. Import → export → half the file gone: the animation section, the extensions, the hand-added exceptions — everything the tool didn’t model, deleted by omission rather than intent. Teams that live through this once learn to keep the tool away from the real file and maintain tokens by hand — which quietly gives up most of what the tooling was for.
What is the round-trip contract?
Three clauses. First, ownership is sectional: the tool declares which parts of the file it generates — the color ramps, the type scale, the semantic layers — and treats everything else as foreign territory. Second, preservation is literal: foreign sections pass through unchanged, not “re-serialized but equivalent”. Third, output is canonical: the tool writes its own sections in one stable form and order, so two exports differ only where decisions differ and diffs stay reviewable.
The opening experiment checks all three at once. Save→load→save should be a fixpoint — a state the operation maps to itself, in the sense borrowed from mathematics (fixed point) — and Scale Composer’s round-trip is tested as exactly that: an imported file re-exports with untouched sections intact, and canonical ordering keeps every subsequent diff minimal.
What does a preserved section look like through a real cycle?
Take a file with one generated section and one hand-added one:
{
"color": {
"brand": {
"600": { "$type": "color", "$value": "#2563eb" }
}
},
"motion": {
"duration-fast": { "$type": "duration", "$value": "150ms" },
"duration-slow": { "$type": "duration", "$value": "400ms" }
}
}
The color section is generator territory; motion is a colleague’s
hand-built work — a color-and-scale tool has no concept of durations. Import
the file, re-derive the palette
from a new seed, export. The color.brand
entries change: brand-600 keeps its name and stores a new value in place of
the old #2563eb — oklch(0.546 0.215 262.9) — with the ramp re-derived
around it, and the diff contains those lines and nothing else. motion comes
back unchanged, both timings intact, still in its place.
Run this cycle on an imported file in Scale Composer — load a DTCG file that carries sections the tool doesn’t generate, adjust the seed, and export: the color sections re-derive while the hand-added sections ride through untouched.

What should you audit before trusting a tool with your file?
Four checks, ordered by what they catch:
- The empty round-trip. Import, change nothing, export, diff. Acceptable differences live only in sections the tool generates (canonical re-serialization); a diff that touches anything else is the tool telling you what it will eventually eat.
$extensionssurvival. The DTCG format’s designated home for tool- and platform-specific metadata is precisely the content a careless importer drops. Check that yours came through intact.- Comments — honestly, there are none to lose. DTCG is JSON, and JSON
has no comment syntax; notes that matter belong in
$descriptionfields, which are part of the format and survive any conforming tool. If your workflow has been keeping annotations somewhere fragile, the import is a good moment to migrate them there. - Ordering stability. Export twice, then export after one trivial change. If key order shuffles between runs, every future diff will bury the real change under phantom ones, and reviewing token changes becomes archaeology for as long as the file lives.
How does preservation make adoption incremental?
Because a preserving tool doesn’t demand the whole file. A team can hand it the color sections first — import, re-derive, export, review a diff that touches only color — while spacing and type remain hand-managed in the same file. Next quarter, spacing. The tool grows into the file section by section, each step a small reviewable change rather than a migration event.
This is the practical payoff of the fixpoint property, and the intuitive reason it matters: trust is built by bounded blast radius. A tool that can only rewrite everything asks for total trust on day one; a tool that preserves asks only for trust over the sections you hand it, and the sections it hasn’t earned yet were never at risk. “Switch token tools” stops being a decision and becomes a series of cheap, reversible experiments.
Run the test before you need to trust it
The audit is not hypothetical work — it is five minutes and a diff. Run the save→load→save test in Scale Composer — import a tokens file, export it untouched and compare; then make one deliberate change and confirm the diff is exactly that change and nothing more.