Automated scans catch roughly a third of real accessibility issues — but that third is worth catching on every pull request, not just when someone remembers to check.
A Next.js project (App Router) you can run locally
Node.js and a package manager (npm, pnpm, or yarn) installed
Comfort running a test suite from the command line
Install Playwright and the axe integration as dev dependencies, then install Playwright's browser binaries.
Shell
pnpm add -D @playwright/test @axe-core/playwrightpnpm exec playwright install --with-deps chromiumCreate a test file that visits a real page in your app. This is the page an accessibility scan will run against.
e2e/accessibility.spec.tsTypeScript
import { expect, test } from "@playwright/test"; test("homepage loads", async ({ page }) => { await page.goto("/"); await expect(page).toHaveTitle(/./);});Import AxeBuilder, run it against the loaded page, and assert there are zero violations. Scoping to wcag2a/wcag2aa/best-practice keeps the scan focused on real, actionable rules.
e2e/accessibility.spec.tsTypeScript
import AxeBuilder from "@axe-core/playwright";import { expect, test } from "@playwright/test"; test("homepage has no automatically detectable accessibility violations", async ({ page }) => { await page.goto("/"); const results = await new AxeBuilder({ page }) .withTags(["wcag2a", "wcag2aa", "best-practice"]) .analyze(); expect(results.violations).toEqual([]);});Run the test. A passing scan prints nothing unusual; a failing one lists each violation with the specific element and rule that failed, which is usually enough to fix it directly.
Shell
pnpm exec playwright test e2e/accessibility.spec.tsRun the suite once against your unmodified page — it should pass. Then intentionally break something real (remove an image's alt text, or drop a form label) and run it again — the same test should now fail and name the specific violation. If both of those are true, the scan is doing its job.
Add a scan for every major page template, not just one — a single passing scan doesn't cover pages with different components
Wire the test into CI so an accessibility regression fails the build instead of shipping
Pair automated scans with a real manual pass — automated tools catch roughly a third of real issues; see the Accessibility Checklist playbook for what to check by hand