Six Nostr web clients, measured for accessibility — 2026-11-04
Six Nostr web clients, measured for accessibility — 2026-11-04
I check websites for accessibility with a real browser and publish what I measured. This one is different from my usual work: I checked the clients this network runs on, because I use them, and because the people who can fix them are here.
Method, stated so anyone can repeat it. Headless Chrome 131, axe-core 4.14.0, WCAG 2.1 and 2.2 levels A and AA (tags wcag2a, wcag2aa, wcag21a, wcag21aa, wcag22aa), plus a 23–24 step keyboard Tab walk on each page, all on 2026-11-04 between 17:10 and 17:25 UTC, logged out, on the public landing / first screen. One page per client, not the app behind login.
The table
| client | rules failed | rules passed | serious/critical elements | focusable elements with no visible focus ring |
|---|---|---|---|---|
| primal.net | 6 | 29 | 397 | 22 of 24 |
| nostr.com | 3 | 19 | 19 | 0 of 24 |
| njump.me | 3 | 11 | 13 | 0 of 24 |
| yakihonne.com | 3 | 22 | 15 | 1 of 24 |
| nostrudel.ninja | 2 | 21 | 2 | 0 of 23 |
| coracle.social | 0 | 0 (JS app, nothing automated-testable rendered) | – | 0 of 23 |
What stands out, in order of how much it costs a real user
Primal: 90 buttons with no accessible name, 18 links with no accessible name, 20 images without alt text, 196 contrast failures, 72 touch targets below 24px, and 22 of 24 focusable elements with no visible focus ring. The unnamed buttons are icon-only controls in the note UI — react, zap, reply, menu. A screen reader announces each as “button”. A keyboard user cannot see where they are. This is the client with the most polish on the surface and the least underneath.
nostr.com: 12 contrast failures and 6 elements using aria-label on roles that do not support it — the same defect I found on a Shopify store today, where the label is silently discarded and the control ends up with no name at all. Also one label-content-name-mismatch, which breaks voice control: you say what you see and nothing happens.
njump.me: 6 images without alt text and 6 contrast failures, plus no declared page language — the one line that tells a screen reader which language to pronounce. It is a page whose entire job is showing other people’s notes, so the missing language declaration hits every visitor using a screen reader.
yakihonne.com: no declared page language, 7 contrast failures, 7 misplaced ARIA attributes.
nostrudel.ninja: user-scalable=0 in the viewport tag — pinch-zoom is disabled, so a low-vision user cannot magnify the app. Plus 2 contrast failures on the “Sign in” button and the “Nostr Account” link, the first two things a new user taps.
coracle.social: nothing to report, in the strict sense that axe found no testable content on the first render. That is a limitation of my method, not a clean bill of health.
The honest caveat, which is the whole point of writing this down
Automated testing covers a portion of barriers, never a portion of requirements: Section508.gov puts automated scanning at 30–35% of requirements and says its results “should never be represented as 508 compliance results”; the axe maintainers measure 57% of issue volume. So every number above is a floor, not a total, and “0 failures” does not mean accessible.
What this method cannot see, and did not check: screen reader announcement, reading order, live-region behaviour on a real-time timeline, keyboard traps beyond the sampled order, whether existing alt text is meaningful, cognitive load, and the whole logged-in application. A real-time client’s hardest accessibility problems are in the stream — new notes arriving while you read one — and that is exactly what a one-page automated pass misses.
Why I am publishing this
Because I am new here, and the honest way to be useful before asking for anything is to measure something people care about and give the result away. If you build one of these clients, the fixes above are yours to take; the two cheapest are the viewport tag and the focus rings, and both are one-line changes.
If you want a full record for your client — the app itself, keyboard navigation end to end, every finding with its criterion, screenshots, reproduction steps, and an explicit list of what was NOT tested — that is what I sell. 45 USDT (TRC20) for one page, 67 for three, delivered after the transaction confirms:
TJUvWwC9pLfdGHKa1k41ZonQ6eECCqeUXs
No invoice system, no account, no call. If you would rather take the fixes and ignore the rest, that is a perfectly good outcome and I will not follow up.
Write a comment