Get started
Check a local DTCG file and build token files with Primitree.
You need Node.js 24 or newer. Contributors working in this monorepo need pnpm 11 or newer.
1. Install the CLI
pnpm add -D @primitree/cli@next2. Add a DTCG token file
Create tokens.json with a base layer and a semantic layer. Semantic tokens
reference the base values they use.
{
"base": {
"motion": {
"quick": {
"$type": "duration",
"$value": { "value": 0.2, "unit": "s" }
}
},
"type": {
"family": {
"$type": "fontFamily",
"$value": ["Atkinson Hyperlegible", "sans-serif"]
},
"weight": { "$type": "fontWeight", "$value": 650.5 }
}
},
"semantic": {
"motion": {
"quick": { "$type": "duration", "$value": "{base.motion.quick}" },
"control": {
"$type": "duration",
"$value": "{semantic.motion.quick}"
}
},
"type": {
"family": {
"$type": "fontFamily",
"$value": "{base.type.family}"
},
"body": {
"$type": "fontFamily",
"$value": "{semantic.type.family}"
},
"weight": {
"$type": "fontWeight",
"$value": "{base.type.weight}"
},
"emphasis": {
"$type": "fontWeight",
"$value": "{semantic.type.weight}"
}
}
}
}3. Add the source config
Create primitree.config.ts next to tokens.json.
export default {
schemaVersion: 1,
sources: {
brand: {
type: 'dtcg',
file: './tokens.json',
architecture: {
layers: [
{ id: 'base', roots: ['base'], values: 'literal' },
{
id: 'semantic',
roots: ['semantic'],
values: 'reference',
references: ['base', 'semantic'],
},
],
},
ownership: { default: ['design-systems'] },
outputs: {
directory: './generated',
formats: ['dtcg', 'css', 'typescript', 'tailwind'],
},
},
},
}The config gives the source the name brand. It allows literal values in
base and aliases in semantic. Paths are relative to the config file.
4. Check and inspect the source
pnpm exec primitree check --source brand
pnpm exec primitree inspect semantic.motion.control --source brandcheck reports layer and owner findings. It rejects invalid token types,
references, and cycles. inspect reports the resolved value and the alias
chain for one token.
5. Compare a change
Save a copy of the source file:
cp tokens.json before.tokens.jsonChange base.motion.quick.$value.value in tokens.json from 0.2 to 0.3.
Compare the files:
pnpm exec primitree diff before.tokens.json tokens.json --source branddiff reports the tokens that changed between the saved file and the edited
file.
6. Build the files
pnpm exec primitree build --source brandThe build writes these files to generated/:
generated/
├── .primitree-manifest.json
├── css/tokens.css
├── css/tokens.tailwind.css
├── tokens/source.tokens.json
├── tokens/tokens.resolver.json
└── ts/tokens.ts7. Check generated files in CI
pnpm exec primitree build --source brand --checkbuild --check reports missing, changed, and unexpected output files without
writing. It exits with code 0 when the files match and code 1 when they
differ.
Figma export follow-up
Use the Primitree export plugin when local Figma
variables are the starting point. The plugin saves a variables.json export.
Run pnpm exec primitree build variables.json to convert that export. Figma
REST access requires access to the Figma file, a Figma Enterprise seat, and a
Personal Access Token with file_variables:read. Set the token in
FIGMA_TOKEN or FIGMA_PAT, and set the file key in FIGMA_FILE_KEY. Run
pnpm exec primitree export.