Design

UX Audit Process

Production-tested audit methodology from the ActiveWizards Astro site. Two complete audit rounds, 147 pages, zero design regressions in production.


1. Audit Cycle

Build -> Deploy Staging -> Audit Round N -> Fix -> Redeploy -> Re-Audit -> Approve

^ |

| |

+---- repeat until PRODUCTION_READY

Round Types

RoundFocusWho

Round 1: StructuralLayout, navigation, content hierarchy, component correctnessDeveloper self-audit
Round 2: Visual DoctrineDesign system compliance, accent budget, typography, spacingDesign reviewer
Round 3+: RegressionVerify fixes did not break previously approved pagesBoth

Never ship after Round 1 alone. The structural round catches obvious breaks, but design system violations only surface in a dedicated visual audit.


2. Reviewer Handoff Format

When handing staging to a reviewer, provide:

## Staging Review Request

URL: https://staging.aw-site.pages.dev
Branch: feature/astro-migration
Pages to audit: 147 (115 blog, 12 cases, 5 services, index pages)
Design spec: docs/DESIGN_SYSTEM.md (Visual Doctrine section)

### Page types to check:
1. Homepage (/)
2. Blog index (/blog)
3. Blog post (/blog/sample-post) -- pick 5 random posts
4. Case study index (/case-studies)
5. Case study detail (/case-studies/sample-case)
6. Service index (/services)
7. Service detail (/services/ai-agents)
8. Contact (/contact-us)
9. 404 page (/nonexistent)

### Known issues:
- [ ] Blog diagrams pending dark theme regeneration (57 SVGs)
- [ ] Footer external links may 404 (expected, not our domain)

3. Audit Report Format

Each finding is a structured record:

### [Page Name] — v[version]

Status: NEEDS_WORK | APPROVED | PRODUCTION_READY

| # | Finding | Severity | Status |
|---|---------|----------|--------|
| 1 | Hero image missing loading="eager" | Tactile Error | FIXED |
| 2 | Accent color on body links exceeds budget | Doctrine Violation | FIXED |
| 3 | Tag pills should use font-mono | Doctrine Violation | FIXED |
| 4 | Add reading time to blog cards | High-Signal Win | DEFERRED |

Example Finding Detail

#### Finding #2: Link color leak on blog prose

Page: /blog/* (all posts)
Severity: Doctrine Violation
Root cause: Global a { color: var(--color-accent) } applies inside prose blocks,
making every link teal. Accent budget allows max 3 teal elements per viewport.
Fix: Scope accent links to navigation and CTAs only. Prose links use
--color-text-secondary with underline, teal on hover.
Regression risk: HIGH -- affects all 115 blog posts.

4. Severity Levels

Doctrine Violation (P0)

The design system spec is violated. These are non-negotiable and block production.

Examples:

  • Accent color (#00D4AA) used on more than 3 elements per viewport
  • Box shadows present (banned in Cyber-Brutalist doctrine)
  • Rounded corners on cards (must be sharp: border-radius: 0)
  • Wrong font family (serif where Geist Sans is required)
  • "Solutions" or "Services" used instead of prescribed terminology

Information Architecture (P1)

Content hierarchy, navigation, or page structure issues. Block production if they affect findability.

Examples:

  • Breadcrumbs missing on detail pages
  • Heading hierarchy broken (H1 -> H3, skipping H2)
  • Navigation links point to wrong pages
  • Related posts section shows irrelevant content
  • Case study metrics display in wrong order

Tactile Error (P2)

Visual or interaction issues that degrade the experience but do not violate the design system.

Examples:

  • Hover state missing on interactive element
  • Image not lazy-loaded (performance, not correctness)
  • Code block overflows horizontally without scroll
  • Mobile menu does not close on link click
  • Table scrolls but no visual indicator of overflow

High-Signal Win (P3)

Improvements that would meaningfully improve the experience but are not bugs. Can be deferred to post-launch.

Examples:

  • Add estimated reading time to blog cards
  • Add "copy" button to code blocks
  • Add "back to top" button on long posts
  • Testimonial photos could be grayscale for consistency
  • Terminal-style animation on hero metrics


5. False Positive Identification

Not every finding is valid. Push back on:

Intentional Design Decisions

If the design spec explicitly calls for a pattern, it is not a bug even if the reviewer dislikes it.

Example: "The footer has too much whitespace" -- check the spec. If the spec says py-20, it is correct.

Browser-Specific Rendering

Test on Chrome, Firefox, and Safari before accepting a rendering finding. Some CSS (like backdrop-filter) renders differently across browsers.

Content Issues vs Design Issues

"This blog post has a bad title" is an editorial issue, not a UX finding. Keep the audit focused on the design system and interaction patterns.

Performance Findings in Audit Context

"The page loads slowly" is not a UX audit finding -- it belongs in the Performance playbook. Unless the slow load causes visible layout shift, defer it.


6. Common Root Causes

One bug often masquerades as multiple findings across different pages. Identify the root cause before fixing individual symptoms.

Global CSS Leak

Symptom: 15 findings across 12 pages about "links are wrong color." Root cause: Single a { color: var(--color-accent) } rule leaking into prose. Fix: One CSS change fixes all 15 findings.
/* Before: global leak */
a { color: var(--color-accent); }

/* After: scoped to navigation and CTAs */
.nav-link, .cta-link, .footer-link {
  color: var(--color-accent);
}
.prose a {
  color: var(--color-text-secondary);
  text-decoration: underline;
}
.prose a:hover {
  color: var(--color-accent);
}

Template Inheritance Bug

Symptom: All blog posts have the same issue (missing breadcrumb, wrong heading level). Root cause: The BlogLayout.astro template has the bug; every post inherits it. Fix: Fix the layout once, all 115 posts are corrected.

Tailwind Class Order

Symptom: Responsive styles do not apply on mobile. Root cause: md:px-8 px-4 works, but px-4 md:px-8 also works in Tailwind v4. The real issue is usually a parent container constraining width.

Missing Design Token

Symptom: Colors inconsistent across pages. Root cause: Hardcoded hex value instead of var(--color-*) token. Fix: Search-and-replace the hardcoded value with the token.
# Find all hardcoded accent colors
grep -rn "#00D4AA" src/ --include="*.astro" --include="*.css"
# Should only appear in global.css @theme block

7. Page-by-Page Systematic Audit

Audit Order

  • Layouts first: BaseLayout, BlogLayout, CaseStudyLayout -- fixes here cascade to all pages
  • Index pages: Homepage, blog index, case studies index, services index
  • Detail pages: Sample blog post, sample case study, sample service
  • Edge cases: 404 page, empty states, very long posts, posts with many diagrams
  • Per-Page Checklist

    For each page, verify:

    • [ ] Correct </code> tag</li> <li>[ ] Meta description present and under 155 characters</li> <li>[ ] OG image renders (check with sharing debugger)</li> <li>[ ] Heading hierarchy: exactly one H1, logical H2/H3 nesting</li> <li>[ ] All images have <code>alt</code> text</li> <li>[ ] All images have <code>width</code> + <code>height</code></li> <li>[ ] No horizontal overflow on mobile (320px viewport)</li> <li>[ ] Interactive elements have hover/focus states</li> <li>[ ] Links go to correct destinations</li> <li>[ ] No console errors</li> <li>[ ] No visual overflow or clipping</li> <li>[ ] Accent color within budget (max 3 teal elements per viewport)</li> <li>[ ] Correct font family (Geist Sans for body, Geist Mono for code/labels)</li> <p></ul></p> <hr /> <h2>8. Regression Testing</h2> <p>After fixing findings from an audit round, you must re-check previously approved pages. Global CSS changes are the #1 source of regressions.</p> <h3>Regression Triggers</h3> <table><tr><td>Change</td><td>Regression Risk</td><td>Re-check</td></tr> <p></table></p> <table><tr><td>Global CSS edit (global.css)</td><td>HIGH</td><td>All page types</td></tr> <tr><td>Layout template edit</td><td>HIGH</td><td>All pages using that layout</td></tr> <tr><td>Component edit (Nav, Footer)</td><td>MEDIUM</td><td>All pages</td></tr> <tr><td>Single page content fix</td><td>LOW</td><td>Only that page</td></tr> <tr><td>Tailwind config change</td><td>HIGH</td><td>All pages</td></tr> <p></table></p> <h3>Regression Testing Protocol</h3> <li>After fixing Round N findings, deploy to staging</li> <li>Re-audit every page type (not every page -- one representative per type)</li> <li>Specifically check the viewport areas near the fix</li> <li>Run automated checks (broken links, Lighthouse)</li> <li>If any regression found: fix and re-run from step 1</li> <h3>Automated Regression Checks</h3> <pre class="shiki github-light" style="background-color:#fff;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D"># Broken links (catches dead links from CSS/HTML changes)</span></span> <span class="line"><span style="color:#6F42C1">npx</span><span style="color:#032F62"> linkinator</span><span style="color:#032F62"> https://staging.aw-site.pages.dev</span><span style="color:#005CC5"> --recurse</span></span> <span class="line"></span> <span class="line"><span style="color:#6A737D"># Visual regression (optional, with Percy or Playwright)</span></span> <span class="line"><span style="color:#6F42C1">npx</span><span style="color:#032F62"> playwright</span><span style="color:#032F62"> test</span><span style="color:#005CC5"> --project=visual-regression</span></span></code></pre> <hr /> <h2>9. Production Readiness Gate</h2> <p>A page is PRODUCTION_READY when:</p> <li>All P0 (Doctrine Violation) findings are resolved</li> <li>All P1 (Information Architecture) findings are resolved</li> <li>P2 (Tactile Error) findings are either resolved or explicitly deferred with rationale</li> <li>P3 (High-Signal Win) findings are logged for post-launch backlog</li> <li>No regressions from previous rounds</li> <li>Lighthouse scores meet thresholds (Performance >= 90, A11y >= 95, SEO >= 95)</li> <h3>Sign-Off Format</h3> <pre class="shiki github-light" style="background-color:#fff;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#005CC5;font-weight:bold">## Production Readiness Sign-Off</span></span> <span class="line"></span> <span class="line"><span style="color:#24292E;font-weight:bold"><strong>Date:</strong></span><span style="color:#24292E"> 2026-03-06</span></span> <span class="line"><span style="color:#24292E;font-weight:bold"><strong>Reviewer:</strong></span><span style="color:#24292E"> [</span><span style="color:#032F62;text-decoration:underline">name</span><span style="color:#24292E">]</span></span> <span class="line"><span style="color:#24292E;font-weight:bold"><strong>Audit rounds completed:</strong></span><span style="color:#24292E"> 2</span></span> <span class="line"></span> <span class="line"><span style="color:#005CC5;font-weight:bold">### Page Status</span></span> <span class="line"><span style="color:#24292E">| Page Type | Count | Status |</span></span> <span class="line"><span style="color:#24292E">|-----------|-------|--------|</span></span> <span class="line"><span style="color:#24292E">| Homepage | 1 | PRODUCTION_READY |</span></span> <span class="line"><span style="color:#24292E">| Blog index | 1 | PRODUCTION_READY |</span></span> <span class="line"><span style="color:#24292E">| Blog posts | 115 | PRODUCTION_READY |</span></span> <span class="line"><span style="color:#24292E">| Case studies | 12 | PRODUCTION_READY |</span></span> <span class="line"><span style="color:#24292E">| Services | 5 | PRODUCTION_READY |</span></span> <span class="line"><span style="color:#24292E">| Contact | 1 | PRODUCTION_READY |</span></span> <span class="line"><span style="color:#24292E">| 404 | 1 | PRODUCTION_READY |</span></span> <span class="line"></span> <span class="line"><span style="color:#005CC5;font-weight:bold">### Deferred Items</span></span> <span class="line"><span style="color:#E36209">-</span><span style="color:#24292E"> Blog diagram dark theme regeneration (57 SVGs) -- post-launch</span></span> <span class="line"><span style="color:#E36209">-</span><span style="color:#24292E"> Copy-to-clipboard on code blocks -- post-launch</span></span> <span class="line"><span style="color:#E36209">-</span><span style="color:#24292E"> Reading time on blog cards -- post-launch</span></span> <span class="line"></span> <span class="line"><span style="color:#005CC5;font-weight:bold">### Approved for production: YES</span></span></code></pre> <hr /> <h2>10. Lessons from the AW Audit</h2> <h3>Heading Anchor Gotcha</h3> <p>Astro's rehype plugins auto-generate heading anchors. When a heading contains special characters, the anchor ID can break. Example: <code>## What's New in v2.0?</code> generates <code>id="whats-new-in-v20"</code>, not <code>id="what-s-new-in-v2-0-"</code>. Verify anchor links manually on pages with complex headings.</p> <h3>Accent Budget Enforcement</h3> <p>The "Cyber-Brutalist" design uses teal (#00D4AA) sparingly. Rule: maximum 3 teal-colored elements visible in any single viewport. This means:</p> <ul><li>Navigation CTA button: 1 teal element</li> <li>Active nav link indicator: 1 teal element</li> <li>Section accent border: 1 teal element</li> <li><strong>Total: 3</strong> -- no more teal visible without scrolling</li> <p></ul></p> <p>Violations are easy to introduce: a teal tag pill, a teal link in body text, a teal icon. Each one must be individually justified or converted to a neutral color.</p> <h3>Grid Void Math</h3> <p>Bento grids with 1px gap borders require careful column math. If you have a 3-column grid with 5 items, the 6th cell is a void. Options:</p> <li><strong>Fill with a placeholder card</strong> (empty state with subtle pattern)</li> <li><strong>Span the last item</strong> across remaining columns (<code>grid-column: span 2</code>)</li> <li><strong>Hide the void</strong> by adjusting grid to fit content exactly</li> <p>The AW audit caught 3 instances of visible grid voids that broke the design's implied completeness.</p> <h3>Global Link Color Leak</h3> <p>The most impactful single fix in the AW audit: removing <code>a { color: var(--color-accent) }</code> from global CSS. This one rule caused 15+ audit findings across blog posts, case studies, and service pages. Scoping link colors to specific contexts (nav, CTA, footer) resolved all of them.</p> <h3>Status Geometry</h3> <p>The design doctrine replaces circular status indicators with squares. This is a subtle but consistent pattern:</p> <pre class="shiki github-light" style="background-color:#fff;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D">/* Wrong: circular */</span></span> <span class="line"><span style="color:#6F42C1">.status-indicator</span><span style="color:#24292E"> { </span><span style="color:#005CC5">border-radius</span><span style="color:#24292E">: </span><span style="color:#005CC5">50</span><span style="color:#D73A49">%</span><span style="color:#24292E">; }</span></span> <span class="line"></span> <span class="line"><span style="color:#6A737D">/* Correct: square, aligned with Cyber-Brutalist doctrine */</span></span> <span class="line"><span style="color:#6F42C1">.status-indicator</span><span style="color:#24292E"> { </span><span style="color:#005CC5">border-radius</span><span style="color:#24292E">: </span><span style="color:#005CC5">0</span><span style="color:#24292E">; }</span></span></code></pre> <h3>Linguistic Purge</h3> <p>Specific words are banned from the UI (not just content):</p> <ul><li>"Solutions" becomes "Architecture" or "Infrastructure"</li> <li>"Services" becomes "Capabilities"</li> <li>"Solutions" (any form) is a hard reject</li> <p></ul></p> <p>This extends to navigation labels, page titles, meta descriptions, and alt text. A find-and-replace across all templates is necessary.</p> </article> </div> </section> </main> <footer class="footer" data-astro-cid-37fxchfa> <div class="container" data-astro-cid-37fxchfa> <div class="footer-inner" data-astro-cid-37fxchfa> <div class="footer-left" data-astro-cid-37fxchfa> <p class="footer-brand" data-astro-cid-37fxchfa>Monad Studio</p> <p class="footer-tagline" data-astro-cid-37fxchfa>Websites that win trust and grow your business</p> </div> <div class="footer-center" data-astro-cid-37fxchfa> <a href="/contact/" class="footer-cta" data-astro-cid-37fxchfa>Start a project →</a> </div> <div class="footer-right" data-astro-cid-37fxchfa> <p data-astro-cid-37fxchfa>A studio by <a href="https://activewizards.com" data-astro-cid-37fxchfa>ActiveWizards</a></p> </div> </div> </div> </footer> </body></html>