Skip to content

dogfood: fresh saas scaffold has axe a11y violations (missing h1, color-contrast) #878

Description

@vivek7405

Problem

A freshly scaffolded saas app is not axe-clean out of the box, which is at odds with the "100% accessibility out of the box" claim (#656) and the accessible-web-components blog. Found by running axe-core against a fresh webjs create x --template saas while dogfooding blog claims.

Real axe-core violations (v4, resultTypes: ['violations']):

  • /login: page-has-heading-one (moderate). The generated login page has no <h1>.
  • /features/components (gallery): color-contrast (serious, 1 node). Some text on the gallery has insufficient contrast against its background.

The UI components themselves passed (no missing labels, names, or roles on inputs, buttons, dialog). These are scaffold page-content and theme-token issues, not component-API defects, but a user's first axe run on an unmodified scaffold still lights up.

Design / approach

Fix the generated content so a fresh scaffold is axe-clean:

  1. Give the generated app/login/page.ts (and signup) a real <h1> (the visible heading, or a visually-hidden one if the design uses a logo lockup).
  2. Fix the failing color-contrast token/pair on the feature gallery so it meets WCAG AA (4.5:1 for normal text). Identify the exact element via axe.run on /features/components and adjust the Tailwind/theme token.

Implementation notes (for the implementing agent)

  • Where: packages/cli/templates/ (saas login/signup pages) and the gallery templates under packages/cli/templates/gallery/, plus the theme tokens the generator emits (packages/cli/lib/{create,saas-template}.js for the theme/home). The contrast fix likely lives in the generated styles/theme token set.
  • Repro: generate a fresh app, boot it, run axe-core against /login and /features/components (inject axe.min.js, await axe.run(document, { resultTypes:['violations'] })). Do NOT eyeball the template; the generators emit strings, so verify in a generated app.
  • Landmine: contrast depends on the resolved oklch() theme tokens in light AND dark; check both themes.
  • Use the webjs-scaffold-sync skill to walk every scaffold surface and run generate + boot + check.
  • Consider a scaffold test that runs an axe smoke check on key generated pages so this cannot regress (ties into feat(ui): 100% accessibility out of the box + AI-agent a11y contracts #656).

Acceptance criteria

  • /login and /signup have an <h1>
  • /features/components passes axe color-contrast in light and dark themes
  • axe.run on the generated app's key pages returns zero violations
  • A scaffold test asserts the axe smoke check (counterfactual fails before the fix)

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Fields

No fields configured for issues without a type.

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions