You don't need to buy a tool to find out how far your product has drifted from its design system. You need an afternoon, a free code search, a Figma file and somewhere to write things down. This guide is a design system audit checklist for that afternoon: twelve steps, the commands to run, and a one-page form for the results.
It works without FISYCO. We make FISYCO, which runs checks like these continuously, but the point of the afternoon is an honest first picture with what you already have.
Key takeaways
- An audit counts how many different values and components the product actually uses, and compares that with what the system defines.
- Brad Frost says 30 to 90 minutes is enough for a first pass of an interface inventory; a code search adds the numbers.
- Count colours, font sizes, spacing values, components that duplicate system ones, and raw values where tokens exist.
- Write the result down in one table with a date, so the next audit can show a trend instead of a feeling.
Why an afternoon is enough
The goal isn't a complete catalogue. It's a first measurement you can repeat. Brad Frost, who popularised the interface inventory, describes it as "a comprehensive collection of the bits and pieces that make up your interface". A first pass is quick: "I find between 30 and 90 minutes to be sufficient for a first pass of an interface inventory" (Atomic Design, chapter 4).
The numbers are often surprising. When Robin Rendle ran a quick CSS audit of Gusto's product, CSS Stats reported "101 unique colors and 115 unique background colors", while the design system defined 68 colours. His conclusion: "my understanding of the design system is different from what's in the front-end" (CSS-Tricks, 2018).
Before you start (10 minutes)
- Pick the scope. One product, one repository, one Figma library. A monorepo with five apps is five audits.
- List what the system defines. Open the library in Figma and write down the counts: colours in the palette, text styles, spacing steps, components. These are your reference numbers.
- Exclude generated code. Find the folders your tools write into: icon components, API clients, build output. Every command below skips them with
-g '!src/icons/**'; add a glob per folder. When we first measured a demo repository, the icons our own sync had exported counted as about 590 hard-coded colours, which taught us to exclude generated code first.
The code search (90 minutes)
The commands below use ripgrep, which is free; git grep -E handles most of them with small changes. Adjust src and the excluded folders to your repository.
- Count unique colours. Hex values with 3, 4, 6 or 8 digits, case-folded so
#FFFand#fffcount once:
rg -o --no-filename -g '!src/icons/**' -e '#([0-9a-fA-F]{8}|[0-9a-fA-F]{6}|[0-9a-fA-F]{3,4})\b' src \
| tr 'A-F' 'a-f' | sort | uniq -c | sort -nrThe number of lines is your count of distinct hex colours. Compare it with the palette size from step 2. Scan the list for comment noise such as issue numbers.
- Count colour functions.
rgb(),hsl()and their newer relatives hide colours the hex search misses. The number printed is your total:
rg -o --no-filename -g '!src/icons/**' -e '\b(rgba?|hsla?|hwb|lab|lch|oklab|oklch|color)\(' src | wc -l- Count font sizes, in CSS and in React props:
rg -o --no-filename -g '!src/icons/**' -e 'font-size:\s*[0-9.]+(px|rem)' \
-e 'fontSize[:=]\s*[{"'"'"']?[0-9.]+(px|rem)?' src | sort | uniq -c | sort -nr Compare the number of distinct values with the text styles in your library. Many more values in code than styles in Figma usually means text is sized by hand. Unitless React values are pixels, so merge 14 and 14px when you count.
- Count spacing values. Pixel values in general, which shows how often spacing is typed instead of tokenised:
rg -o --no-filename -g '!src/icons/**' -e '\b[0-9]+px\b' src | sort | uniq -c | sort -nr | head -30 These counts include font sizes from step 6. Look for near-duplicates: 12px, 13px and 14px side by side are usually one intended value.
- Find duplicate components. Search file names for the system's component names:
rg --files -g '!src/icons/**' src | rg -i 'button|modal|dialog|tooltip|card' A PrimaryButton.tsx in a feature folder, next to the system's Button, is a component rebuilt locally. List each one with its folder.
- Find raw palette tokens. If your system has semantic tokens, a palette token in a component is a bypass. Adjust the palette names to your theme:
rg -n -g '!src/icons/**' -e '["'"'"'`](gray|red|blue|green)\.\d{2,3}["'"'"'`]' srcA follow-up note in this series covers more colour patterns and how to turn them into a lint rule.
The design side (45 minutes)
- Check a few screens against the library. Pick the three most-used screens. In production, inspect a button, a heading and a card on each, and compare the values with the Figma library. Note every difference.
- Check the library against itself. In Figma, open two or three product files and look for local styles in the Assets panel and for layers that look like library components but aren't instances. A detached component in design often turns into a rebuilt component in code.
- Compare the token lists. If tokens are exported to code, compare names and values with the Figma variables. A token in Figma that's missing in code, or a code token with a different value, is design system drift in miniature. Match by stable ID if you can, because renames otherwise look like one deletion plus one addition, as our guide to tokens from Figma to code explains.
Write it down (15 minutes)
The result fits on one page. What matters is the date and the same rows every time.
Illustrative example.
Add three lines under the table: the date, who ran the audit, and the three findings you'd fix first. Put the file in the repository, next to the code it describes.
What to do with the numbers
An audit is useful when it changes what happens next:
- Fix by reach, not by count. A drifted value in a component used on every screen outweighs a dozen one-offs. The four health signals explain how to weigh them.
- Turn the worst search into a rule. If hard-coded colours topped the table, add a lint rule so the number can only go down.
- Repeat it. The second audit is worth more than the first, because it shows a trend.
When an afternoon stops being enough
The afternoon audit is a snapshot. Between two snapshots, drift keeps happening, and nobody sees it until the next one. That's the gap we built FISYCO for: it indexes your code and your Figma library, finds the kind of divergences and token bypasses this audit counts, and ranks them by reach. See what FISYCO does.



