Appearance
Importing and exporting tokens
Introduced in v0.1 (Milestone 14).
Tessera's token files are already DTCG: the format the W3C Design Tokens Community Group publishes, which design tools are converging on. tessera tokens import and tessera tokens export move tokens between that and the shapes other tools actually write, without flattening aliases or losing a theme.
What was tested
Round trips of this repository's tokens and the full Tailwind preset (490 tokens) through each format, and fixtures written to match the known quirks of Tokens Studio and Penpot exports. It has not been run against a live Figma file or a current Tokens Studio export, so treat an import from a real file as one to read the notes of.
Export
bash
npx tessera tokens exportwrites strict DTCG 2025.10 token files and a Resolver document into .tessera/export/dtcg:
- the base files, one per file you have, as a set;
- one modifier per attribute (
theme,density), with a context per theme file. The base is the default context, so a tool that applies no modifier gets the base values; - aliases stay aliases (
{color.neutral.900}), and units stay explicit ({ "value": 16, "unit": "px" }).
A theme's $extends, $attribute and $auto are Tessera's, not DTCG's, so they are not in the theme files: the attribute is the modifier's name, and $auto (the media query that switches a theme automatically) is kept under the modifier's $extensions.tessera.
bash
npx tessera tokens export --format tokens-studio --out tokenswrites what the Tokens Studio plugin (and Penpot, which uses the same shape) reads: one file per set, $themes.json and $metadata.json. Colors and dimensions are written as the strings those tools use ("#2563eb", "16px"), and every token carries its type, because a set is read on its own. Tokens Studio has no automatic switching, so $auto is reported and not exported.
Import
bash
npx tessera tokens import tokens.resolver.json
npx tessera tokens import tokens.json
npx tessera tokens import path/to/figma-export --out system/tokensThe format is detected: a Resolver document, plain DTCG files, or Tokens Studio files (a single file, or the multi-file layout). Pass --format dtcg or --format tokens-studio to say. Everything the importer reads is turned into Tessera token files, then built before anything is written: if the result has errors, nothing is written and the errors are printed.
It never overwrites. If a file would be replaced it stops and names it; import into a new folder with --out, or pass --force.
What it does with a Resolver document
- Each set source becomes a base file of its own (so a tier set on a group is not merged away).
- The modifier's default context is the base: its values apply over the set. Every other context becomes a theme file, and the modifier's name becomes its
$attribute. - A context that adds a token the base does not have is T1011. Tessera themes only override values, and the importer reports that rather than quietly widening them.
- The files the document names are read from beside it.
What it does with Tokens Studio
Tokens Studio writes tokens as { "value": "8", "type": "spacing" }, so the importer maps its types to DTCG types and its string values to strict ones:
| Tokens Studio | DTCG |
|---|---|
color | color (hex, rgb(), hsl(), oklch() and named colors are parsed) |
spacing, sizing, borderRadius, borderWidth, fontSizes, letterSpacing | dimension ("16px", "1.5rem"; a bare number is read as pixels, with a note) |
opacity, lineHeights | number ("50%" becomes 0.5; a line height with px or rem is a dimension) |
fontFamilies, fontWeights | fontFamily, fontWeight ("SemiBold" and "Semi Bold" become 600) |
boxShadow | shadow (an array is several layers; innerShadow becomes inset) |
border, duration, cubicBezier | the same type |
References are kept: {spacing.base} and the older $spacing.base both become {spacing.base}. A name Tessera cannot use (it must work as a CSS custom property: letters, numbers, - and _) is rewritten, and so is every reference to it.
Themes come from $themes. A token set that every theme turns on is the base; a set only some themes turn on belongs to those themes, and the theme's name is the file name (density=compact sets the attribute). Design tools often define the semantic layer only in the theme sets, which Tessera's override-only themes cannot do, so a token that exists only in theme sets is added to the base with the first theme's value, and the importer says how many. Without $themes, all the sets are merged into the base in order.
What it skips
Some things cannot be written as a Tessera token: a gradient, a typography or composition composite, a math expression such as {spacing.base} * 2, an em or percent letter spacing, or a token that references one of those. Each is skipped with a T1016 note that names it, and kept under $extensions.tessera.skipped in the file it came from. Nothing disappears silently, and tessera tokens export puts the skipped tokens back, so a design tool's own token survives a trip through Tessera.
The Figma mapping
Tessera does not ship a Figma plugin. The route from Figma is through a tool that writes tokens, and the mapping is the same in each:
| Figma variables | Tessera |
|---|---|
| A collection | A group of tokens (or a set, in a Tokens Studio export) |
| A mode (Light, Dark, Compact) | A theme: data-theme="dark", or data-density="compact" for another attribute |
| An alias to another variable | An alias, never flattened |
| A number with a unit | An explicit { "value", "unit" } |
The ways to get variables out of Figma are a plugin that exports them as Tokens Studio sets or DTCG files, then tessera tokens import, or the Variables REST API. The REST API needs an Enterprise plan and a full seat, according to Figma's documentation, so most teams will use a plugin. Check the page before relying on either, because Figma changes its plans.
Going back, tessera tokens export --format tokens-studio gives a set per file and the $themes that combine them, which the plugin reads back into Figma variables.
Errors
- T1016: an import skipped or adjusted something. A warning that names the token.
- T1017: an import could not read what it was given (not JSON, or a Resolver that names a file you did not give).
Both commands are in the CLI reference.