AUGUR
AUGUR Heuristics tab — full evaluation with working-well and issue cards
AUGUR Accessibility tab — WCAG 2.2 findings with citations

AUGUR • AN AI-NATIVE TOOL FOR HEURISTIC & ACCESSIBILITY EVALUATION

AUGUR CASE STUDY
Designer & Builder, solo  •  Personal project  •  July 2026  •  AI-native evaluation tool, live in production

AUGUR runs a heuristic and accessibility evaluation on any URL, side by side, in the time it takes to load a page. I designed and built it end to end — the prompt architecture, the trust signals in the interface, and the production safeguards that keep a public AI tool from running up an unbounded bill. It pairs a real accessibility scanner for what can be measured with Claude for what has to be judged, and treats the difference between those two as the actual design problem.

Highlights:
  • Cut a third framework (Everett McKay's Intuitive Design) after testing whether Claude's training actually held it with any fidelity — the model declined to reproduce it, correctly naming the risk as confabulation, not recall
  • Split every evaluation into two engines — a deterministic accessibility scanner and Claude's interpretation — so every WCAG citation traces back to a real scan finding, never a visual guess
  • Caught a live bug where axe-core's own wording leaked past both the prompt and the schema enum, and fixed it with a second independent layer instead of a bigger prompt
  • Rate-limited the public tool with two independent signals (cookie + IP) on a true sliding window, plus a separate account-level spend cap — two backstops, each covering a failure the other doesn't
AUGUR Heuristics tab, full production result
A live evaluation: severity-coded issue cards and working-well cards, each tagged with the AI's own confidence in the finding.
⸻ A NOTE ON THIS CASE STUDY
This isn't a case study with an AI chapter appended at the end. AI is the mechanism the whole product runs on, so it's threaded through every section below — how the system prompt is architected, how trust is signaled in the interface, how the build itself was directed and debugged with Claude Code, and how the deployed app is protected against its own cost.

▶  TRY THE AUGUR APP LIVE     ▶  GITHUB SOURCE     ▶  VIEW BUILD-LOG

PROJECT BRIEF

Heuristic and accessibility audits are two of the most consistently valuable — and consistently skipped — steps in real design work. They're slow, they require specific expertise, and under deadline pressure they're the first thing cut. AUGUR is a tool that removes the excuse: submit any URL, and it returns a structured heuristic evaluation against the Nielsen Norman Group's ten usability heuristics, and a WCAG 2.2 accessibility evaluation, side by side, in the time it takes to load a page.

That's only possible because of what runs underneath it. A rules-based tool can check contrast ratios and missing alt text, and AUGUR does exactly that, deterministically. But judging whether a page's structure is confusing, or its navigation matches what a user expects, isn't measurement — it's interpretation. AUGUR pairs the two: a real accessibility scanning engine for what can be measured, Claude for what has to be judged. The actual design problem is building that pairing well: deciding what the model gets to interpret, what it's never allowed to guess at, and how its output earns a reader's trust.

GROUNDING THE FRAMEWORKS

Grounding the model in the actual standard

A model asked to evaluate a page "against Nielsen Norman's heuristics" from memory alone will produce something plausible-sounding regardless of whether its recollection is accurate. That's a real failure mode for any AI evaluation tool, and it's invisible unless you deliberately test for it. AUGUR doesn't rely on recall: the ten heuristics, their definitions, and the questions each one asks are supplied directly in the system prompt as explicit ground truth, sourced from Nielsen Norman Group's own published Heuristic Evaluation Workbook. The model's job is to apply the standard it's been handed, not to reconstruct one from training data.

The same reasoning shaped the accessibility side. WCAG 2.2 was chosen specifically because it's the current, legally referenced standard — not WCAG 3.0, which remains an incomplete draft. A Candidate Recommendation isn't expected until late 2027, and a final Recommendation, with the years of legal adoption that follow it, trails well beyond that. Citing a standard that isn't finished yet would be citing a moving target.

A third framework — Everett McKay's Intuitive Design — was seriously considered and deliberately cut, for two independent reasons. First, his principles exist only inside a commercial book with no public reference implementation. Encoding them, even reworded, would mean building a free tool partly out of someone else's proprietary IP. Second, and more interesting: a direct test of whether Claude's training actually held McKay's principles came back negative. The model recognized his premise but declined to reproduce a list, correctly naming the risk as confabulation, not recall. Nielsen Norman's ten heuristics passed that same test cleanly. Two unrelated failure modes, one framework, the same conclusion — cut it, keep the two that were actually grounded.

Nielsen Norman Group — Jakob's Ten Usability Heuristics reference poster
NN/g's own published reference for all ten heuristics — the actual source material supplied to the model, not a paraphrase of it.
W3C's How to Meet WCAG (Quick Reference) page
The same approach on the accessibility side: W3C's own WCAG quick reference, not a secondhand summary of it.
DESIGNING THE AI ARCHITECTURE

1) Two layers: what's measured, and what's judged

Every evaluation runs two engines in the same pass. axe-core scans the live DOM and returns deterministic, verifiable violations — a missing alt attribute either exists or it doesn't. Claude never re-evaluates or second-guesses that data. The system prompt instructs it to treat scan results as verified fact and explain them, not judge them. Heuristic evaluation is the opposite case: there's no scanner for whether a page's structure matches user expectations, so that's where the model actually interprets, against the framework described above.

Keeping those two roles separate, rather than asking one model call to estimate everything from a screenshot, is what makes the accessibility tab's citations trustworthy: every WCAG reference on that tab traces back to a real, reproducible scan finding, not a visual guess.

Accessibility tab with specific WCAG 2.2 success criterion citations
Each accessibility card cites its specific WCAG 2.2 success criterion (e.g. 1.4.3, 2.4.4/4.1.2) — traceable to a real scan finding, not inferred from the image.

2) Constraining output with a schema

Every response is returned through Claude's tool-use API against a defined JSON schema, not parsed out of free-text. Severity, confidence, and rating fields are all constrained to fixed enums — Critical / Severe / Moderate / Minor, High Confidence / Confident / Suspected / Uncertain — so the model can't drift into inconsistent wording across evaluations, and the frontend never has to guess what shape a response will take. This is a trust decision as much as an engineering one: a badge system only works if the vocabulary behind it is actually fixed.

Confidence tagging is deliberately scoped to heuristic findings only. Accessibility findings come from a deterministic scan and are already verified fact — a confidence badge there would just be noise. The distinction between "measured" and "interpreted" is made once, structurally, rather than repeated on every card.

Figma component set — severity badges, confidence badges, working-well ratings, and their semantic color pairs
The full badge system as Figma components: severity, AI confidence, and working-well ratings, each with its own light/dark semantic color pair.

3) When the schema wasn't enough on its own

A schema constrains the field type, not necessarily the exact word choice inside it. axe-core labels one of its own severity levels "serious." Despite the prompt and the schema enum both instructing the model to report that as AUGUR's own "Severe" label, the raw word occasionally leaked straight through into the badge. The screenshot alongside this is that bug, live, from mid-build testing.

The fix wasn't a bigger prompt — it was a second, independent layer: a small server-side normalization step that remaps any known alias before the response ever reaches the frontend, plus a client-side fallback style so that any future unrecognized value degrades gracefully instead of rendering an invisible badge. Prompting for correctness and verifying it in code aren't the same thing, and this is the specific case that proved it.

Accessibility card showing the unconverted 'Serious' severity label, before the normalization fix
The bug caught mid-build: axe-core's own wording ("Serious") slipping past both the prompt instruction and the schema enum.

The system prompt itself went through eleven tracked revisions over the course of the build — kept as a versioned log, not edited in place — as specific failure modes surfaced under real testing: truncated output, inconsistent severity ordering, over- and under-eager issue counts. None of that tuning is visible in a finished product. It's the difference between a prompt that works on the examples you tried and one that holds up against a URL you've never seen.

4) Making confidence show its work

A badge alone is still just a rating with no reasoning attached. "Suspected" tells a reader the model isn't fully sure, but not why — and a confidence label that can't explain itself is asking to be trusted on faith. Every confidence badge now carries a required one-sentence explanation underneath it: whether the finding is something directly visible in the screenshot, or an inference about intent or composition that can't be verified from the image alone. It's a small addition to the schema, but it turns confidence from a static rating into a piece of reasoning a reader can actually check against the evidence.

