LiveSeptember 23, 2026 · one session
Sense Check
Judges whether the alt text, links, headings and labels on a page mean something, and sends the unclear ones to a person.
I built Sense Check for the part of accessibility testing that automated checkers leave to people: whether alt text says what an image shows, whether a link says where it goes, whether a heading describes its section. Rules settle what is certain, Jev judges the rest, and anything Jev is unsure about goes to a person. It is a first pass, not an audit, and it says so.
- WCAG success criteria it reads for
- 8
- certain problems settled by rules
- 13
- kinds of typed question Jev answers
- 6
- outcomes: fine, fix, or a person checks
- 3
- Jev requests a page at most, four at a time
- 11
- tests: a fixture page, a fake Jev, a local server
- 33
- a report is kept, so a refresh costs nothing
- 5 min
- records stored
- 0
Architecture
Five parts, without a database.
My role: Product owner and developer. I researched the gap, set the brief and shipped it to production, with Claude Code as my AI pair programmer.
src/lib/extract.tsThe page read like a screen reader: alt text, accessible names, headings with the prose after them, labels. Hidden parts skipped.
src/lib/sense.tsThe rules, the batched Jev questions, the confidence gate and the report.
src/lib/transport.tsThe fetcher shared with WP Front Door: private addresses refused before the request and inside the socket's DNS lookup.
src/lib/injection.tsPage text written to steer AI readers is kept away from Jev and flagged for a person.
src/appnext/form, a streamed loading state, a report grouped by what each finding says, and a JSON endpoint.
- Next.js 16
- React 19
- TypeScript
- Tailwind CSS 4
- node-html-parser
- Vitest
- Vercel
- Jev (TypeSafe AI)
Why it exists
Checkers find the missing alt text, not the useless one
Deque's coverage report found that automated tools catch 57% of accessibility issues by volume, yet raise issues for only 16 of the 50 WCAG 2.1 AA success criteria. Whether alt text, a link or a heading means something has always been left to a person, and the European Accessibility Act has covered e-commerce in the EU since June 28, 2025.
What it asks
- Images: would this alt text tell someone what the image shows, or where its link goes? Is it a file name, a generic word, a keyword list, a copy of the caption?
- Links: can a person tell where it goes from its text and its sentence, and could the text mislead them?
- Headings: does each one describe the section after it? Form fields: does the label say what to enter?
How it decides
Rules for what is certain, Jev for the judgement calls
A missing alt attribute, a file name as alt text, a link with no name, an empty heading, a field labelled only by its placeholder, a page with no language: rules settle those and never ask Jev. Everything else goes to Jev in batches, each question pointing at its item by path, and the answer's probability decides what happens next.
Confidence gating
- 70% or more likely fine: counted as fine
- 30% or less: reported as a fix, with what is wrong
- In between: marked for a person to check, with Jev's probability shown
Without a key
- The rules run alone, generic link text is marked for checking, and the report says how many items were left unjudged
Before release
What testing changed before release
Fixed before release
- The first real run, on a WordPress.org plugin page, reported the core image lightbox's images as missing alt text: they have no src and no alt until the lightbox opens. Hidden parts and images a script fills in are now skipped
- A linked image that is the whole link was reported twice, as an image and as a nameless link; it is now one finding
- A dropdown's options leaked into its label; a label now leaves out the control inside it
Readable reports
- The W3C's deliberately inaccessible demo page gives 38 findings; grouped by what they say, they read as five cards
Built to be run by strangers
A fetcher that cannot be turned on anyone
Addresses
- Only public addresses on standard ports, checked before the request and again inside the socket's own DNS lookup; redirects followed by hand, each hop checked
- Ten checks a minute per address and at most twenty checks of one site in ten minutes, whoever asks, on each server instance
The Jev key
- At most eleven Jev requests a page, under a daily budget, and reports kept five minutes
- Page text that addresses AI readers is kept away from Jev and flagged for a person
Tests and delivery
A fixture page with one of every problem
The extraction and the rules are tested against a product page built to hold one of each problem; the Jev path against a fake Jev that records every request, so the tests prove no page text ever reaches a question.
Checks before shipping
- Vitest, TypeScript strict, ESLint and a production build, on every push through GitHub Actions
- Live checks after deploying: HTTP to HTTPS, the security headers, a WordPress.org plugin page and the W3C demo page, and every refusal: loopback, cloud metadata, a decimal-encoded loopback, a non-standard port, credentials in the address
Hosting
- Vercel, from a private GitHub repository; no database and no paid service
Growth
Skills I sharpened.
- Accessibility
- WCAG 1.1.1, 1.3.1, 2.4.2, 2.4.4, 2.4.6, 3.1.1, 3.3.2 and 4.1.2; accessible names computed the way a screen reader reads them.
- AI engineering
- Jev (TypeSafe AI): fan-out over a page's items, and confidence-gated routing to human review.
- Security
- SSRF prevention with a guarded socket lookup, prompt-injection screening, per-site and per-address limits, a daily key budget.
- Next.js 16
- App Router, next/form, a streamed loading state, a grouped server-rendered report, a route handler.
- Testing
- Vitest with a fixture page, a fake Jev that records requests, and a local server for the transport.