Jun 2, 2026

10 min read

AI-Ready Design Systems (3/3)

Audit before you scaffold: meeting projects where they are

Francois Brill

Francois Brill

Designer + Builder

Audit before you scaffold: meeting projects where they are
TL;DR

For engineers: the read-only audit phase we run on every new project: what files to read (package.json, tailwind.config.js, the components directories, fonts), the .agents/design-system-audit.md template, and the four concrete decisions that come out of it.

For founders: why we audit before scaffolding. An hour reading saves a week of cleanup. The principle is what's worth knowing; the file list is detail for your team. The audit is non-destructive by design, your existing code stays where it is. If you want the bigger picture first, Article 1 covers why this approach.

Before I created a single file in the design-system folder, I spent forty-five minutes just reading the existing codebase. That hour saved us a week of cleanup.

The first instinct, and I'll be honest about it, was to skip that entirely. We had an earlier React project we had ported tokens from. The brand was shared. The colors lived in a spreadsheet. The logo was the same. My first thought was: copy the token files, adapt the component structure, move fast.

I was thirty seconds from running the scaffold command when I noticed the package.json. React. The new project was Nuxt 4 with Vue 3. Different framework, different mental model, different file conventions, different way components compose. A direct port would have landed in the wrong place from line one.

The audit became mandatory.

The temptation to skip it

Every new project comes with a version of the same pressure: the client wants to move, the scope is already defined, and auditing feels like delay. The work hasn't started yet, so pausing to read feels like stalling.

But skipping the audit doesn't eliminate the discovery work. It moves it later, into the middle of implementation, where discoveries become blockers.

An hour reading saves a week patching.

The audit is the cheapest moment to learn what you're building on. We now run it on every project, not just complex ones. The methodology has been refined across several engagements. Each one revealed something new to read for. What's described here is what the process covers now.

What "audit" means here

The audit is a read-only phase. You open files. You take notes. You write nothing to the codebase.

That last part matters more than it sounds. The temptation during an audit is to start fixing things you notice. A token that's inconsistent. A component that could be abstracted. A color that doesn't quite match. Resist all of it. If you start editing during the read phase, you lose the thread of what you're actually trying to understand.

The audit's output is decisions, not code.

The deliverable is a single Markdown document: .agents/design-system-audit.md. It lives in the .agents/ folder, which is the canonical location for all spec documents in this methodology. (Article 1 covers why .agents/ exists and what lives there.) By the end of the audit, that document answers every structural question the scaffold will need answered. Where does the design system folder go? Which Tailwind flavor? What existing tokens should be preserved? What components already exist and at what tier?

The document is the audit. Not a summary of findings, not a slide deck. A structured spec that feeds directly into the scaffold.

What we read for

On a recent Nuxt + Tailwind v4 marketing site, the audit covered these files in roughly this order.

Foundation first

Example: these three files establish the stack immediately.

package.json
nuxt.config.ts
tailwind.config.js

package.json gave us nuxt@^4.0.0, vue@^3.5.13, and tailwindcss@4.1.11 running through PostCSS. That detail alone changed the flavor recommendation.

CSS layer

app/assets/css/tailwind.css
app/assets/scss/variables.scss
app/assets/scss/main.scss

The tailwind.css file held the main Tailwind v4 config: @theme blocks, inline token definitions, custom utilities. variables.scss had hex codes that had drifted somewhat from what was defined in tailwind.css. Some colors appeared in both places with slight inconsistencies. We noted the drift and moved on. Reconciling it in the audit phase would have pulled us off track. That reconciliation became a scoped item for a later article.

main.scss held a combination of global resets, some component-level overrides, and utility classes that predated the Tailwind migration. Understanding those overrides explained some rendering behavior that would have looked like bugs otherwise.

Components

app/components/UI/
app/components/section-components/

We opened every file in both directories and counted. Not reading deeply, just classifying. What tier is this component? Atomic (a button, a badge, an input) or compositional (a hero section, a pricing block, a feature grid)?

The count came out to roughly 26 components in UI/ and 10 in section-components/. Naming in UI/ was generally consistent. section-components/ had some drift, with a few components using kebab-case filenames and others using PascalCase.

Pages

app/pages/

Pages gave us context for how components were being used in practice. They showed which section components appeared frequently, which ones appeared once and might be throwaway layouts, and how copy was structured across the site. You miss a lot if you skip the pages.

Fonts

public/webfont/

The webfont directory held three font families: General Sans (variable, multiple weights), Tiempos Headline (Roman and Italic cuts), and Delicious Handrawn (single weight, for accent use). The CSS loaded all three. The audit noted which was body, which was display, and which was decorative.

The sister project

