Building AI Tooling That Knows What It's For
Give a model a live URL and ask it to find accessibility problems, and it'll try. It'll look at a screenshot, guess at what seems off, and hand back something plausible-sounding. That's also exactly the wrong way to build this. Accessibility violations aren't a matter of opinion, they're testable against a real spec, and a model eyeballing a screenshot is a worse detector than software that's been checking these exact rules for a decade. The real design question wasn't how to get AI to find issues. It was where AI actually adds something a deterministic tool can't, and where it should just stay out of the way.
What I built
Point it at any live URL and a Cloudflare Worker spins up a headless browser and runs axe-core, the same engine behind Chrome DevTools, against the real rendered page. That part is old, boring, and reliable on purpose. What a free scanner won't do is what happens next: instead of handing back a flat list of forty violations, the tool sends them to Claude, which groups them by shared root cause (the same broken color token showing up nine times isn't nine bugs, it's one) and drafts an actual ticket for each group, with a specific fix, not just a description of what's wrong. Priority isn't the model's call, that's arithmetic, severity times how many elements it hits, computed in code.
The AI's job is exactly two things: deciding which violations actually share a cause, and writing the ticket once they're grouped. The parts of this that need judgment get a model. The parts that don't get a formula I can defend.
What actually happened
I ran it against my own site first, mostly to get real test data. It came back with nine separate color-contrast violations, same rule, same generic description. A simpler tool would report nine bugs. This one split them into two: seven elements sharing one secondary text color that failed contrast, and two headings sharing a completely different color with a completely different failure. Same rule, two unrelated causes, and the model told them apart because it was reading the actual failing colors, not pattern-matching on which rule fired.
The more interesting lessons came from what didn't work the first time. Early on I caught a bug where bounding boxes were measured against the full page while the screenshot only captured the visible viewport, every overlay box would've pointed at empty space below the fold. And about halfway into scoping this, I almost built something that already exists: a straightforward WCAG scanner with visual overlays. Tools like that already do this, for free, built by people who specialize in exactly that. The actual gap wasn't detection, it was that none of them do anything with the results beyond listing them. That's the reason this exists as a triage tool instead of another scanner.
The strangest lesson showed up once the tool went live and I started testing it against sites I don't control. Most scan cleanly. One well-known site consistently failed partway through, and figuring out why turned into its own small investigation: was the site's bot protection closing the browser session, or was the page just heavy enough to run the scanner out of memory? Puppeteer actually lets you tell the two apart, it fires a distinct event specifically when the browser's renderer process crashes, separate from a normal navigation failure. Wiring that up meant the tool can tell a visitor which of those two very different things happened, instead of a raw error and a guess. A public scan-any-URL tool was never going to work on every URL. What matters is failing in a way that actually explains itself.
Why this matters beyond the demo
The useful version of AI here wasn't replacing the accessibility checker. It was sitting on top of a real one and doing the part that's genuinely a judgment call. That split is a product decision before it's an engineering one: knowing what to hand a team as forty flagged elements to fix one by one, versus three grouped root causes with a specific change each. The tool doesn't do accessibility work. It does triage, and triage is what actually clears a backlog.
Check it out at: https://a11y-triage.stephpawlowski.com
Full write-up on Github at https://github.com/stephpawlowski/accessibility-triage-tool
Read more about this project at Four Failures, One Bug and Looking for Trouble in My Own Tool