Most Teams Only Test One Screen Reader. Here’s the Problem With That.
If you’re a frontend developer who cares about accessibility and or has to do the laborious task of screen reader testing for your web experiences, how many screen readers do you actually test with before shipping?
For most teams, the answer is one.
Not because they don’t care about accessibility. Not because they don’t want to test more thoroughly.
Because the tooling ecosystem makes it surprisingly difficult.
The Cross-Platform Screen Reader Problem
Today, testing screen reader accessibility typically means testing across multiple screen readers:
- NVDA (Windows only)
- JAWS (Windows only, paid license)
- VoiceOver (macOS and iOS only)
- Narrator (Windows only)
- and honestly more like Orca ChromeVox and whatnot
The challenge is obvious:
- macOS developers can test VoiceOver natively
- Windows developers can test NVDA, JAWS, or Narrator
- Most teams don’t maintain accessibility testing environments across every operating system
- Almost nobody manually validates every component against all four screen readers during day-to-day development
As a result, accessibility bugs often survive until late QA cycles—or worse, production.
The feedback loop is broken by platform lock-in.
The Hidden Problem: Screen Readers Don’t Agree
Many developers assume that if a component works in one screen reader, it will behave similarly everywhere else.
In reality, screen readers frequently announce the same element differently.
Consider a simple button:
Submit form
so Using Speakable like so:
npx @reticular/speakable analyze button.html --renderer all
We get this output:
── VoiceOver ──
"Submit form, button"
── NVDA ──
"button, Submit form"
── JAWS ──
"Submit form button"
── Narrator ──
"Submit form, button, to activate press Enter"
At first glance these differences may seem minor.
But announcement order, punctuation handling, verbosity, and interaction hints all influence how users understand and navigate interfaces.
A component can feel perfectly clear in one screen reader while becoming noticeably more confusing in another.
Without cross-testing, these differences remain invisible.
Now what I found Speakable does as a CLI and MCP tool is that it predicts what multiple screen readers will announce from a piece of HTML.
Instead of launching four separate screen readers across multiple operating systems, Speakable:
- Parses your HTML into an accessibility tree
- Interprets roles, names, states, and properties
- Runs that information through screen-reader-specific renderers
- Shows how each screen reader is likely to announce the content
The goal isn’t to replace manual testing.
The goal is to make accessibility feedback available during development instead of only during QA.
Think of it as:
Speakable + Screen Readers > Screen Readers Alone
Speakable helps catch issues between commits.
Real screen readers still provide final validation before release.
Catching Accessibility Regressions with Semantic Diff
One of the hardest accessibility problems isn’t finding bugs.
It’s preventing regressions.
A seemingly harmless markup change can completely alter what gets announced.
found that Speakable includes a semantic diff engine as well where instead of comparing raw HTML, it compares accessibility announcements. i.e
Before might have read:
"Search, edit text"
but after markup changed and it reads:
"edit text"
Suddenly you’ve lost the accessible name (oh god is this a lawsuit?).
The visual UI may look identical.
The accessibility experience changed significantly.
This makes semantic diff especially useful inside CI pipelines.
That means pull requests can surface accessibility-impacting changes automatically (we love regression catchers).
Full Accessibility Audits from the Command Line
Speakable also provides accessibility auditing without requiring browser DevTools.
The audit engine can identify issues such as:
- Missing labels
- Broken ARIA references
- Focusable elements without accessible names
- Roles missing required properties
- Invalid accessibility relationships
This creates a fast feedback loop directly from the terminal.
No browser setup required.
No navigating through multiple inspection panels.
Just run the audit and review the report.
Static Analysis Isn’t Enough
Modern web applications are increasingly dynamic.
Accessibility issues often emerge only after user interaction.
Examples:
- Opening a modal
- Filtering a combobox
- Triggering a live region update
- Moving focus between components
Static HTML analysis can’t fully capture those behaviors.
That’s why Speakable 1.4 introduced runtime accessibility analysis. allowing you to do things like this:
import { createRuntimeEngine } from '@reticular/speakable/runtime';
const engine = createRuntimeEngine(document);
engine.start();
engine.interact('click', '#open-modal');
engine.interact('tab');
const timeline = engine.getTimeline();
The resulting timeline shows accessibility-relevant events such as:
- Focus movement
- Role announcements
- ARIA state changes
- Live region updates
- Modal activation
This helps surface problems that traditional linting and static analysis tools often miss.
For example:
- Focus trapped incorrectly
- Focus escaping a modal
- Live regions that never announce updates
- Comboboxes that fail to communicate filtered results
Accessibility Checks Inside AI Coding Assistants
Another challenge with accessibility tooling is context switching.
Developers frequently jump between:
- Editor
- Browser
- Accessibility inspector
- Screen reader
- Documentation
Well with this new wave of MCP servers, Speakable can also run as an MCP server.
npx @reticular/speakable-mcp
Storybook Support for Component Libraries
For teams maintaining design systems or component libraries, Speakable can analyze Storybook deployments directly.
Point Speakable at a running Storybook instance and it will:
- Crawl stories
- Analyze rendered HTML
- Generate accessibility reports
- Produce component-level findings
Protected environments are supported as well through authentication headers, making it usable for internal Storybook deployments behind VPNs or enterprise authentication systems.
For design system teams, this creates a scalable way to evaluate accessibility across hundreds of components.
Links
npm
@reticular/speakable
Website
GitHub
https://github.com/R3TICULAR/AnnounceKit
Discord
Top comments (0)