Share an axe accessibility report
axe-core is the engine behind most automated accessibility testing, and its
output is a JSON object: violations, passes, incomplete, each with an
impact level, WCAG tags and a list of failing nodes.
Nobody triages accessibility from a JSON object. And accessibility is the one category of finding that genuinely needs three different people looking at the same thing.
Render the results
npm i -D @axe-core/playwright axe-html-reporter
import { AxeBuilder } from "@axe-core/playwright";
import { createHtmlReport } from "axe-html-reporter";
const results = await new AxeBuilder({ page }).withTags(["wcag2a", "wcag2aa"]).analyze();
createHtmlReport({
results,
options: { outputDir: "a11y", reportFileName: "axe.html" },
});
Cypress is the same call with cypress-axe's results object. The output is a
single self-contained page grouped by violation, with impact, the WCAG
criterion and every failing selector.
Publish it
Drag a11y/axe.html into the app, or from CI:
curl -fsS -X PATCH "https://commareports.com/api/v1/reports/$REPORT_ID" \
-H "Authorization: Bearer $COMMA_API_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n --rawfile html a11y/axe.html \
--arg title "Accessibility — $GITHUB_REF_NAME" \
'{title: $title, html: $html}')"
Run with if: always() so a run that trips an a11y gate still produces the
report that explains it.
Why this one benefits most from review
The findings split cleanly across roles, and each needs a different person:
color-contrast→ design.label,aria-required-attr→ engineering.heading-order,region→ whoever owns the page structure, usually both.
Anchored threads put each of those conversations on its own violation, so the report becomes the triage board rather than the input to one. See commenting on HTML.
Track the trend
PATCH one report id per surface (marketing site, app shell, checkout) and each run appends a revision. A remediation sprint then has an artifact: the same URL, fewer violations, with the history behind it.
A routine can re-run the scan weekly against production so regressions surface without a deploy triggering them.
Limits
- Entry HTML: 5 MB. Assets: 25 MB per file, 250 MB and 500 files total.
- 60 requests/minute per token.
Try it
Comma is free — unlimited reports, unlimited commenters, unlimited revision history.
Publish an accessibility report →