We also reviewed the earlier React project we had ported tokens from. This was the near-miss from the intro. Reading it confirmed two things: the token naming conventions were different enough that a direct port would have introduced inconsistencies, and the component structure didn't map cleanly to Vue's composition model. We carried the brand values across (the core yellow at #f7b200, the primary blue at #3c5ccf) but nothing else.

What the audit told us

After reading everything, the audit document captured this.

Stack detected

LayerValue
FrameworkNuxt 4, Vue 3
CSS frameworkTailwind 4.1.11 (PostCSS)
AdditionalSCSS (variables + global styles)
FontsGeneral Sans, Tiempos Headline, Delicious Handrawn
Node version20 (from .nvmrc)

Existing tokens

Colors defined in @theme in tailwind.css:

  • Primary yellow: #f7b200
  • Primary blue: #3c5ccf
  • Gray scale: 9 steps, defined as CSS custom properties

Custom utility classes: heading-xl, heading-lg, heading-md, heading-sm, heading-xs, eyebrow, eyebrow-sm. These were defined in the CSS layer, not in a tokens file. They were in consistent use across pages.

Existing components, inferred tiers

Tier 1 (atomic): ~26 components in app/components/UI/. Buttons, badges, inputs, labels, cards, icons, avatars, modals.

Tier 2 (section-level): ~10 components in app/components/section-components/. Hero variants, feature sections, CTA blocks, testimonial layouts.

Naming and conventions

Components used PascalCase for filenames, mostly consistent. A few outliers in section-components/ used kebab-case. CSS classes were a mix of Tailwind utilities and custom utility classes. The heading-* and eyebrow-* conventions were the most coherent custom layer.

Voice and copy patterns

Pages used short, punchy headlines. Body copy was concise. No passive constructions. The tone was direct, slightly informal, brand-confident. This matters for the spec because copy patterns inform component design: how much space a headline needs, whether subheadings are common, whether there are UI strings that need consistent treatment.

The audit document

The .agents/design-system-audit.md file has a fixed structure. Here's the template we use on every project:

# Design system audit
 
## Stack detected
 
<!-- Framework, CSS toolchain, build config, Node version -->
 
## Flavor recommendation
 
<!-- tailwind-v4, tailwind-v3, css-modules, styled-components, etc. -->
 
## Folder location recommendation
 
<!-- Where the design-system directory lives in the repo -->
 
## Existing tokens
 
<!-- Colors, typography scales, spacing, any defined custom properties -->
 
## Existing components – inferred tiers
 
<!-- Tier 1 (atomic), Tier 2 (section), Tier 3 (page/layout) -->
 
## Naming + conventions
 
<!-- File naming, component naming, CSS class conventions -->
 
## Voice / copy
 
<!-- Tone, headline patterns, UI string patterns -->
 
## What will be scaffolded
 
<!-- List of files and folders the scaffold will create -->
 
## Non-destructive promises
 
<!-- Explicit list of what will NOT be touched -->
 
## Open questions
 
<!-- Anything unresolved that needs a decision before scaffold runs -->
 
## Verification
 
<!-- How to confirm the scaffold landed correctly -->

Each section is short. The flavor recommendation is one line. The folder recommendation is one line. The non-destructive promises are a bullet list. None of this should take long to fill in. The value is not in the volume of notes. It's in the fact that every structural decision has been made before a single file gets written.

Specs point at existing files. They don't replace them.

The audit document references paths, versions, and existing tokens. It doesn't duplicate them. When the AI scaffold reads the audit, it knows where to look for the real values.

The decisions that came out of it

The audit produced four concrete decisions for this project.

1. Folder location

The first instinct was to put the design system at the repo root: /design-system/. That felt tidy. After reading the Nuxt project structure, it was wrong. Nuxt 4 uses an app/ directory for all application code. Putting the design system at the repo root would have split the conceptual location of everything UI-related. We moved it to app/design-system/.

2. Flavor

Tailwind 4.1.11 with PostCSS. Not the Vite plugin variant. This determined how the token file would be structured and how the scaffold would wire up the @theme block.

3. Scope

We would scaffold the token layer and the spec documents. We would not move, rename, or refactor the existing components in app/components/UI/ or app/components/section-components/. The components already worked. Moving them into a new folder would have required updating every import across the codebase, a non-trivial change with no immediate benefit.

This was actually a decision I backed out of. Early in the audit I considered restructuring the component directories as part of the design system adoption. It seemed logical: if we're introducing a design system, shouldn't components live inside it? After reading the import graph, no. The cost was too high and the gain was cosmetic. The spec documents reference the existing paths. The existing paths stay.

4. What to preserve

The heading-* and eyebrow-* utility classes were well-established and used throughout the codebase. The custom font stack was fully configured. The color tokens were defined, even if there was some drift in the SCSS layer. The audit told us to preserve all of this and build the new token layer around it, not instead of it.

Non-destructive adoption

Non-destructive isn't polite. It's the only way the change lands.

Every design system introduction into an existing codebase carries the same risk: the team builds something new and the existing code quietly diverges from it. Two systems running in parallel. Neither authoritative.

Non-destructive adoption means the new scaffold fits around what exists. The new app/design-system/ folder holds specs and the token layer. The components stay where they are. The existing CSS stays in app/assets/. Nothing breaks, nothing moves, nothing requires a migration sprint to make the codebase consistent again.

The audit is what makes this possible. You can't make non-destructive promises without first reading what needs to be preserved.

A note on AI doing the audit

This is one of the places where AI is useful.

Reading 30 files and synthesizing them into a structured document is exactly the kind of task that benefits from AI assistance. No judgment calls about design direction, no opinion about architecture. Just: here is what exists, here is what it implies, here is where the edge cases are.

We run the audit as a prompt. We give the AI a list of files to read, the template for the audit document, and the instruction to read first and write nothing to the codebase. The AI produces a draft audit document. We review it, correct anything it misread, and lock it.

The first version of our audit process missed the webfont directory entirely. A later version didn't look at pages, so it missed how components were actually being used in context. Each project revealed something else worth reading for. The file list above is what the template covers now.

The audit is still a read-only phase. The AI writing the audit document is writing a plan, not touching the codebase. That distinction holds regardless of who is doing the reading.

The scaffold runs after the audit. Not before.

Everything in Article 4 assumes this document exists and is complete. The AI running the scaffold reads .agents/design-system-audit.md and uses it to make every structural decision: where to put things, what to name them, what to leave alone.

Without the audit, the scaffold is guessing. And guesses at the structural level are expensive to undo.

Not sure what your design system actually contains?

Clearly Design audits your existing codebase and turns what is already there into an AI-ready source of truth, without breaking the components you ship today.