Widget
One line of code. An interface for your visitors, and an engine that patches real barriers.
The widget is two things in one script tag, and this page keeps them apart: a panel any visitor can open and tune, and a background engine that applies fixes in the page as it loads. Every fix is labelled deterministic, inferred or declined, and every site gets a table naming the rules that ran and the rules that did not.
- Automated coverage ≈ 1/3 of WCAG
- axe-core 4.10 engine
- 33 languages
Read this part first
A bridge while you fix the source, not a destination
An overlay runs in the browser, on top of markup it did not write. That is genuinely useful on the day you install it, and it is still second best: the fix that lasts is in your own code. So every fix the engine applies is also emitted as a patch your developers can merge, and taking the script tag off once the source is fixed is a supported outcome rather than something we argue you out of.
What automation cannot findIt is not a substitute for accessible code
Compliance is a legal determination, not a product feature.
Automated coverage ≈ 1/3 of WCAG
Audit, remediate, monitor
- Step 1
Audit
Automated checks across your templates, plus a background scan of the DOM as it is actually rendered on your site.
- Step 2
Remediate
Deterministic and inferred fixes applied live from a signed manifest, each one labelled and each one also available as a patch.
- Step 3
Monitor
A full rescan every 24 hours, and a per-page structure hash sampled at page load so a changed template is re-audited within the hour.
Half one · the interface
An interface every visitor can tune
A trigger button sits in the corner of your site. Opening it shows, in this order: the language selector, a search field, the seven profiles, the three groups of individual adjustments, your accessibility statement, and the controls for getting the widget out of the way. Nothing in the panel touches your page until a visitor asks for it.
Seven profiles
A profile is a preset, not a lock. Turning one on switches a group of adjustments, and the visitor can then change any of them one at a time. The panel shows which profile set a control and marks it customised once they do.
35 adjustments, in three groups
Every adjustment is an independent control with its own keyed component, so a licence can hide one it does not want offered. Steppers announce a human value rather than a percentage of an internal scale, and a control that a site overrides says so instead of pretending to be on.
Content14 controls
- Content scaling
- Readable font
- Dyslexia-friendly font
- Text magnifier
- Line height
- Letter spacing
- and 8 more
Colour9 controls
- Dark contrast
- Light contrast
- High contrast
- Monochrome
- Text colour
- Background colour
- and 3 more
Orientation12 controls
- Reading mask
- Reading guide
- Stop animations
- Hide images
- Highlight focus
- Big black cursor
- and 6 more
Languages, shortcuts, and getting out of the way
33 languages
The interface strings ship in 33 languages, chosen from the panel or matched to the visitor’s browser. We do not translate your page content. A machine translation of your own copy, served under your name, is a liability we are not taking on.
Keyboard shortcuts that yield
Alt and 1 opens the panel, Alt and 9 opens settings, Alt and 0 hides it. None of them fire inside a form field, so the widget cannot steal a keystroke from your checkout. Tab reaches the trigger; the trigger never opens anything by itself.
Hide for 24 hours, or hide on this site
A visitor who does not want the widget can dismiss it for 24 hours, or turn it off on your site until they restore it. The site-level choice says plainly that it needs the restore link or a browser-data clear to undo, because a hidden control a person cannot get back is a trap.
No cookies, and a statement to link
Preferences live in localStorage under one key, per origin, and no cookie is set. The statement button opens the accessibility statement generated for your licence within 48 hours, or your own page if you would rather point somewhere else.
Half two · the engine
What happens behind the scenes
The panel is what your visitors see. The engine is the part that changes your pages: it audits your templates on our workers, compiles fixes, checks that they actually helped, and only then publishes a manifest the widget applies in the browser.
Discover
Crawl from your base URL, sitemap first and then links, up to your plan’s page cap. URLs are grouped into templates by DOM shape, so a five-thousand-page store becomes a few dozen templates rather than five thousand audits.
Audit
axe-core 4.10 plus our own rule pack for the things axe does not cover: keyboard traps, focus order, dialog semantics and route announcement in single-page apps.
Compile fixes
Each finding is classified deterministic, inferred or declined. Deterministic fixes follow mechanically from the markup. Inferred fixes are proposed from context and have to pass a refusal gate. Anything that fails the gate becomes declined, with the question a person needs to answer.
Verify
The captured page is reloaded in a fresh browser context with the candidate manifest applied, and axe runs again. Any fix that increases violations is dropped before it ever reaches your site. The before-and-after counts are the only evidence our marketing is allowed to cite.
Publish
Surviving fixes ship as a signed runtime manifest keyed to the URL pattern, and as a code patch against the captured HTML. The manifest is what the widget applies. The patch is what your developers merge.
Every fix carries its label
The label is on the fix in the manifest, in the patch, in the report and in the coverage table, not a category we sort things into afterwards.
- Deterministic
- The fix follows from the markup with no judgement involved: a missing lang attribute, a duplicate id, a heading level out of order, an aria-label copied from the visible label next to it.
- Inferred
- A model proposed the fix from surrounding context: alt text from the image bytes and the copy around them, a name for an icon button from what it sits beside. Shown with the reasoning, and reversible.
- Declined: needs a person
- Neither of the above held, so nothing was applied. A confident wrong aria-label misleads screen reader users for years; a missing one is caught by the next audit. Declined items are listed with the question a person has to answer.
What the engine will not do
- It will not overwrite an attribute you already set. If an element already carries the attribute a fix wants to write, the fix is skipped. Your own accessibility work wins.
- It will not ship a fix that made things worse. Verification re-runs axe with the manifest applied, and any candidate that raises the violation count is dropped rather than published.
- It will not guess indefinitely. The compiler stops at 20,000 images or links on one site and the portal says the scope was exceeded, rather than quietly truncating your report.
- It will not turn a declined item into a fix by trying again. Declined stays declined until a person answers the question, and it stays visible in your coverage table and monthly report while it waits.
Evidence
A coverage table for your site, and a statement you can publish
The table is per site and it names rules, not just failures: what the engine addressed, what it only partly addressed, and what it never touched. A rule that was never run is listed as not run. That last column is the one most tools leave out.
| WCAG 2.2 success criterion | Status | How |
|---|---|---|
| 1.1.1 Non-text content | Addressed | Deterministic and inferred |
| 4.1.2 Name, role, value | Addressed | Deterministic |
| 2.4.4 Link purpose | Partly addressed | Inferred, 3 declined |
| 1.4.3 Contrast (minimum) | Partly addressed | Theme adjustments only |
| 2.4.6 Headings and labels | Not addressed | Declined: wording is a judgement |
| 1.2.2 Captions (prerecorded) | Not addressed | Outside what we do |
Install
Goes live in minutes
One script tag, carrying the site key for the licence it belongs to. Paste it before the closing body tag, or install through Google Tag Manager, the WordPress plugin, the Shopify app, or a React and single-page-app integration that re-applies on route change.
The snippet, with a placeholder site key
<!-- latchkey via manual -->
<!-- We do not put an integrity hash on this URL because we ship security fixes to it. -->
<script src="https://thelatchkey.in/w/v1/widget.js" data-lk-key="lk_site_XXXXXXXX" async></script>How licences and hostnames work
- One licence per site. One script tag per registered hostname, and the config endpoint answers only for hostnames that licence has claimed.
- www and apex are one licence. example.com and www.example.com are the same site to you, so they are the same site to us and the same bill.
- Staging and preview hostnames are free. Add them under allowed hostnames and they serve without a second licence, marked no-index. A subdomain that is genuinely a different site is a different licence.
- A copied snippet does not work elsewhere. The site key is public. It is in your page source. What stops it being useful on someone else’s domain is the hostname check: an unlisted host gets a refusal, the loader removes itself, and one console line names the host and where to fix it.
Performance and safety budget
A loader budget of 12KB gzipped
No cookies, on your site or ours
A kill switch per site
A patch for every runtime fix
Pricing
Priced on the traffic you actually have
Visits are counted by the widget’s own beacon. Subscriptions are sold by Dodo Payments as merchant of record, which is what appears on your card statement.
Questions people actually ask
Start finding barriers on your own site
Seven days, no card. You get the interface, the engine, the labelled fixes and the coverage table that says what none of them touched.