Editor tools for working with DTCG formatted design tokens in CSS, HTML, JavaScript/TypeScript (lit-element), and for token definitions in JSON or YAML files.
Supports both Editor's Draft and DTCG 2025.10 stable schema versions, including multi-schema workspaces where different token files use different schema versions.
Note
This is pre-release software. If you encounter bugs or unexpected behavior, please file a detailed issue.
Display markdown-formatted token descriptions and value when hovering over token names.
Auto complete for design tokens - get code snippets for token values with optional fallbacks.
DTLS complains when your stylesheet contains a var() call for a design token,
but the fallback value doesn't match the token's pre-defined $value.
Toggle the presence of a token var() call's fallback value. Offers to fix
wrong token definitions in Diagnostics.
Display token color values in your source, e.g. as swatches.
Highlight token references inside token definition files.
Jump to the position in the tokens file where the token is defined. Can also jump from a token reference in a JSON file to the token's definition.
Go to definition in a split window using Neovim's <C-w C-]> binding,
which defers to LSP methods when they're available.
Locate all references to a token in open files, whether in CSS or in the token definition JSON or YAML files
DTLS supports both DTCG schema versions:
-
Editor's Draft - Original DTCG format
- String color values (hex, rgb, hsl, named colors)
- Curly brace references:
{color.brand.primary} - Group markers for root tokens:
_,@,DEFAULT
-
2025.10 Stable - Latest stable specification
- Structured color values with 14 color spaces (sRGB, oklch, display-p3, etc.)
- JSON Pointer references:
$ref: "#/color/brand/primary" - Group inheritance:
$extends: "#/baseColors" - Standardized
$roottoken for root-level tokens - All draft features (backward compatible)
DTLS can load multiple token files with different schema versions simultaneously:
{
"designTokensLanguageServer": {
"tokensFiles": [
"legacy/draft-tokens.json", // Editor's Draft
"design-system/tokens.json" // 2025.10 (auto-detected from $schema)
]
}
}Schema version detection priority:
$schemafield in the token file (recommended)- Per-file
schemaVersionconfig inpackage.json - Duck-typing based on features (structured colors,
$ref,$extends) - Defaults to Editor's Draft for ambiguous files
For more information, see Schema Versioning Guide.
Download the latest release for your platform and place the binary in your
$PATH, renaming it to design-tokens-language-server.
Using native Neovim LSP (see :help lsp for more
info):
Create a file like ~/.config/nvim/lsp/design_tokens_ls.lua:
---@type vim.lsp.ClientConfig
return {
cmd = { 'design-tokens-language-server' },
root_markers = { '.git', 'package.json' },
filetypes = { 'css', 'html', 'javascript', 'javascriptreact', 'typescript', 'typescriptreact', 'json', 'yaml' },
settings = {
dtls = {
-- Optional: configure global token files
tokensFiles = {
{
path = "~/path/to/tokens.json",
prefix = "my-ds",
},
},
-- Optional: configure group markers
groupMarkers = { '_', '@', 'DEFAULT' },
}
},
-- Optional: enable document color support
on_attach = function(client, bufnr)
if vim.lsp.document_color then
vim.lsp.document_color.enable(true, bufnr, {
style = 'virtual'
})
end
end,
}Then configure your LSP setup to load configs from ~/.config/nvim/lsp/. This allows
you to manage each language server in its own file. See the
neovim docs for details on setting up native LSP clients.
Tip
If your tokens are in node_modules (e.g., npm:@my-ds/tokens/tokens.json),
the default root_markers may find the wrong package.json. The example
above uses { '.git', 'package.json' } which prefers .git over nested
package.json files - this works for most git-based projects.
For non-git projects or monorepos, use a custom root_dir that explicitly
skips node_modules:
root_dir = function(bufnr, on_dir)
local root = vim.fs.root(bufnr, function(name, path)
if name == 'package.json' and not path:match('node_modules') then
return true
end
return name == '.git'
end)
if root then on_dir(root) end
end,Install from the VS Code Marketplace.
The extension includes the language server binary, so no additional installation is required.
Install from the Zed Extensions page, or search for "Design Tokens" in Zed's extension panel.
In order to use DTLS, you need to first configure it to know where to find your design tokens, and you can also provide it with options for how to deal with them.
Design Tokens Language Server uses the DTCG format for design tokens. If you have a design token file in a different format, you can use style-dictionary to convert it to DTCG.
DTLS automatically detects which schema version your token files use based on
file contents (duck-typing). It looks for features like structured color values,
$ref, and $extends to identify 2025.10 stable, falling back to Editor's
Draft for ambiguous files. See Schema Versioning Guide
for details on detection and migration.
You can configure the language server globally or on a per-project basis.
Per-project configuration is done via a designTokensLanguageServer block in
your project's package.json.
Note
If you have better ideas on how to source token files in a given project, Please open an issue with your suggestions.
Add a designTokensLanguageServer block to your project's package.json, with
references to tokens files. Entries under tokensFiles can be either a string
or an object with path and prefix properties. The path property can be a
relative path or a deno-style npm specifier.
{
"name": "@my-design-system/elements",
"designTokensLanguageServer": {
"prefix": "my-ds",
"tokensFiles": [
"npm:@my-design-system/tokens/tokens.json",
{
"path": "npm:@his-design-system/tokens/tokens.json",
"prefix": "his-ds",
"groupMarkers": ["GROUP"]
},
{
"path": "./docs/docs-site-tokens.json",
"prefix": "docs-site"
},
{
"path": "~/secret-projects/fanciest-tokens.json",
"prefix": "shh"
}
]
}
}When using npm: specifiers for token packages, DTLS normally resolves them
from node_modules. If the package isn't installed locally, you can enable
network fallback to fetch tokens from a CDN (default:
unpkg.com, configurable via the cdn option).
This is opt-in and disabled by default.
{
"designTokensLanguageServer": {
"networkFallback": true,
"networkTimeout": 30,
"cdn": "unpkg",
"tokensFiles": [
"npm:@my-design-system/tokens/tokens.json"
]
}
}Set designTokensLanguageServer.networkFallback to true in your VS Code
settings.
cdn: unpkg
files:
- npm:@my-design-system/tokens/tokens.jsonNote: The .config/design-tokens.yaml format supports the cdn option, but
networkFallback and networkTimeout must be set via package.json or VS Code
settings.
| Option | Type | Default | Description |
|---|---|---|---|
networkFallback |
boolean |
false |
Enable CDN fallback for package specifiers |
networkTimeout |
number |
30 |
Max seconds to wait for CDN requests |
cdn |
string |
"unpkg" |
CDN provider: unpkg, esm.sh, esm.run, jspm, jsdelivr |
- Network fallback is opt-in -- it never fetches from the network unless explicitly enabled
- Responses are limited to 10 MB to prevent resource exhaustion
- Requests have a configurable timeout (default 30 seconds)
- Only
npm:specifiers with a file component trigger CDN lookups
You can set up global configuration in your editor's LSP settings for DTLS. This
configuration will be used as fallbacks for all projects. There's no need to set
them if your project already has a designTokensLanguageServer block in its
package.json.
For example, in your lsp config for neovim:
return {
cmd = { 'design-tokens-language-server' },
root_markers = { 'package.json', '.git' },
filetypes = { 'css', 'html', 'javascript', 'javascriptreact', 'typescript', 'typescriptreact', 'json', 'yaml' },
settings = {
dtls = {
tokensFiles = {
{
path = "~/path/to/tokens.json",
prefix = "my-ds",
},
}
}
}
}The DTCG format does not require a prefix for tokens, but it is recommended to
use a prefix to avoid conflicts with other design systems. if your token files
do not nest all of their tokens under a common prefix, you can pass one yourself
in the prefix property of the token file object.
Important
Group markers are only used with Editor's Draft schema. The 2025.10 stable
specification uses the standardized $root reserved token name instead.
Because the DTCG format is nested, a conflict can emerge when the token file
author wants to define a group of tokens, but have the group name also be a
token. For example, --token-color-red and --token-color-red-darker are both
valid tokens, but unless the author manually prefixes each token in the red
group with red-, it would not be possible to define a token called
--token-color-red.
Editor's Draft Schema: Design Tokens Language Server uses "group markers" to contain the token data for a group. The group marker is a well-known token name that is used to represent the group's top-most token.
The default group markers are _, @, and DEFAULT, because those are
examples mentioned in the various issues on DTCG and style-dictionary which
address the problem of tokens which are also groups.
If you include the groupMarkers property (either project-wide or for a
specific token file), then tokens with the same name as any of the group markers
will be treated as a group, and that tokens's data will be used for the group
name, minus the group marker.
2025.10 Stable Schema:
Use the standardized $root reserved token name instead of group markers. No
configuration needed.
Editor's Draft Example:
{
"color": {
"red": {
"_": {
"$value": "#FF0000",
"$description": "Red color"
},
"darker": {
"$value": "#AA0000",
"$description": "Darker red color"
}
}
}
}This creates tokens: --color-red and --color-red-darker.
Configure group markers in package.json:
"designTokensLanguageServer": {
"prefix": "my-ds",
"groupMarkers": ["_"],
}2025.10 Example:
{
"$schema": "https://www.designtokens.org/schemas/2025.10/format.json",
"color": {
"red": {
"$root": {
"$type": "color",
"$value": {
"colorSpace": "srgb",
"components": [1.0, 0, 0],
"alpha": 1.0
}
},
"darker": {
"$type": "color",
"$value": {
"colorSpace": "srgb",
"components": [0.67, 0, 0],
"alpha": 1.0
}
}
}
}
}This creates the same tokens: --color-red and --color-red-darker. No
configuration needed - $root is standardized.
See CONTRIBUTING.md








