Audit Your UI with AI: A Repeatable System for Your Codebase
2026-08-06
Lessons from HazMind, #1 — 2026-08-06
I'm building HazMind solo, with the guidance of a certified EHS specialist. Through our many conversations, we identified critical tool requirements and prioritized quality-of-life usability improvements. At its core, the app is a step-by-step digital wizard—asking the user one question at a time to reach a result. It could just as easily be a loan application or a symptom checker; nothing below depends on the domain. There is no UX team here—just me, a pile of design docs, and an AI coding agent. This post explains how I turned a one-off "review my UX" request into a repeatable evaluation system that audits itself — one that runs real browser tests to verify its own findings, and that a UX researcher or product manager could pick up and extend without reading the code.
Step 1: Audit the code, not screenshots
My first pass used a single prompt. I asked the AI to evaluate the design system and UX against Nielsen’s 10 heuristics. This covered both implemented and planned features.
These principles include things like "show system status" and "prevent errors." Any standard framework works. The goal is auditing against a standard instead of vibes.
Two factors made this better than a generic review:
- The AI read the actual codebase, not mockups. Screenshots show you what a screen looks like; the code shows what it does. Reading the source is what surfaced findings like "every sign-in failure collapses into one generic error message" and "the error page says 'Page not found' even for server errors" — invisible in a screenshot.
- Design docs were included. My repo has specs and roadmaps. Auditing these let me evaluate features before building them. This is the cheapest way to catch problems. The output was a report with a scorecard and prioritized findings. However, a report is just a snapshot. Snapshots get outdated quickly.
Step 2: Turn findings into checkable claims
The document became a system when I turned findings into falsifiable claims. Each claim has an ID, a severity level, and a written verification method.
```other ### U03 · Disabled "Continue" button gives no reason — Med · defect · e2e
One form step asks several questions at once; the design says the submit button should explain what's still missing ("Submit — one answer left"). The shipped button is just a greyed-out "Continue".
Probe: start a flow → reach that step → answer only one of its questions → read the submit button's text. No mention of what's missing → still open.
Status: open · Last verified: 2026-08-06 ```
Every finding also gets a kind, and this classification does a lot of work:
defect— a verifiable gap. Machines can check it and close it.decision. A deliberate design choice. In my app, users can’t undo answers. This keeps records trustworthy. An auditor might see "no undo" as a defect. The system verifies the facts but cannot close these. Humans handle trade-offs.planned. Exists in docs but not yet live. If it ships broken, it becomes a defect.
This register file — plain markdown, versioned in the repo — is the record of truth. The pretty report is regenerated from it and published to one stable URL, so stakeholders always have a current link instead of five stale PDFs.
Step 3: Package the audit as a command
I had the AI write a skill. This markdown file lets the agent run /usability-audit in future sessions. It defines the procedure. It verifies claims, runs browser tests, and updates the register. It then reports what changed.
The skill also enforces guardrails:
- Evaluate, don't fix. Audits never edit code. Fixes come later.
- Verify interactions in the browser. Code reading isn't enough. Probes must pass.
- Highlight High-severity fixes. Don't close these silently. Ensure they get noticed.
- Queue new findings. These go into a "candidates" list. A person decided what counts.
Step 4: Verify with simulated users, not vibes
The register marks verification as static or e2e. For e2e, the audit launches Hazmind. It uses Playwright to simulate user behavior and my first dry run revealed a few things I missed during development:
- A first-time visitor. This confirmed redundant legal pop-ups at every start.
- A dark mode user. This proved the theme toggle ignored OS preferences and failed on reload.
- Partial form completion. This confirmed the button greys out without explanation.
This shows the problem in action. It isn't just an AI opinion. These probes also confirm when a bug is truly fixed.
Step 5: Run it and refine
The first run caught errors in the skill itself. It found a stale label and an environment bug. Both were fixed in the instructions. It also handled flaky tests correctly because the skill documented how to retry them. This loop ensures the system stays useful.
That loop — run, hit friction, write the fix into the instructions — is how the system stays usable six months from now.
This is a peek at what my current usabiilty scorecard from the stable URL reveal.
PS: I'm still in active development and refinement!
Why this works for teams
The components are simple. Markdown files, browser scripts, and a stable URL. This makes it easy to hand off.
- UX Researchers can add findings easily. They just need a claim and a check method. Accessibility standards like WCAG map perfectly to this format.
- Product Managers get a clear scorecard. They see what is fixed or regressed. They own the "decision" queue.
The register tracks health over time. It isn't just a one-off review.
The takeaways
- Audit code and docs. Screenshots miss the worst bugs in error paths.
- Use checkable claims. Prose findings rot. Verifiable ones last.
- Separate defects from decisions. Machines check facts. Humans handle design choices.
- Make it re-invocable. A packaged procedure accumulates improvements.
- Trust browser probes. "Fixed" means a simulated user succeeded. Don't rely on code diffs alone.
**