One related wording change alongside it: the Uncertain badge now reads "Uncertain: needs review" — display-only, done in the badge-rendering component via a small lookup table, so the underlying value, schema, and styling keys are all untouched. A lone word doesn't obviously suggest what to do with it; a short phrase does.

Close-up of a confidence badge with its one-sentence explanation beneath it
The addition, up close: a "Confident" rating explaining exactly what it's basing that on.
Three heuristic cards with different confidence tiers, each with its own explanation
Three tiers in context — High Confidence, Confident, and Suspected each reasoning differently about the same page.
KEY DECISIONS & TRADEOFFS

1) The empty state teaches first

Most of AUGUR's likely first-time visitors won't know what "heuristic evaluation" means, or why WCAG 2.2 specifically. A tool built on AI judgment has an extra burden most tools don't: explaining why its output should be trusted before it's produced any. The pre-submission state isn't a blank placeholder. It's a short, plain-language explanation of both frameworks and why each was chosen, written to be read before a single URL is entered.

AUGUR empty state — onboarding copy explaining heuristics and accessibility before first use
The empty state, doing onboarding work instead of sitting blank.

2) An honest loading state

A real evaluation launches a browser, screenshots the live page, runs a full accessibility scan, and waits on a Claude response — realistically tens of seconds, not milliseconds. Rather than a generic spinner, a slow cross-fading sequence of phrases keeps the wait legible and on-brand, timed deliberately (a slow fade in, a long hold, a slow fade out) so it reads as considered rather than anxious.

AUGUR loading state — cross-fading phrase animation during evaluation
The loading state: a slow phrase cycle, not a spinner — honest about the wait instead of hiding it.

3) One component system behind every card

Every card in the interface is a Figma component built on the same token set the app's CSS uses directly. The header bar's color and icon are driven entirely by the severity or rating value, so a "Critical" issue and an "Excellent" working-well finding are visually unmistakable from across the room, not just on close reading. Two card types share the same shell: an issue card (severity, description, recommendation) and a working-well card (rating, confidence) — different content, same visual grammar.

Figma card component, full header variant set, and three rendered card types
The card component, its full header variant set, and three rendered states side by side — one component, every severity, unmistakable at a glance.
HOW I BUILT IT

From a bare prototype to a working pipeline

The project started under a working name, HEURISTIC — a single input field and a title, wired to a raw Claude response with no structure at all. AUGUR came later, tested against options across several registers — the clinical (RUBRIK, Site-Crit), the irreverent (RoastMySite.com) — before landing on a name that works as both noun and verb: something that reads surface patterns to surface a hidden, structural truth. The renaming happened before the product had a card system, a color language, or a second evaluation lens — it was a bet on what the tool was for, made early.

Directing Claude Code through the build meant working the way I'd brief an engineering team: reviewing every response against intent, catching what didn't match, and deciding what "correct" meant in cases neither of us had fully anticipated. Testing deliberately included sites nothing like a typical client homepage: a single-purpose novelty page, a frozen 1996 web relic, a page that's just a solid color block. Edge cases are where a prompt's real failure modes show up, not the well-behaved sites it was tuned against.

The very first prototype, titled HEURISTICS, before AUGUR's rename or card system
Day one: a single field, no structure, still under the working name.
The first real AI response — raw markdown output, before any card design existed
The first real response — raw markdown, no schema, no cards yet. Everything since has been structure built on top of this.

Testing against sites designed to break assumptions

A novelty single-purpose site answers one question and nothing else — exactly the kind of page a rigid rubric might penalize for "missing" navigation or content it was never meant to have. AUGUR's evaluation of a one-word answer site correctly identified it as, arguably, one of the most efficient websites in existence: question in, answer out, zero clicks required. It didn't ding the page for the empty nav it was never going to need. Recognizing restraint as a legitimate design choice, not a deficiency, is a genuinely harder judgment call than flagging an actual violation. A blank, single-color page is the opposite stress test: confirming the tool reports "nothing here to evaluate" honestly, rather than inventing plausible-sounding findings to fill space.

