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.
Design tokens often need to express alternate values in different contexts. What defines a “context” is up to the user to determine, and is unique to their usecases. But common examples of contexts are:
A resolver outlines a way to generate different end values (or sometimes even different tokens) to satisfy the needs for all these contexts. The general process is:
One would simply repeat the process once per the number of end-contexts being generated.
The mechanism by which multiple possible values of design tokens are reduced to a single value, i.e. this module.
Context is up to the end user to define, but is “any condition that requires a different value for a design token.” There are no official contexts in this specification.
Subsets of tokens that collectively form the default base set. Users SHOULD ensure the sum total of sets contain mutually exclusive tokens, i.e. they don’t overwrite one another and may be combined in any order to produce the same result.
Mapping of contexts to token impacts. Modifiers MAY accept an input that determine the final token values after the resolver has run.
The user’s selection for the modifiers, expressed as a key–value map. See example.
The process of combining token sets and applying modifiers based on the specified inputs to produce the final set of tokens.
The characteristic of modifiers that do not overlap with one another, i.e. operate on different tokens. Modifiers MAY be orthogonal, but it are not required to be.
A resolver is a JSON object with the following properties:
Name | Type | Required | Description |
---|---|---|---|
name | string |
A short, human-readable name for the resolver. | |
version | YYYY-MM-DD |
Y | Version, expressed as a ISO 8601 date. |
description | string |
Additional information about the resolver’s purpose. | |
tokens | (Set | Modifier)[] | Y | Resolution order of tokens. |
Users SHOULD name resolver files with a .resolver.json
syntax.
A resolver MAY provide a human-readable name. This is used to identify the resolver.
MUST be 2025-10-01
. Reserved for future versions in case breaking changes are introduced.
{
"name": "Marketing Design System",
"version": "2025-10-01"
}
A resolver MAY provide additional information.
The tokens key is an array that may contain any combination of sets and modifiers. The order is significant, with tokens later in the array overriding any tokens that came before them, in case of conflict.
Name | Type | Required | Description |
---|---|---|---|
type | "set" |
Y | MUST be "set" . |
name | string |
Optional human-readable name for this set. | |
sources | <token-defs> | Y | The tokens that belong to this set. |
File strings from sources
MAY be hoisted into the top-level tokens array as a simpler syntax.
Inline tokens (objects) MUST NOT ever be declared in tokens. An object inside tokens MUST be either a set or modifier.
A modifier can be thought of as a “conditional set,” where its contents depends on an external input. T
Name | Type | Required | Description |
---|---|---|---|
type | "modifier" |
Y | This MUST be "modifier" . |
name | string |
Y | The name of the modifier. This MUST be unique among other modifiers in the same file. |
context | Record<string, <token-set>> |
Y | A key–value map of contexts to <token-defs>. |
default | string |
Optional default value. MAY be provided in case the input doesn’t require this value. |
Tools MUST throw an error if 2 modifiers with the same name are declared in tokens.
An input is a mapping of modifier names to modifier values declared in any resolver. Inputs are not part of the resolver file itself, rather, provided to the tool alongside the resolver. A resolver that declares any modifiers MUST be consumed with an input as options.
An input SHOULD be serializable to a JSON object. Meaning, an input MAY be expressed in any programming language, but that expression should be easily converted back into a JSON object. Related concepts would include 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.
Modifiers are said to be orthogonal when they do not operate on the same set of tokens. In practical terms, if modifiers are orthogonal, then the order in which they are applied isn’t significant since they will produce the same values.
Implementors SHOULD make modifiers orthogonal. Tools MAY decide how to handle non-orthogonal modifiers.
An array consisting of:
string
which MUST be a valid URI pointing to a valid Tokens JSON file, orAny other inputs are invalid.
The array order is significant, where tokens with the same name overwrite previous instances of that token, if any.
An $extensions
object MAY be added to any set, modifier, or object in this spec to declare arbitrary metadata ignored by tooling. Its purpose in a resolver is the same as in the format.
Tools MUST handle the resolution stages in this order to produce the correct output.
Tools MUST require all inputs meet the schema described in that resolver’s modifiers syntax.
If a resolver does NOT declare any modifiers, skip this step and proceed to Sets flattening
Tools MUST iterate over the tokens array in order.
name
, with a single item in the sources
array.sources
MUST be resolved in array order.Every modifier is applied in order, taking in the external input inputs.
default
context.default
context, throw an error and stop resolution.Conflict resolution occurs when flattening sets or applying modifiers, and a token name appears by tokens of different values, from different sources. In many cases, this is intentional, but not always.
When 2 tokens try and occupy the same space, tools MUST resolve the conflict in the following manner:
$type
is unknown), overwrite the value.Alias resolution may only done after all sets and modifiers are handled, and there are no other tokens to merge in. Resolve aliases the same way as outlined in the format, allowing deep aliases but erring and stopping resolution on circular aliases and/or aliases that point to unresolvable types (such as aliasing a dimension token inside a gradient token, which is invalid).
After all aliases resolve correctly in the final set, the end result is one tokens object, that behaves as if it was a single JSON file to begin with.
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, and SHOULD 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.
Referenced in:
Referenced in: