@designesy/tokens
v0.2.2
Published
Standalone DTCG 2025.10 design token validator — 20 conformance checks, zero dependencies, works offline.
Maintainers
Readme
@designesy/tokens
Standalone DTCG 2025.10 design token validator. 20 conformance checks. Zero dependencies. Works offline.
Why
The W3C Design Tokens Format Module reached its first stable version (2025.10) on October 28, 2025, backed by 24+ organizations including Adobe, Google, Meta, and Figma. Token adoption is at 84% of teams.
But no standalone DTCG validator CLI exists on npm. Terrazzo has co check, but it's bundled inside a full token compiler. This package is the first focused, standalone DTCG validator — the npm audit of design tokens.
Install
# One-off (no install needed)
npx @designesy/tokens tokens.json
# Or install locally
npm install --save-dev @designesy/tokensUsage
Validate a local file
npx @designesy/tokens tokens.jsonOutput:
Designesy Tokens Validator — DTCG 2025.10
Source: tokens.json
Tokens: 47
Score: 90/100 Grade: A — 18 pass, 2 warn, 0 fail
✓ t01 PASS Every token has $type (direct or inherited)
✓ t02 PASS Every token has $value
✓ t03 PASS Semantic tokens have $description
~ t04 WARN Color tokens use OKLCH or Display-P3
3 primitive color(s) using legacy hex (valid DTCG, should migrate to OKLCH)
✓ t05 PASS Custom types namespaced under $extensions
✓ t06 PASS Aliases resolve to valid typed tokens
~ t07 WARN $schema property present
✓ t08 PASS DTCG 2025.10 structural validation
✓ t09 PASS No type drift between themes
✓ t10 PASS Dimension units are px or rem only
✓ t11 PASS $type is one of 15 valid spec types
✓ t12 PASS Token names don't start with $ (except $root)
✓ t13 PASS Token names don't contain {, }, or .
✓ t14 PASS $value matches $type structure (primitives)
✓ t15 PASS Color value well-formedness
✓ t16 PASS Composite type structure
✓ t17 PASS Canonical $value:"{ref}" alias syntax
✓ t18 PASS Alias type compatibility
✓ t19 PASS Circular reference detection
✓ t20 PASS $deprecated value valid
Result: PASS with 2 warning(s)Validate a remote URL
npx @designesy/tokens https://www.designesy.org/export/dtcgCI gate — fail if score below threshold
npx @designesy/tokens tokens.json --min-score 80
# Exit code 0 if score ≥ 80, exit code 1 if belowJSON output for piping
npx @designesy/tokens tokens.json --jsonQuiet mode (only output on failure)
npx @designesy/tokens tokens.json --quietThe 20 Checks
| ID | Check | PASS | WARN | FAIL |
|----|-------|------|------|------|
| t01 | Every token has $type (direct or inherited) | All typed | — | Any missing |
| t02 | Every token has $value | All valued | — | Any missing |
| t03 | Semantic tokens have $description | All described | Primitive missing | Semantic missing |
| t04 | Color tokens use OKLCH or Display-P3 | All structured | Legacy hex primitives | Semantic uses bare hex |
| t05 | Custom types namespaced under $extensions | Namespaced | — | Bare custom type |
| t06 | Aliases resolve to valid typed tokens | All resolve | — | Dangling reference |
| t07 | $schema property present | Present | Missing (no editor validation) | — |
| t08 | DTCG 2025.10 structural validation | Passes | — | Schema violation |
| t09 | No type drift between themes | Consistent | — | Drift detected |
| t10 | Dimension units are px or rem only | Valid units | — | Invalid unit |
| t11 | $type is one of 15 valid spec types | All valid | — | Invalid type name |
| t12 | Token names don't start with $ (except $root) | All valid | — | Name starts with $ |
| t13 | Token names don't contain {, }, or . | All valid | — | Forbidden character |
| t14 | $value matches $type structure (primitives) | All conform | — | Value/type mismatch |
| t15 | Color value well-formedness | All well-formed | — | Malformed color |
| t16 | Composite type structure | All valid | — | Missing required child |
| t17 | Canonical $value:"{ref}" alias syntax | All valid | — | Invalid alias syntax |
| t18 | Alias type compatibility | All compatible | — | Type mismatch |
| t19 | Circular reference detection | No cycles | — | Circular chain detected |
| t20 | $deprecated value valid | All valid | — | Invalid value type |
Scoring
20 checks. PASS = 1 point, WARN = 0.5 points, FAIL = 0 points.
Score = (points / 20) × 100
| Grade | Score | |-------|-------| | A | ≥ 90 | | B | ≥ 80 | | C | ≥ 70 | | D | ≥ 60 | | F | < 60 |
Programmatic API
import { validateTokens, validateTokenString } from '@designesy/tokens';
// From a parsed object
const result = validateTokens(tokenJsonObject, 'tokens.json');
console.log(result.score); // 90
console.log(result.grade); // 'A'
console.log(result.valid); // true (no FAILs)
// From a JSON string
const result2 = validateTokenString(jsonString, 'tokens.json');
if ('error' in result2) {
console.error(result2.error);
}GitHub Actions
Use this package as a CI gate to validate your design tokens on every PR. The example below uses SHA-pinned actions — the 2026 supply-chain security best practice. Dependabot bumps the SHAs when new versions land.
name: Validate design tokens
on: [pull_request]
permissions:
contents: read
jobs:
tokens:
runs-on: ubuntu-latest
steps:
# SHA-pinned (replace with current SHAs from the action repos)
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af573 # v4.2.2
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: '22'
- run: npx @designesy/[email protected] tokens.json --min-score 80Or use the composite action (no Node setup needed):
- uses: LE-VAI/designesy-org/.github/actions/tokens-validate@main
with:
url: https://example.com/tokens.json
min-score: 80Spec Reference
License
MIT © Designesy