Evaluation of a minimal novelty site, testing against manufactured findings
A deliberately minimal novelty site — testing whether the model recognizes restraint as intentional rather than penalizing it.
Evaluation of a blank solid-color page, in the final card UI
A blank solid-color page, run through the finished card UI — confirming honest "nothing here" output instead of manufactured findings.

What broke only in production

The gap between "works locally" and "works deployed" showed up hard on first launch. Vercel's build silently dropped the accessibility scanner's script file. It's read via a runtime-constructed path rather than a static import, deliberately, to route around a separate Next.js dev-bundler bug. But that meant the build's automatic file tracing couldn't detect it as a dependency, so it never shipped. Fixed by explicitly declaring the file in next.config.js, confirmed by inspecting the actual build trace manifest rather than guessing.

The next deploy broke differently: Vercel has no browser pre-installed at all, and the serverless-Chromium package's bundled binary — 64.8MB on its own — silently exceeded the platform's function size limit. The fix was a variant of that same package that downloads its binary from a hosted release at cold start instead of bundling it. A third, harder-to-see bug followed once that was live. Warm serverless containers get reused across requests, so Chromium's default profile directory was never cleaned up between invocations, intermittently crashing the browser mid-navigation. Traced to a documented issue in the library itself, and fixed by giving every invocation its own disposable profile directory.

AUGUR's generic error state, shown during the first failed Vercel deployment
The first production deploy, failing silently behind a generic error message — the starting point for three separate serverless-specific bugs, each diagnosed from real logs rather than guessed at.
PRODUCTION HARDENING

Protecting the product from its own cost

Every evaluation is a real, billed AI call — a public tool with no usage limit is a public tool with an unbounded bill. AUGUR caps evaluations at three per visitor per rolling seven-day window, checked before the browser launches, the scan runs, or Claude is called. The whole point is avoiding that cost for a request over the limit, not spending it and rejecting the result afterward.

Visitors are identified by two independent signals — a persistent cookie and IP address — each checked separately, blocked if either is exhausted. A single combined key would have meant either signal alone — clearing cookies, one click — resets the count to zero. Requiring both to be defeated at once is a meaningfully higher bar for the casual case this exists to stop. The counters live in Upstash Redis with a true sliding-window algorithm, not a fixed-TTL counter that resets all at once. That's a subtly different, and weaker, guarantee than what "3 per week" actually implies.

⸻ TWO INDEPENDENT BACKSTOPS
The rate limiter stops casual overuse. It is explicitly not the account's real safety net — that's a separate, account-level spend cap set directly in the Anthropic Console, which caps total cost regardless of how a request got made. Neither replaces the other. Each covers a failure mode the other doesn't.
AUGUR in production, protected by rate limiting and an independent Anthropic spend cap
The finished product these safeguards protect — live, public, and billed per evaluation.
VALIDATION & REFLECTION

What I'm proud of

The two-layer architecture held up under real, unpredictable testing. Dense pages, minimalist novelty sites, and blank pages all produced honest, right-sized output instead of padding to hit a fixed count. The trust signals aren't decoration: confidence tags, cited WCAG criteria, and the severity taxonomy tell a reader which parts of the output are fact and which are judgment worth double-checking.

What I'd improve next

The biggest gap is disclosure pacing — how many findings to show at once. A flat cap can lie in both directions: too low hides real failures, too high pads a clean result to look thorough. The fix is a default view I haven't built yet — two strengths, five or six priority issues, ordered by severity, the rest revealed progressively. Two smaller pieces after that: annotation markers directly on the screenshot, precise for verified findings and approximate for interpreted ones, and a shareable evaluation link — a full report compressed into a URL instead of a database row, so a result can go to a stakeholder without an account.

AUGUR running, full card interface
Where it all lands — the finished interface, cards and all.
FEATURED UX CASE STUDIES
DROP ME A LINE.

LET'S BE IN TOUCH:






JOSEPH IS BASED IN SAN FRANCISCO, CALIFORNIA: