Health Scoring

Buoy calculates a 0-100 health score that represents how well your codebase adheres to your design system. Higher scores mean less drift.

Score Ranges

Score Rating What It Means
80-100 Good Design system is well adopted. Minor issues only.
50-79 Fair Some drift detected. Worth addressing before it grows.
30-49 Needs Work Significant drift. Prioritize cleanup.
0-29 Poor Major drift. Design system adoption is low.

How Scores Are Calculated

The score is based on three factors:

1. Unique Value Count

Penalty for having more unique values than expected. A design system with 8 spacing tokens shouldn't have 31 different spacing values in code.

Expected: 8 spacing values
Found: 31 spacing values
Penalty: proportional to excess (23 extra = significant penalty)

2. Close Matches (Typos)

High penalty for values that are "almost" correct. These are likely mistakes:

#3b83f6 close to #3b82f6 → high penalty
15px close to 16px → high penalty

3. File Concentration

Penalty for files with many issues. A file with 47 drift signals suggests systemic problems in that area.

Dashboard.tsx: 47 issues → penalty
Card.tsx: 38 issues → penalty

Example Calculation

Starting score: 100

Colors:
  Expected: ~12, Found: 47
  Penalty: -25

Spacing:
  Expected: ~8, Found: 31
  Penalty: -20

Close matches:
  2 found
  Penalty: -12

Worst files:
  3 files with 20+ issues
  Penalty: -9

Final score: 34/100 (Poor)

Improving Your Score

Quick Wins

  • Fix typos first — Close matches are high-value fixes
  • Target worst files — Cleaning up one bad file can boost score significantly
  • Consolidate colors — Often many "blues" should be one token

Long-term Strategies

  • Add to CI — Prevent new drift from being introduced
  • Set thresholds — Require minimum scores for merge
  • Track over time — Monitor score trends

Score in CI

Use the score to gate PRs:

# Fail if score drops below 70
buoy ci --threshold 70

# Fail on any drift
buoy ci --strict

Viewing Score Details

$ buoy audit

Design System Health Report
───────────────────────────

Overall Score: 34/100 (Poor)

Score Breakdown:
  Base score:        100
  Unique values:     -25
  Close matches:     -12
  File concentration: -9
  Other penalties:   -20
  ─────────────────────
  Final:              34

Related