Internal Tool

A11y

An accessibility tool that finds issues, proposes fixes as real code diffs, then reruns the checks to prove which fixes worked.

Client
Self
Year
2026
Role
Product Design, UX/UI Accessibility, Technical Implementation, Code review and Deployment

Project overview

A11y audits a web page, pasted source code (HTML, JSX, TSX, CSS) or a Figma design against WCAG 2.2 AA, 2.1 AA, 2.0 AA or an AODA profile. Each finding carries its evidence, its WCAG criterion and its source line. Fixes are reviewed one at a time, combined into a patch and verified by a second scan.

Overview: 29 findings by kind and impact, remediation status, and a map of 55 WCAG criteria showing which were reached by automation

‍

Problem

Most accessibility tools stop at a list of problems. Teams still have to work out the fix, apply it, and check whether it worked or broke something else.

Users

Me first, as a designer doing accessibility work. Later, accessibility professionals and teams working to AODA in Ontario and WCAG elsewhere.

Intended outcome

Find it, fix it, prove it: a tool where no fix counts until a rescan confirms it.

My role

Product owner and designer. I wrote the product brief, co-built the code with Claude Code, reviewed it in VS Code and hand-tested it

Status

Working locally (v0.1.0). Not public yet: licensing, policy and documentation checks come first.

‍
The challenge

Automated checks reach only part of WCAG, and a "correct" fix can still break something else. A useful tool has to be honest about both, without becoming another list of warnings.

  • Trust. The tool cannot overclaim. Passing automated checks is not conformance, and the AODA profile is a technical reading, not legal advice.
  • Human judgement. Alt text, accessible names and labels carry meaning. Software that invents them produces confident nonsense.
  • Second-order effects. A fix can expose a new failure. That only shows up if you test again under the same conditions.
  • Security. Scanning any URL on request is a server-side request forgery risk, and pasted code must never run.
  • Practicing what it preaches. An accessibility tool that fails its own audit has no credibility.

‍

My approach

The brief I wrote framed the product in three words: find it, fix it, prove it. Every design decision follows from making those three steps honest.

Honest findings. Results are split into four kinds, kept visibly apart: violation, heuristic, needs review and inconclusive. When a background can't be resolved (image, gradient, overlap, translucent layers), contrast is marked inconclusive and no ratio is shown. Ratios are truncated, never rounded, so 4.497 can never read as 4.50.

Show what automation cannot reach. The Overview maps all 55 WCAG 2.2 AA criteria. On the bundled test page, automated checks reached 18 of them, and the other 37 are shown as needing a person.

Overview: 29 findings by kind and impact, remediation status, and a map of 55 WCAG criteria showing which were reached by automation
Findings: filterable table with impact, criterion and status, and a detail panel showing the affected element, evidence and recommended fix

‍

Three levels of fix confidence. Each fix is labelled high-confidence, review recommended or manual assessment required. For anything that carries meaning (alt text, names, labels, page titles), the tool never writes the words. It asks the person, and only then produces the edit.

Remediation workspace: an image with no alt text, where the person types the alt text and the side-by-side diff updates

‍

Explain the trade-off, not just the number. Contrast fixes keep the hue and move lightness by the smallest step that passes. The tool shows the before and after ratios on a scale, and warns when a CSS rule may style other elements too.

Contrast fix: #9a9a9a at 2.81:1 changed to #767676 at 4.54:1, shown on a scale with a warning that the rule may affect other elements

‍

Built for low-vision readers. The interface uses Atkinson Hyperlegible Next and Mono from the Braille Institute, with light and dark themes and a layout that works down to 360 px.

Design to implementation

The product promise became the architecture. Verification is a separate step that rescans, so the interface can never show a fix as resolved on trust.

Findings point at exact characters. Before rendering, every start tag is stamped with its source position as its first attribute, so the position survives the engine's shortened snippets. Fixes edit only those characters, and a reviewer sees each change as a side-by-side or unified diff.

Code is read, never run. Submitted HTML loads in a sandbox whose content security policy blocks every script. JSX is turned into static HTML through the TypeScript compiler, never executed, and the audit says so on every screen.

The rerun reports what a patch broke. On the bundled clinic page, correcting a misspelled aria-labeledby exposes a new aria-prohibited-attr failure. Swapping a div role="button" for a native button reveals that the page's button:focus { outline: none } now hides focus. Verification catches the side effects of a "correct" fix.

After verify: accepted fixes show Resolved on rerun, the rejected fix shows Still failing, with the zoom fix diff open

‍

Reports never overclaim. Every export states the standard, scope, engine version and limits, and includes a manual-review checklist for every criterion in the profile. Exports cover a .patch file that applies with git apply, the patched file, JSON, CSV and print to PDF.

Report: target, standard, engine, tested state and summary counts, with JSON, CSV and PDF export

‍

Engineering quality

Note on the one integration failure. It expects a 401 page to be reported as "access denied". The Chromium in my workspace (141) throws an error on an empty 401 response instead of returning it, so the tool reported "unreachable". The build notes record this suite passing on the expected browser. It is still worth handling, since a scanner can meet more than one browser version.

Security as a design constraint. Each URL scan runs its own forward proxy. Every hop, including redirects, images and websockets, is resolved, refused if any address is private, and then connected to the exact address that was checked. This closes the DNS-rebinding gap that a check-then-fetch approach leaves open. Tests confirm that an internal server receives zero requests.

Git and delivery. The repository is public on GitHub, and I push through GitHub Desktop. History shows 16 conventional commits from the build session and my rename commit across 18 files. There is no CI pipeline, and the app is not deployed: it needs a long-running Node server with Chromium, and I am completing licensing, policy and documentation checks before it goes public.

‍

Outcome

A11y v0.1.0 runs end to end on my machine: scan, review, fix, verify and export. I use it for my own accessibility work.

  • Shipped locally: URL, source and Figma JSON audits; WCAG 2.0, 2.1, 2.2 and AODA profiles; the remediation workspace; verification; and JSON, CSV, PDF and .patch exports.
  • Verified in a fresh environment: on the bundled test page, a live scan found 29 issues. Three accepted fixes (zoom, alt text, contrast) were all resolved on rerun, the rejected fix stayed failing, and the patch introduced no new failures.
  • Test suites: 236 of 236 unit, 16 of 16 end to end, and 16 of 17 integration tests passed (one failure explained above).
  • No usage metrics yet. It is not public, so there are no user numbers to report.

Phone, dark theme: Overview of the demo audit with findings by kind and impact

‍

Still open

  • Licensing, policy and documentation checks before a public release.
  • Deploy as a Node server with Chromium, and move rate limits to shared storage for more than one instance.
  • Live Figma import and AI explanations are built but switched off until tokens are configured.
  • The GitHub pull-request integration is a written design in docs/github-integration.md, not code yet.
  • Logo and visual identity for the A11y name.

Skills demonstrated

Product design

A brief built on find, fix, prove; fix confidence as a product concept; limits stated in the product itself

UX/UI and accessibility

Four finding kinds kept apart; the person writes anything that carries meaning; a criteria map showing what automation cannot reach; low-vision typeface

Technical implementation

Rescan-based verification, source-line tracing, a script-free sandbox, Figma JSON analysis

Code review and quality

Reviewed AI-written code in VS Code; the app audits itself and passes in both themes

Testing and delivery

Unit, integration and end-to-end suites; Git through GitHub Desktop

‍

Tools and technology

Design

Atkinson Hyperlegible Next and Mono, Lucide icons, light and dark themes. [NEEDS CONFIRMATION: Figma or other design files]

Development

Next.js 16 App Router, React 19, strict TypeScript 6, Tailwind 4, Zod 4, Playwright-driven Chromium, axe-core 4.14, diff

Testing

Vitest (unit and integration), Playwright (end to end), axe-core self-audit, ESLint

Version control and deployment

Git, GitHub, GitHub Desktop. Not deployed; no CI pipeline yet

AI-assisted

Claude Code for shared code authorship; an optional AI explanation feature, off by default, that treats finding data as untrusted input


Project links

Live product

Not public yet

GitHub repository

github.com/dannycyph3r/A11y-workbench

‍

Reflection

  • What I learned. In accessibility, "fixed" is a claim that needs evidence. Making verification its own step changed the whole product, from the state model to the report wording.
  • What I would improve. Test against more than one browser version. The 401 case showed that error handling can depend on the exact Chromium build.
  • What I would do next. Finish the licensing and policy work, deploy a hosted version, and build the GitHub pull-request integration so fixes can arrive as reviewable PRs.

‍

See All Projects