Skip to content

DTCG extensions

Reference2026-11-09

DTCG 2025.10 reserves $extensions for vendor data. What the specification cannot express, Syntope stores there under the eu.syntope.* namespace. Every file Syntope Engine writes is checked against the official schema, so files stay valid DTCG, and a tool that ignores these keys still reads the standard tokens.

A DTCG file without any Syntope keys is ordinary input. You never need to add them yourself.

Early beta. File metadata can still change between versions.

Keys on tokens and files

Key Where Holds What other DTCG tools see
eu.syntope.stringTokens Root of a token file String tokens, keyed by token path Nothing, unless they read the extension
eu.syntope.formula On a dimension or number token A calculation One calculated $value, for one theme
eu.syntope.colorExpression On a color token A base colour and one change One calculated $value, for one theme
eu.syntope.figma On a typography or number token Figma text properties The standard $value
eu.syntope.transition On a transition token The CSS property from a Tokens Studio export. Carried for other tools, Syntope does not apply it. The standard $value

String tokens

DTCG 2025.10 has no string type, so a file cannot hold "$type": "string" in its token tree. The engine moves each string token into the root $extensions of its own file. A group left empty by the move stays in the file.

{
"label": {},
"$extensions": {
"eu.syntope.stringTokens": {
"label.greeting": { "$type": "string", "$value": "Hello" }
}
}
}

Only another string token or a Syntope extension field can reference a string token. A standard token that references one cannot be exported. Do instead: give the standard token a literal value, or make it a string token too. See String.

Calculated values

DTCG 2025.10 has no arithmetic and no colour functions. A calculated token keeps its calculation in $extensions, and $value holds the result for tools that do not calculate.

{
"size": {
"$type": "dimension",
"base": { "$value": { "value": 8, "unit": "px" } },
"double": {
"$value": { "value": 16, "unit": "px" },
"$extensions": {
"eu.syntope.formula": { "expression": "{size.base} * 2", "unit": "px" }
}
}
},
"color": {
"$type": "color",
"brand": { "$value": { "colorSpace": "srgb", "components": [0, 0.4, 1] } },
"soft": {
"$value": { "colorSpace": "srgb", "components": [0, 0.4, 1], "alpha": 0.5 },
"$extensions": {
"eu.syntope.colorExpression": {
"base": "{color.brand}",
"change": { "type": "alpha", "amount": 0.5 }
}
}
}
}
}
Field Rule
formula.expression The calculation, with references in {}
formula.unit Required on a dimension token, not allowed on a number token
colorExpression.base A whole reference to a color token, or a DTCG colour
colorExpression.change.type lighten, darken, mix or alpha
colorExpression.change.space lch, hsl, srgb, p3 or oklch. Required except for alpha
colorExpression.change.amount A number, or the text of a number formula
colorExpression.change.color The second colour, only for mix

Syntope never reads the stored $value of a calculated token. It calculates the value itself, per theme.

One $value per token. The engine refreshes $value each time it writes a file, using the theme the token’s set is shown in (for a set in no theme, the theme in use). A tool that does not calculate reads that one result, even where another theme would give a different value. Do instead: if another tool needs the value of each theme, give the token a plain value in each theme’s set.

A calculated token with no value in that theme blocks the export, and an edit that causes this is refused.

The token form in Syntope Tokens, the Figma plugin, does not offer calculations in this beta. A token that carries one shows its result, and typing a new value replaces the calculation. Do instead: add or change the calculation in the JSON editor, through an AI app, or by importing it.

Figma text properties

Figma can do more with text than DTCG typography can express, and DTCG forbids extra keys in a typography $value. These fields go in eu.syntope.figma on a typography token.

{
"text": {
"body": {
"$type": "typography",
"$value": {
"fontFamily": "Inter",
"fontSize": { "value": 16, "unit": "px" },
"fontWeight": 400,
"letterSpacing": { "value": 0, "unit": "px" },
"lineHeight": 1.5
},
"$extensions": {
"eu.syntope.figma": {
"lineHeight": { "unit": "PIXELS", "value": 24 },
"textCase": "UPPER"
}
}
}
}
}
Field Holds
paragraphSpacing, paragraphIndent A DTCG dimension
textDecoration NONE, UNDERLINE or STRIKETHROUGH
textCase ORIGINAL, UPPER, LOWER, TITLE, SMALL_CAPS or SMALL_CAPS_FORCED
fontStyle The exact Figma face, such as Medium Italic
lineHeight { "unit": "PIXELS", "value": 24 }, { "unit": "PERCENT", "value": 150 } or { "unit": "AUTO" }
letterSpacing A percentage of the font size, such as -2%
keep The DTCG typography fields left to the layer when the token is applied

Each field can hold a reference to another token instead of a literal.

fontStyle, lineHeight and letterSpacing take precedence over the matching standard fields in Syntope and in Figma. So that other tools read sensible values, the engine refreshes literal fontWeight, lineHeight and letterSpacing values in $value from them each time it writes a file.

On a number token, the only field is lineHeight, with the unit alone: { "unit": "PERCENT" } or { "unit": "AUTO" }. $value is the ratio for PERCENT and 1.2 for AUTO. A pixel line height is a dimension token, not a marked number. See Typography and Number.

Keys that keep project structure

These keys let the plugin read back exactly what it wrote. The engine reads them back into the project’s structure, and they change no token value. A tool that ignores them loses nothing it needs.

Key Where Holds
eu.syntope.tokenSource Root of a token file The set’s id, location and order
eu.syntope.resolverSet On a set in the Resolver file id and order
eu.syntope.resolverModifier On a modifier in the Resolver file id and order
eu.syntope.authoring On the Base set in the Resolver file version, the sidebar order (sidebarOrder) and theme groups with one theme (disabledThemeGroups)
eu.syntope.tokenSources Under $defs in a single-file project, not in $extensions Token sets that a single Resolver file has no other place for, such as sets left out of Base and every theme

Token IDs are not written to files. See Stable IDs.

What happens to extensions

  • Other vendors’ extensions stay. The engine keeps any other namespace on a token as it found it.
  • Changing a token’s type in the plugin removes eu.syntope.formula, eu.syntope.colorExpression, eu.syntope.figma and eu.syntope.transition from it, because their meaning depends on the type. Undo in the plugin restores them, for up to 50 steps and until the plugin closes.
  • A Tokens Studio export is converted without reading any eu.syntope.* key it contains. The conversion writes its own.