Copyright © 2025 the Contributors to the Design Tokens Resolver Module Specification, published by the Design Tokens Community Group under the W3C Community Contributor License Agreement (CLA). A human-readable summary is available.
This specification extends the format and describes a method to work with design tokens in multiple contexts (such as “light mode” and “dark mode” color themes).
This specification was published by the Design Tokens Community Group. It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups.
This is a snapshot of the editors’ draft. It is provided for discussion only and may change at any moment. Its publication here does not imply endorsement of its contents by W3C or the Design Tokens W3C Community Group Membership. Don’t cite this document other than as work in progress.
This document has been published to facilitate Wide Review.
This document was produced by the Design Tokens W3C Community Group, and contributions to this draft are governed by Community Contributor License Agreement (CLA), as specified by the W3C Community Group Process.
GitHub Issues are preferred for discussion of this specification.
This section is non-normative.
Consumers of design tokens often need to express alternate values that apply in different contexts. Such examples include, but are not limited to:
However, these alternate contexts are susceptible to combinatorial explosion, making storage and management unwieldy.
This format describes a mechanism for deduplicating all repeat values of tokens across all contexts as well as enumerating all permutations of contexts.
This section is non-normative.
A trait describing two or more contexts that each operate on exclusive tokens, i.e. do not overlap. Modifiers MAY be orthogonal, but it are not required to be.
Making modifiers orthogonal as much as possible reduces cognitive load and reduces user error.
A resolution is a single possible permutation of a resolver document. A resolution maps 1:1 to an input, but the difference is the “input” refers to the modifier contexts used, whereas “resolution” refers to the final set of tokens and token values produced.
A resolver document MUST use standard JSON syntax ([RFC8259]).
Tools MAY support extensions such as JSONC or JSON5 so long as the document may be converted to normal JSON without affecting token values.
Users SHOULD use the .resolver.json
file extension to name resolver documents.
When transmitting a resolver document over HTTP, users SHOULD use the expected application/json
MIME type ([RFC6838]) in the Content-Type
header ([RFC1341]). Users SHOULD NOT use a custom or unexpected MIME type.
A resolver document contains the following properties at the root level:
Name | Type | Required | Description |
---|---|---|---|
name | string |
A short, human-readable name for the document. | |
version | YYYY-MM-DD |
Y | Version. Must be 2025-10-01 . |
description | string |
A human-readable description for this document. | |
sets | Map[string , Set] |
Definition of sets. | |
modifiers | Map[`string, Modifier] | Definition of modifiers. | |
composition | ReferenceObject[] |
Y | Resolution of sets and modifiers. |
The document MAY provide a human-readable name
at the root level. This is helpful to distinguish one resolver document from another, in case the filename itself isn’t enough.
The document MUST provide a version at the root level, and it MUST be 2025-11-01
. This is reserved for future versions in case breaking changes are introduced.
The document MAY provide a description
at the root level. This may be used to add additional explanation or context not present in name.
A set is a collection of design tokens in DTCG format. A set MUST contain a sources
array with tokens declared directly, or a reference object pointing to a JSON file containing design tokens, or any combination of the two.
A set MAY include a description
describing the purpose of the set.
If the array declares multiple sources, they will be merged in array order, meaning if a token is declared multiple times, the last occurrence in the array will be the final value. Tools MUST respect array ordering.
A modifier is similar to a set, but allows for conditional inclusion via the contexts map.
A modifier MUST declare a contexts
map of a string
value to an array of token sources. The array of tokens sources MUST be a ReferenceObject, inline tokens, or any combination of the two.
A modifier SHOULD have two or more contexts
, since one is the equivalent of a set. A modifier MUST NOT have an empty contexts
map. Tools SHOULD throw an error for modifiers with only 1 context. Tools MUST throw an error for modifiers with 0 contexts.
Like sets, array order MUST be respected such that in case of conflict, the last occurrence of a token in the array produces the final value.
A modifier MAY reference a set inside a context value. However a modifier MUST NOT reference any other modifier, not even another context inside the same modifier.
A modifier MAY declare a human-readable description
.
A modifier MAY declare a default
value that MUST match one of the keys in contexts
. Tools MUST throw an error if the value is not present in contexts
.
The number of possible resolutions a document may generate may be predicted with the product of all contexts
across all modifiers.
The composition
key is an array of sets and modifiers ordered to produce the final result of tokens. The order is significant, with tokens later in the array overriding any tokens that came before them, in case of conflict.
In composition
, a set or modifier MAY be declared inline, so long as name
and type
keys are added to the object:
Property | Type | Required | Description |
---|---|---|---|
name | string |
Y | A unique name that MUST NOT conflict with any other name in compositions . |
type | "set" | "modifier" |
Y | MUST be "set" or "modifier" according to the type. |
Tools MUST throw an error in the case where name
or type
are missing from an inline object, or if name
is duplicated among any objects.
Inline sets and modifiers MUST NOT be referenced in any way. Tools SHOULD throw an error when a reference object points to a composition item.
This section is non-normative.
The composition
array allows for any ordering of sets and modifiers to the user’s choosing. However, in the scenario that many sets must appear after the modifiers to resolve conflicts, it is likely a smell of unpredictable and brittle token organization. Ideally, modifiers handle conditional values so well they require few or no overrides (see orthogonality). In practical terms, this means that
When referring to another JSON document or a structure within the same document, a reference object MUST be used. This is described in JSON Schema 2020-12 as an object with a key of $ref
whose string is a valid JSON pointer as described in [RFC6901].
Tools MUST resolve all reference objects in a resolver document.
Reference objects MUST NOT be circular, neither referencing other pointers that reference itself, nor referencing any parent node of the reference object.
A pointer MAY point anywhere within the same document, with the exception of the following:
#/modifiers/…
). Sets and modifiers MUST NOT reference another modifier.#/composition/…
). Composition, by its nature, references many other parts of the document. Duplicating any part of composition will produce complex, hard-to-predict chains.Tools MUST throw an error if encountering any invalid pointers.
As JSON Schema 2020-12 allows, other keys MAY exist on a reference object alongside $ref
. In these scenarios, the local keys alongside $ref
MUST be treated as overrides.
If a key alongside $ref
declares an object or array, tools MUST flatten these shallowly, meaning objects and arrays are not merged.
An $extensions
object MAY be added to any set, modifier, or inline set/modifier, to declare arbitrary metadata that is up to individual tools to either use or ignore.
If provided, $extensions
MUST be an object with the keys being vendor-specific namespaces. This allows multiple tools to use this metadata without conflict.
Tools MAY allow defining structures in JSON Schema $defs but is not a requirement, and ultimately is up to the tool to decide.
A resolver document only describes how conditional token values MAY be produced. But the conditions must still be provided somewhere. The term “input” refers to any selection of context values passed to the tool.
Tools MUST accept inputs as a JSON-serializable object, such as an object in JavaScript or a dictionary in Python.
Tools that load a resolver that declares modifiers SHOULD throw an error if an accompanying input is not provided.
Inputs SHOULD be case-insensitive. For example, { "theme": "dark" }
, { "Theme": "Dark" }
, and { "THEME": "DARK" }
SHOULD be equivalent. However, tools MAY make individual decisions on case sensitivity.
Inputs MUST have strings as their values. Tools MUST throw an error if an input contains a non-string value, such as { "beta": true }
or { "size": 100 }
.
Tools MUST handle the resolution stages in order to produce the correct output.
composition
order to produce the final tokens structure.Tools MUST require all inputs match the provided modifier contexts.
If a resolver does NOT declare any modifiers, skip this step and proceed to Composition.
Tools MUST iterate over the composition array in order.
For every item in the array, determine whether it’s a set or modifier, flattening into a single tokens structure in array order.
sources
in array order to produce a single tokens structure.context
that matches the input, combining the array in order to produce a single tokens structure.Repeat until you’ve reached the end of the composition array.
The final result will be a tokens structure that behaves the same as if it were one source to begin with.
Aliases MUST NOT be resolved until this step.
After the composition has been flattened into a single tokens structure, the only remaining step is resolving aliases. Aliases are resolved the exact same way as outlined in the format:
$type
.This section is non-normative.
A resolver document allows for the use of tokens to exist in multiple JSON files for organization. But for the purposes of portability, it may be advantageous to deal with only a single JSON document.
“Bundling” refers to the process by which a resolver document may be reduced down into a single file. There are multiple strategies to accomplish this, more than this document outlines. But for the purpose of illustration, this will outline 2 of the many possible approaches:
Inlining involves taking all reference objects to remote files, and replacing them with their contents. This is a simple strategy that accomplishes the end goal, but results in duplication whenever the same file is referenced multiple times. While a tool may not have any difficulty with duplicated tokens, a human reading this document may likely struggle reading the number of lines of code this would produce.
As described in $defs, $defs
don’t have defined behavior in a resolver document. But they are valid pointers for reference objects. This strategy involves creating a top-level $defs
key, with each top-level key containing the contents for that file.
There is no downside to using $defs
other than the possibility of some tools not supporting it, since $defs
is not a requirement of this spec.
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MAY, MUST, MUST NOT, SHOULD, and SHOULD NOT in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.
Tools implementing the Resolver Specification MUST:
This section is non-normative.
This resolver spec wouldn’t have happened without the Hyma Team, including but not limited to Mike Kamminga, Andrew L’Homme, and Lilith. Significant contributions were also made by Joren Broekema, Louis Chenais. We thank the members of the Design Tokens Community Group for their contributions and feedback.