/

How to Run a Design System Consistency Audit in Code

Audit design system drift across components, tokens, and UI states. Build an evidence inventory, record justified exceptions, and prioritize practical fixes.

Serafim Korablev
Serafim Korablev
@korablev

A design system consistency audit compares the interface a team ships with the components, tokens, and patterns it has agreed to use. The deliverable should be a prioritized list of evidenced differences, with an owner and a disposition for each one.

Start with one important journey, such as creating a project and inviting a teammate. Include the pages, dialogs, forms, and feedback states along that journey. This gives the first audit a boundary you can finish and a workflow against which to validate changes.

The method below is a proposed audit workflow. Its example findings illustrate decisions to make; they are not measurements from a customer codebase.

1. Establish what counts as the system

Identify the approved component source, token definitions, and documentation. Record which source decides a disagreement. If the design file shows a retired button while current production and the maintained component agree, “match the design file” needs a decision from an owner.

Tokens can carry a name, value, type, and description, and can reference other tokens. The Design Tokens Community Group format formalizes an exchange format for this information. An audit can use an existing token setup without requiring migration to that format.

Write down the roles you intend to compare: primary action, secondary action, body text, muted text, page heading, panel surface, and destructive feedback. A comparison becomes more useful when it asks whether two elements have the same job.

2. Build an inventory around repeated decisions

For the selected journey, collect component imports and variants, repeated local implementations, typography roles, semantic color usage, and state coverage. Pair source locations with screenshots when available.

Use a compact inventory such as this:

AreaIntended patternObserved implementationEvidence to collect
Invite actionShared primary ButtonLocal button markupAPI comparison and pending state
Supporting textMuted foreground tokenLiteral color valueComputed color in both themes
Page headingEstablished heading roleNew text sizeEquivalent page comparison
Failed invitationShared inline error patternGeneric toast onlyReproduction after server failure

Treat these as candidate findings. A local wrapper may add useful domain behavior while still using the approved primitive. A literal color may be an external brand requirement. Both need inspection before classification.

3. Compare semantics before comparing raw values

Two elements can look identical today and still follow different rules. One may use a semantic foreground token while the other hardcodes the token's current value. Conversely, two different values may be intentional because they serve different roles.

In shadcn/ui, semantic variables pair backgrounds with corresponding foregrounds and support theme-specific values. The official theming documentation provides a concrete example of this model.

For each candidate, ask: what role is this value expressing, where is that role defined, and what should happen when the theme changes? This turns “too many shades of gray” into a fix the maintainer can evaluate.

Do not call a low-contrast shared token correct merely because it is shared. Text contrast needs its own check; WCAG defines different minimum contrast requirements for ordinary and large text, with specified exceptions. W3C's Contrast Minimum guidance explains the requirements and their scope.

4. Audit states of the real component

Review a component in the conditions that reveal its contract: a long label, pending work, disabled access, an error, narrow space, and each supported theme. Select states relevant to that component instead of creating every possible combination.

Storybook stories capture rendered component states, and args supply component inputs. This can make an existing story collection a useful audit inventory. Storybook's writing-stories documentation explains that structure.

If the team does not use Storybook, use an existing component preview or a controlled application fixture. Keep the actual component under review. A separately drawn lookalike cannot establish whether changing the shared implementation preserves its consumers.

5. Record exceptions as decisions

Give every confirmed difference one disposition: fix it, approve an exception, propose a system change, or investigate missing evidence.

An exception register can be small:

FieldExample entry
SurfaceCustomer brand preview
DifferenceUses a customer-supplied accent color
ReasonThe feature previews that customer's branding
BoundaryPreview area only; surrounding controls use product tokens
OwnerFeature maintainer
Revisit triggerTheme editor redesign

Prefer a specific boundary and revisit trigger to “approved for now.” When the same exception appears in several independent features, ask whether it should become an explicit system variant.

6. Prioritize by consequence and reach

For the first repair batch, select findings with a demonstrated user consequence or a repeated pattern across the audited journey. A hidden primary action deserves attention before a barely different decorative radius.

Record the component's reach before changing it. A shared primitive needs representative consumer checks; a local style may allow a smaller correction. Choose a few changes whose outcomes can be reviewed clearly instead of mixing a broad token migration with a feature release.

For each finding, include the route, state, source location, expected pattern, observed difference, proposed change, and verification needed. Mark source-based inferences separately from behavior reproduced in the rendered interface.

7. Keep drift from returning

After repairs, add the approved rule where authors and reviewers will encounter it: component documentation, examples, or the pull request checklist. Link to the correct component and state when possible.

For AI-assisted work, context and discovery belong upstream. Why agents invent components covers that problem; a private component registry can make approved options easier to find.

Track confirmed recurrence within a stated scope, rather than treating the raw number of search matches as a quality score. A useful follow-up question is whether another PR reintroduced the same rejected button variant after the rule became available.

Design Bug Bot reviews changes against repository components and styling patterns, offering findings and suggested code as another input to ongoing consistency review.

Frequently asked

How often should a design system audit run?
Tie it to a useful event: a substantial UI release, a theme migration, repeated review findings, or the addition of a major product area. Use ongoing PR review for the smaller changes between audits.
Should the audit remove every duplicate component?
First compare responsibilities and supported states. Consolidate implementations that should share a contract; preserve or document differences with a clear product reason.

Published

Sep 7, 2026

Read time

5 min

Tags

GuideDesign QAReactDesign Bug Bot

Share