Configures Lighthouse CI's Accessibility category for automated accessibility testing (a11y / WCAG coverage) - `categories:accessibility` audits backed by axe-core (axe) - with per-URL minimum-score assertions (fail a build when a page's score drops below a threshold) and per-audit overrides, distinct from the Performance category that `lighthouse-perf` covers. Use when the project already runs Lighthouse CI for Web Vitals and the team wants to add accessibility coverage in the same pipeline rather than spinning up a separate scanner.
80
100%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Medium
Suggest reviewing before use
Lighthouse CI ships five audit categories: Performance, Accessibility,
Best Practices, SEO, and Progressive Web App. The Accessibility
category runs a curated subset of axe-core rules
(lhci). Configuring it via the same lighthouserc.js that
lighthouse-perf
uses keeps the audit pipeline unified.
This skill is the a11y slice of Lighthouse CI;
lighthouse-perf
is the Web Vitals slice. Both consume the same config; one CI run
produces both reports.
axe-a11y in unit/integration tests).If the project doesn't already use Lighthouse CI, prefer
axe-a11y directly - Lighthouse adds a
layer.
axe-a11y directly.npm install --save-dev @lhci/cli)..lighthouserc.js alongside any perf assertions - the categories:accessibility category score plus per-audit overrides on critical rules (Worked example).npx lhci autorun to collect, assert, and upload in one pass.minScore) and re-run npx lhci autorun until green.minScore over time - per-URL thresholds, the full audit-ID reference, and the GitHub Actions workflow live in references/advanced-config-and-ci.md.(Same as lighthouse-perf.)
npm install --save-dev @lhci/cliAdd the a11y assertions to the same .lighthouserc.js that
lighthouse-perf
uses for Web Vitals, so one config drives both categories:
// .lighthouserc.js
module.exports = {
ci: {
collect: {
url: [
'http://localhost:3000/',
'http://localhost:3000/dashboard',
'http://localhost:3000/checkout',
],
numberOfRuns: 3,
settings: {
preset: 'desktop',
chromeFlags: '--no-sandbox',
},
startServerCommand: 'npm run start',
},
assert: {
assertions: {
// Performance
'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],
'interaction-to-next-paint': ['error', { maxNumericValue: 200 }],
'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],
// Accessibility - category score (0-1)
'categories:accessibility': ['error', { minScore: 0.95 }],
// Per-audit overrides - error on critical-impact a11y rules
'aria-required-attr': ['error', { minScore: 1 }],
'button-name': ['error', { minScore: 1 }],
'label': ['error', { minScore: 1 }],
'meta-viewport': ['error', { minScore: 1 }],
// Lower-impact a11y rules - warn but don't block
'color-contrast': ['warn', { minScore: 1 }],
'image-alt': ['warn', { minScore: 1 }],
},
},
upload: { target: 'temporary-public-storage' },
},
};Per lhci, assertion levels are 'error' (CI fails),
'warn' (surfaced but doesn't fail), and 'off' (disabled).
Then run all three phases (collect / assert / upload) in one pass:
npx lhci autorunThe same command and flags (--collect.url, etc.) serve both
perf and a11y assertions. The Accessibility category score (0 - 1) reflects
axe-rule pass rate weighted by severity. A score of 1.0 doesn't mean perfect
a11y - manual testing per
screen-reader-test-author
remains essential, so assert specific audit IDs (button-name, label, ...) in
addition to the category score. The full audit-ID reference, per-URL thresholds
via assertMatrix, and the CI workflow live in
references/advanced-config-and-ci.md.
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Asserting only the category score | A score of 1.0 hides per-rule details; can't pinpoint regressions. | Assert specific audit IDs in addition to the category score. |
Setting categories:accessibility minScore: 1 | Strict; a single moderate-severity rule failure blocks every PR. | Start with minScore: 0.95; tighten over time. |
| Running only on the homepage | Most a11y bugs live on form-heavy / dynamic pages. | Audit a representative URL set. |
| Disabling the a11y category to "fix later" | "Later" never arrives. | Use a11y-violation-gate ratchet pattern. |
| Treating Lighthouse score as the gold standard | Lighthouse covers ~50-60% of WCAG; doesn't catch ARIA misuse, screen-reader issues, keyboard-only flow bugs. | Pair with manual testing + dedicated axe-a11y component scans. |
axe-a11y
in unit/integration tests for component-level.axe-a11y directly.lhci autorun,
configuration shape, assertion levels.assertMatrix thresholds, the full accessibility audit-ID table, and
the GitHub Actions workflow:
references/advanced-config-and-ci.md.lighthouse-perf - sibling skill for the Performance / Web Vitals category in
the same Lighthouse run.axe-a11y - direct axe-core usage for
component-level coverage.a11y-violation-gate - CI
gate consuming Lighthouse a11y output.