Skip to content

feat: add dev-only @axe-core/react accessibility checker- #1 - #1453

Merged
hman38705 merged 2 commits into
solutions-plug:mainfrom
petermuazu:main
Sep 1, 2026
Merged

feat: add dev-only @axe-core/react accessibility checker- #1#1453
hman38705 merged 2 commits into
solutions-plug:mainfrom
petermuazu:main

Conversation

@petermuazu

Copy link
Copy Markdown
Contributor

Closes #1328
Closes #1329
Closes #1330
Closes #1331

Summary

Restores the deleted @axe-core/react integration as a dev-only accessibility check that logs violations to the DevTools console during local development — catching issues before they ever reach CI's accessibility.yml (jest-axe / Lighthouse / axe-core / pa11y jobs).

The harness is attached to the React root via a client component rendered in the root layout, and is fully tree-shaken out of the production bundle — verified against a real Next.js/Turbopack production build, not just disabled at runtime.

Why

  • Dev feedback loop: axe violations are surfaced immediately in the browser console while developing, instead of surfacing only after a CI run.
  • Zero production cost: @axe-core/react (plus the ~1MB axe-core engine it carries) must never ship to production users. The integration relies on build-time constant folding of process.env.NODE_ENV so the guarded dynamic import is eliminated entirely from production output.

What changed

File Change
frontend/src/lib/reportAccessibility.ts New. Dev-only initializer: returns early unless NODE_ENV === 'development' (plus a typeof window SSR guard and a one-shot initialized flag), then lazy import()s @axe-core/react and calls axe.default(React, ReactDOM, 1000, config).
frontend/src/components/AxeAccessibility.tsx New. 'use client' component (renders null) that calls reportAccessibility(React) on mount.
frontend/src/app/layout.tsx Mounts <AxeAccessibility /> inside the root <body> so it shares the app's React/ReactDOM instances with axe.
frontend/src/lib/__tests__/reportAccessibility.test.ts New. Unit tests for the guard logic (see Testing).

Edge case: production tree-shaking (requirement)

The requirement states the integration must be fully tree-shaken from the production bundle, not merely disabled at runtime.

  • process.env.NODE_ENV === 'development' is statically replaced by Next.js at build time. In production the branch becomes false, and the guarded dynamic import('@axe-core/react') / import('react-dom') are dead-code-eliminated.
  • Verified via bundle analysis: built the exact pattern with a Next 16.2.11 / Turbopack production build and grepped every .next/static/chunks/*.js:
    • @axe-core/react reference: 0 matches
    • axe-core library content (color-contrast, landmark-one-main, html-has-lang, axe.run): 0 matches
  • The remaining harness in production is a handful of bytes (an empty reportAccessibility body plus a null-rendering component) — well within existing bundlewatch budgets.

⚠️ Note for reviewers: this tree-shaking behavior is bundler-specific. esbuild, for example, does not fold a guarded dynamic import and would ship all of axe-core — which is why verification was done against Next's actual compiler (Turbopack) rather than a generic bundler.

Testing

  • New unit tests (npx jest reportAccessibility) — all pass:
    • No-op when NODE_ENV is production.
    • Initializes @axe-core/react in development with the expected args (React, ReactDOM, 1000, config).
    • Only initializes once across repeated calls (Fast Refresh / route transitions don't double-patch ReactDOM).
  • Production bundle analysis confirms zero axe-core content (see above).

Out of scope / pre-existing issue

frontend/src/app/admin/content/page.tsx has broken relative imports (../../../../ resolves above src/) plus pre-existing type errors, so a full npm run build currently fails on that route — unrelated to this change. The touched files typecheck and compile cleanly in isolation. A follow-up to fix that admin route is recommended since it also blocks CI's build-based a11y audit jobs.

petermuazu and others added 2 commits August 29, 2026 13:49
Restore the deleted @axe-core/react integration as a dev-only check that
logs axe violations to the DevTools console during local development,
catching issues before CI's accessibility.yml runs. A client component in
the root layout initializes the harness only when NODE_ENV is development;
the guarded dynamic import is tree-shaken out of the production bundle
(verified against a Next/Turbopack production build, no axe-core content
in any chunk).

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
feat: add dev-only @axe-core/react accessibility checker
@drips-wave

drips-wave Bot commented Aug 29, 2026

Copy link
Copy Markdown

@petermuazu Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@hman38705
hman38705 merged commit f4e2682 into solutions-plug:main Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants