Linting for off-system values

Run ds-lint to find hardcoded colors and sizes, tell an exact match from a near-miss, and apply safe fixes — without ever losing control of your code.

ds-lint

What you’ll learn

Welcome back. In Getting started you ran ds-bridge once and saw a list of findings. This time we’ll slow down and read that list properly — what each finding means, which ones are safe to fix automatically, and how ds-bridge quietly watches your edits so off-system values never sneak in unnoticed.

A quick word for designers and managers reading along: an off-system value is just a color, size, or shadow typed in by hand instead of pulled from the design system. ds-bridge’s job is to spot those and point at the design token that should have been used. Nothing here requires you to write code.

Setup

You’ll need the ds-bridge plugin installed and a project with a design-token file. If that isn’t done yet, Getting started covers install and setup — start there and come back.

# Lint a folder, pointing at your token source explicitly.
ds-bridge lint src --tokens tokens.json

Steps

  1. Run the lint and read the summary first. Every run leads with a count and ends with a table grouped by kind. Here is a real run against the sample project that ships with ds-bridge:

    7 findings
    
    src/Banner.tsx
      src/Banner.tsx:9:24  exact  color: "#3b82f6" — use token color.brand.primary
      src/Banner.tsx:9:44  near  padding: 17 — near token(s): space.md
    src/Hero.tsx
      src/Hero.tsx:4:9  off-system  color: #ff00aa — no matching token (off-system)
    src/button.css
      src/button.css:2:9  exact  color: #3b82f6 — use token color.brand.primary
      src/button.css:3:14  near  background: #3a81f5 — near token(s): color.brand.primary, color.base.blue-500
      src/button.css:4:11  near  padding: 17px — near token(s): space.md
    src/card.module.css
      src/card.module.css:6:24  exact  box-shadow: #11182733 — use token shadow.card
    
    ┌────────────┬───────┐
    │ kind       │ count │
    ├────────────┼───────┤
    │ exact      │     3 │
    │ near       │     3 │
    │ off-system │     1 │
    └────────────┴───────┘
    
  2. Tell the three kinds apart. This is the heart of ds-lint:

    • exact — the value is a token, byte for byte. #3b82f6 equals color.brand.primary. There is no judgement to make: it should be the token. Safe to rewrite automatically.
    • near — the value resembles a token but isn’t identical. #3a81f5 is a hair off color.brand.primary; 17px is close to the 16px space.md. A near-miss might be a deliberate one-off, or it might be a typo that should snap to the token — only a human can say.
    • off-system — nothing in the design system is close. #ff00aa has no token at all. It’s either a true exception or a sign the system is missing a token.
  3. Apply only the safe fixes. Re-run with --fix. ds-bridge rewrites exact matches to a var(--…) reference and leaves everything else exactly as it was:

    Changed 2 files.
    

    Read that carefully — only two files changed, even though there were three exact findings. The third, box-shadow: #11182733, is a composite token (a shadow with offset and blur), which --fix can’t safely express as a single var(), so it stays put and keeps showing up until you adjust it by hand. After the fix, a re-run confirms the near-misses and off-system value are untouched:

    src/button.css:3:14  near  background: #3a81f5 — near token(s): color.brand.primary, color.base.blue-500
    src/button.css:4:11  near  padding: 17px — near token(s): space.md
    src/Hero.tsx:4:9  off-system  color: #ff00aa — no matching token (off-system)
    src/card.module.css:6:24  exact  box-shadow: #11182733 — use token shadow.card
    

Result

You can now read any ds-lint run at a glance: the summary table tells you the shape of the problem, and each finding’s kind tells you what to do. Exact matches are mechanical — let --fix handle them. Near-misses and off-system values are conversations, not corrections.

Two things make this effortless day to day:

Next, see how the same token source can drift away from your built CSS in Catching token drift.

Troubleshooting