motir.co's /explore, /explore/topic and /docs pages render NO main landmark — the skip link has no target and a screen reader re-reads the banner on every navigation
Opened by Zhu Yue ·
Found by the smoke spec of MOTIR-4112's new Playwright lane, on motir-marketing origin/main 9a201de, 2026-09-02. Out of that card's scope — it builds the lane, it does not fix what the lane finds.
The measurement
getByRole('main') on /explore times out. The accessibility snapshot Playwright captured shows the page's whole tree with a banner, a navigation, headings, a search, lists and a contentinfo — and no main.
git grep -l '<main' -- app # motir-marketing @ 9a201de
app/page.tsx
app/design/page.tsx
app/legal/page.tsx
app/legal/[slug]/page.tsx
Four pages have one. The rest do not, and the set that does not includes the two most-linked surfaces on the site:
| route | main landmark |
|---|---|
/ · /design · /legal · /legal/[slug] | ✅ |
/explore | ❌ |
/explore/topic/[slug] | ❌ |
/docs and every page under it | ❌ |
Why it matters more than it looks
/explore is the public directory — the surface MOTIR-3877 is about to make the entrance to every public project page. A page with no main:
- gives a skip-to-content link nothing to skip to, so a keyboard user tabs the entire banner and nav on every arrival;
- removes the landmark a screen-reader user navigates by (
Din NVDA, the rotor in VoiceOver), so the only way to reach the content is to read past the chrome again on each navigation; - is a WCAG 2.1 AA issue under 2.4.1 Bypass Blocks in practice, and it is the one bypass mechanism this site does not otherwise provide.
The shape of the fix, and the part that is NOT mechanical
The four pages that have one put <main> in the PAGE. That is why the others do not have one — nothing in the shared chrome supplies it, so each page has to remember, and most did not. A fix that adds <main> to each remaining page re-creates the same defect for the next page somebody writes.
So the fix belongs in the shared chrome, and it has a real question in it: the four pages that already render <main> would then nest one inside another, which is invalid. Decide whether the chrome owns the landmark and those four drop theirs, or the chrome renders it only where a page does not — and say which, in the layout's own comment.
Acceptance criteria
- Every route this site serves renders exactly ONE
mainlandmark — asserted by a test that ENUMERATES the routes rather than listing them, so a page added later cannot ship without one. - No page nests a
maininside another; the four pages that render their own are reconciled with whatever the chrome does. - The skip-to-content affordance (if the chrome has one, or once it does) targets that landmark and is exercised by a keyboard-driven assertion.
/explore,/explore/topic/[slug]and the/docstree each pass; the assertion runs in an existing lane with no new CI job.
Context refs
motir-marketing/app/explore/page.tsx·app/explore/topic/[slug]/page.tsx·app/docs/**— the pages with no landmarkmotir-marketing/app/page.tsx·app/design/page.tsx·app/legal/page.tsx— the four that have one, and where they put itmotir-marketing/app/_components/— the shared chrome, and where the fix probably belongsmotir-marketing/e2e/specs/smoke.spec.ts— the spec that found it; its landing-page case is the one that passesmotir-core/design/public-site/— the chrome as drawn
Discussion
No comments yet.
Adding to this discussion signs you in on app.motir.co and brings you back to this request.