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
| Round | Focus | Who |
| Round 1: Structural | Layout, navigation, content hierarchy, component correctness | Developer self-audit |
| Round 2: Visual Doctrine | Design system compliance, accent budget, typography, spacing | Design reviewer |
| Round 3+: Regression | Verify fixes did not break previously approved pages | Both |
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: Singlea { 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: TheBlogLayout.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 ofvar(--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
Per-Page Checklist
For each page, verify:
- [ ] Correct
tag - [ ] Meta description present and under 155 characters
- [ ] OG image renders (check with sharing debugger)
- [ ] Heading hierarchy: exactly one H1, logical H2/H3 nesting
- [ ] All images have
alttext - [ ] All images have
width+height - [ ] No horizontal overflow on mobile (320px viewport)
- [ ] Interactive elements have hover/focus states
- [ ] Links go to correct destinations
- [ ] No console errors
- [ ] No visual overflow or clipping
- [ ] Accent color within budget (max 3 teal elements per viewport)
- [ ] Correct font family (Geist Sans for body, Geist Mono for code/labels)
8. Regression Testing
After fixing findings from an audit round, you must re-check previously approved pages. Global CSS changes are the #1 source of regressions.
Regression Triggers
| Change | Regression Risk | Re-check |
| Global CSS edit (global.css) | HIGH | All page types |
| Layout template edit | HIGH | All pages using that layout |
| Component edit (Nav, Footer) | MEDIUM | All pages |
| Single page content fix | LOW | Only that page |
| Tailwind config change | HIGH | All pages |
Regression Testing Protocol
Automated Regression Checks
# Broken links (catches dead links from CSS/HTML changes)
npx linkinator https://staging.aw-site.pages.dev --recurse
# Visual regression (optional, with Percy or Playwright)
npx playwright test --project=visual-regression
9. Production Readiness Gate
A page is PRODUCTION_READY when:
Sign-Off Format
## Production Readiness Sign-Off
Date: 2026-03-06
Reviewer: [name]
Audit rounds completed: 2
### Page Status
| Page Type | Count | Status |
|-----------|-------|--------|
| Homepage | 1 | PRODUCTION_READY |
| Blog index | 1 | PRODUCTION_READY |
| Blog posts | 115 | PRODUCTION_READY |
| Case studies | 12 | PRODUCTION_READY |
| Services | 5 | PRODUCTION_READY |
| Contact | 1 | PRODUCTION_READY |
| 404 | 1 | PRODUCTION_READY |
### Deferred Items
- Blog diagram dark theme regeneration (57 SVGs) -- post-launch
- Copy-to-clipboard on code blocks -- post-launch
- Reading time on blog cards -- post-launch
### Approved for production: YES
10. Lessons from the AW Audit
Heading Anchor Gotcha
Astro's rehype plugins auto-generate heading anchors. When a heading contains special characters, the anchor ID can break. Example: ## What's New in v2.0? generates id="whats-new-in-v20", not id="what-s-new-in-v2-0-". Verify anchor links manually on pages with complex headings.
Accent Budget Enforcement
The "Cyber-Brutalist" design uses teal (#00D4AA) sparingly. Rule: maximum 3 teal-colored elements visible in any single viewport. This means:
- Navigation CTA button: 1 teal element
- Active nav link indicator: 1 teal element
- Section accent border: 1 teal element
- Total: 3 -- no more teal visible without scrolling
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.
Grid Void Math
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:
grid-column: span 2)The AW audit caught 3 instances of visible grid voids that broke the design's implied completeness.
Global Link Color Leak
The most impactful single fix in the AW audit: removing a { color: var(--color-accent) } 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.
Status Geometry
The design doctrine replaces circular status indicators with squares. This is a subtle but consistent pattern:
/* Wrong: circular */
.status-indicator { border-radius: 50%; }
/* Correct: square, aligned with Cyber-Brutalist doctrine */
.status-indicator { border-radius: 0; }
Linguistic Purge
Specific words are banned from the UI (not just content):
- "Solutions" becomes "Architecture" or "Infrastructure"
- "Services" becomes "Capabilities"
- "Solutions" (any form) is a hard reject
This extends to navigation labels, page titles, meta descriptions, and alt text. A find-and-replace across all templates is necessary.