Everyday Programmer
Field Notes

Client Design System Audit Case Study

An anonymous client story about turning scattered interface decisions into a practical design system roadmap.

7 min readfield notes, design systems, audits

A client asked for help after their product team realized the interface was becoming harder to change than the product logic behind it. This is the anonymized version of that audit: no company names, no private roadmap details, and no screenshots that would identify the product.

The useful part was not a perfect component inventory. It was the sequence of decisions that helped the team move from “the UI feels inconsistent” to “we know which system work should happen first.”

Situation

The team had a working product, a small frontend group, and a healthy habit of shipping quickly. Most screens had been built by capable engineers under real delivery pressure.

The symptoms were familiar:

  • Similar cards had different padding and heading hierarchy.
  • Form help text moved depending on who built the page.
  • Empty states sounded like three different products.
  • Status labels mixed internal implementation names with user-facing language.

Problem

The team initially described the problem as missing components. After the first pass, the bigger issue looked like missing defaults.

A component library would help eventually, but the product needed shared answers first: how pages are framed, how recovery states are written, how primary and secondary actions are ordered, and when a bespoke layout is worth the cost.

audit-findings.md
md
 1  # Repeated decisions found during audit
 2  
 3  - Page headers use multiple max widths and vertical rhythms.
 4  - Settings forms repeat the same structure with different help text placement.
 5  - Empty states vary in tone, title case, and action hierarchy.
 6  - Status badges expose backend labels instead of customer-facing states.

Tradeoffs

There were two honest paths.

The first path was to pause feature work and build a broad component library. That would create visible system progress, but it would also ask the team to guess at abstractions before the product had agreed on its defaults.

The second path was to define a smaller set of production rules and ship one vertical slice. That felt less impressive, but it reduced risk and gave the team something they could apply immediately.

Decision

We chose the smaller path: document repeated product decisions, convert the most common ones into reusable primitives, and leave the rest as guidance until the team had more evidence.

The first implementation target was not every component. It was one product surface with enough variety to test the system: page shell, section layout, form rows, empty state, status badge, and action placement.

system-slice.ts
ts
export const firstSystemSlice = [
  "page shell",
  "section spacing",
  "form row guidance",
  "empty state pattern",
  "status badge language",
] as const;

What Worked

The audit worked best when it stayed close to the product. Screenshots were grouped by decision, not by page. Engineers could see where a shared primitive would remove repeated work, and product partners could see where language inconsistency created hesitation.

The most useful artifact was a short decision log. It gave the team enough language to review new work without waiting for a complete documentation site.

What Broke

A few assumptions did not survive contact with the product.

The first empty-state pattern was too rigid for permission and billing states. The first status badge vocabulary hid an important operational distinction. A spacing rule that looked clean in mockups made dense review pages harder to scan.

Those breaks were useful. They showed where the system needed variants, where the product needed clearer language, and where guidance was better than abstraction.

decision-log.md
md
# Changes after product testing

- Empty states need recovery, permission, and billing variants.
- Status badges must separate customer language from internal diagnostics.
- Dense review pages can use tighter section rhythm when scanning is the main task.

Takeaways

A design system audit should produce a path to better product work, not just a list of inconsistencies.

The durable takeaways from this client engagement were simple:

  • Start by naming repeated decisions.
  • Build primitives only after the decision is understood.
  • Use one real product slice to test the system.
  • Treat broken assumptions as useful system feedback.
  • Keep the first release small enough for the team to actually adopt.

Keep reading

Related articles