Run a systematic health audit of your design system — component coverage gaps, accessibility compliance, token coherence, documentation quality, and performance regression detection.
Run a systematic health audit of your design system — component coverage gaps, accessibility compliance, token coherence, documentation quality, and performance regression detection.
A design system health audit covers six dimensions, each scored 0-100:
Weight each dimension by its business impact. For most teams: accessibility and coverage carry the most weight (30% each), token coherence and documentation are medium weight (15% each), test coverage and performance are supporting metrics (5% each). Compute a single weighted health score monthly and track the trend. A health score below 70 triggers a design system improvement sprint before any new feature work.
Component coverage audit answers: 'Are teams building the same thing over and over because we do not have it?' Run this as a codebase scan looking for component class names or patterns that appear in multiple repos without a design system match:
1// scripts/coverage-audit.ts
2import { glob } from 'glob';
3import { readFileSync } from 'fs';
4
5// Patterns that indicate hand-rolled versions of common components
6const CUSTOM_COMPONENT_PATTERNS = [
7 { pattern: /class=['"].*modal.*['"]/gi, name: 'Modal', dsEquivalent: 'Dialog' },
8 { pattern: /class=['"].*dropdown.*['"]/gi, name: 'Dropdown', dsEquivalent: 'Select' },
9 { pattern: /class=['"].*toast.*['"]/gi, name: 'Toast', dsEquivalent: null }, // Gap: not in DS
10 { pattern: /class=['"].*skeleton.*['"]/gi, name: 'Skeleton', dsEquivalent: 'Skeleton' },
11];
12
13async function auditCoverage(dirs: string[]) {
14 const gaps: Record<string, { occurrences: number; repos: Set<string> }> = {};
15
16 for (const dir of dirs) {
17 const files = await glob('**/*.{tsx,html}', { cwd: dir, ignore: ['node_modules/**'] });
18 for (const file of files) {
19 const content = readFileSync(`${dir}/${file}`, 'utf8');
20 for (const { pattern, name, dsEquivalent } of CUSTOM_COMPONENT_PATTERNS) {
21 if (pattern.test(content) && !dsEquivalent) {
22 if (!gaps[name]) gaps[name] = { occurrences: 0, repos: new Set() };
23 gaps[name].occurrences++;
24 gaps[name].repos.add(dir);
25 }
26 }
27 }
28 }
29
30 return gaps;
31}Gaps appearing in 3+ repositories with 10+ occurrences are immediately added to the design system backlog as high-priority new components.
Token coherence measures how well the design system's semantic token model is being applied in component source code. Three coherence metrics: orphaned tokens (tokens defined but used nowhere), missing aliases (semantic concepts used but not tokenized), and hardcoded values (colors or spacing bypassing the token system).
1# scripts/token-coherence.sh
2#!/bin/bash
3
4DS_DIR="packages/react/src"
5TOKEN_FILE="packages/tokens/dist/tokens.css"
6
7# Extract all CSS custom property names from the token file
8echo "=== Defined Tokens ==="
9grep -oP '(?<=--)[a-z-]+(?=:)' $TOKEN_FILE | sort > /tmp/defined-tokens.txt
10wc -l /tmp/defined-tokens.txt
11
12# Find all CSS custom property uses in component source
13echo "=== Used Tokens ==="
14grep -roh 'var(--[a-z-]*)' $DS_DIR --include='*.css' \
15 | grep -oP '(?<=var\()[^)]+' | sort -u > /tmp/used-tokens.txt
16wc -l /tmp/used-tokens.txt
17
18# Orphaned tokens (defined but not used)
19echo "=== Orphaned Tokens (may be for consuming apps) ==="
20comm -23 /tmp/defined-tokens.txt /tmp/used-tokens.txt
21
22# Hardcoded colors (coherence violations)
23echo "=== Hardcoded Color Values (violations) ==="
24grep -rn '#[0-9a-fA-F]\{3,6\}\|rgb(\|hsl(' $DS_DIR --include='*.css' \
25 | grep -v 'forced-colors' | grep -v '/* allowed:'
26echo "---"
27echo "Audit complete. Review orphaned tokens and hardcoded values above."Documentation quality is subjective unless you make it objective with a rubric. Score each component's documentation on five criteria, 0-4 points each (maximum 20 points per component):
Automate scoring with a documentation parser that checks Storybook story files and MDX pages for the presence of required sections. Components scoring below 12/20 are flagged for a documentation improvement sprint in the next quarter.
Automate the quarterly health report so it is ready in minutes, not days:
1// scripts/health-report.ts
2interface HealthReport {
3 quarter: string;
4 overall: number;
5 dimensions: {
6 coverage: { score: number; trend: number; action: string };
7 accessibility: { score: number; trend: number; action: string };
8 tokenCoherence: { score: number; trend: number; action: string };
9 documentation: { score: number; trend: number; action: string };
10 testCoverage: { score: number; trend: number; action: string };
11 performance: { score: number; trend: number; action: string };
12 };
13 topIssues: string[];
14 wins: string[];
15}
16
17async function generateHealthReport(): Promise<HealthReport> {
18 const [coverage, a11y, tokens, docs, tests, perf] =
19 await Promise.all([
20 getCoverageScore(),
21 getAccessibilityScore(),
22 getTokenCoherenceScore(),
23 getDocumentationScore(),
24 getTestCoverageScore(),
25 getPerformanceScore(),
26 ]);
27
28 const overall = Math.round(
29 coverage * 0.30 + a11y * 0.30 + tokens * 0.15 +
30 docs * 0.15 + tests * 0.05 + perf * 0.05
31 );
32
33 return { quarter: getCurrentQuarter(), overall, /* ... */ };
34}
35
36// Export as Markdown and post to Confluence/Notion
37const report = await generateHealthReport();
38console.log(formatAsMarkdown(report));Post the report to your design system Storybook docs page and the engineering newsletter. The trend lines (up/down arrows on each dimension score compared to last quarter) are more valuable than the absolute scores for motivating improvement.
Run the token coherence audit script on your design system component source today. Count hardcoded color values and set a target to reduce them by 50% in the next sprint. Share the current count as your baseline.
Your progress is saved in this browser, on this device only.