seed-skills/pa11y-accessibility-ci/SKILL.md
Teach agents to automate accessibility testing in CI with pa11y and pa11y-ci, including thresholds, sitemap crawling, GitHub Actions gating, and WCAG rule tuning.
npx skillsauth add PramodDutta/qaskills Pa11y Accessibility CIInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are an accessibility automation engineer who adds reliable pa11y and pa11y-ci checks to web delivery pipelines without treating scanners as a replacement for manual WCAG review.
WCAG2AA or stricter rules in config so upgrades do not silently change expectations.Install pa11y-ci into the web project.
npm install --save-dev pa11y pa11y-ci start-server-and-test
npm pkg set scripts.a11y='pa11y-ci --config .pa11yci.cjs'
npm pkg set scripts.preview='vite --host 127.0.0.1'
npm pkg set scripts.a11y:local='start-server-and-test preview http://127.0.0.1:5173 a11y'
Use a dedicated config file instead of long CLI flags.
// .pa11yci.cjs
const baseUrl = process.env.PREVIEW_URL || 'http://127.0.0.1:5173';
module.exports = {
defaults: {
standard: 'WCAG2AA',
timeout: 30000,
wait: 500,
chromeLaunchConfig: {
args: ['--no-sandbox', '--disable-dev-shm-usage'],
},
hideElements: '.third-party-chat, .cookie-banner-test-only',
},
urls: [
`${baseUrl}/`,
`${baseUrl}/pricing`,
`${baseUrl}/login`,
`${baseUrl}/dashboard`,
],
threshold: 0,
reporters: ['cli', 'json'],
};
Create a small accessibility automation area that the whole team can understand.
.
.github/
workflows/
accessibility.yml
accessibility/
urls.json
crawl-sitemap.mjs
known-issues.md
.pa11yci.cjs
package.json
Use sitemap crawling when the product has many public pages.
sitemap.xml from the preview deployment.// accessibility/crawl-sitemap.mjs
import { writeFile } from 'node:fs/promises';
const origin = process.env.PREVIEW_URL || 'http://127.0.0.1:5173';
const sitemapUrl = `${origin}/sitemap.xml`;
const response = await fetch(sitemapUrl);
if (!response.ok) {
throw new Error(`Could not fetch sitemap: ${response.status}`);
}
const xml = await response.text();
const urls = [...xml.matchAll(/<loc>(.*?)<\/loc>/g)]
.map((match) => match[1])
.filter((url) => url.startsWith(origin))
.filter((url) => !url.includes('/logout'))
.slice(0, Number(process.env.PA11Y_MAX_URLS || 50));
await writeFile('accessibility/urls.json', `${JSON.stringify(urls, null, 2)}\n`);
console.log(`Wrote ${urls.length} URLs for pa11y-ci`);
Point the config at the generated list when required.
// .pa11yci.cjs
const urls = require('./accessibility/urls.json');
module.exports = {
defaults: {
standard: 'WCAG2AA',
timeout: 30000,
},
urls,
threshold: Number(process.env.PA11Y_THRESHOLD || 0),
};
Run the accessibility gate after the app builds and the preview server starts.
name: accessibility
on:
pull_request:
push:
branches: [main]
jobs:
pa11y:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run build
- run: npm run a11y:local
- uses: actions/upload-artifact@v4
if: always()
with:
name: pa11y-results
path: pa11y-ci-results.json
Use ignore only when there is a documented reason.
module.exports = {
defaults: {
standard: 'WCAG2AA',
ignore: [
// Temporary until design system token QA-1284 is fixed.
'color-contrast',
],
},
urls: ['http://127.0.0.1:5173/'],
threshold: 0,
};
When pa11y fails, inspect the page, selector, context, and rule.
npm run a11y:local.| Need | Pa11y Choice | Agent Action |
|---|---|---|
| Small public site | Static urls list | Keep direct route coverage explicit |
| Large marketing site | Sitemap crawler | Cap URL count and exclude unsafe paths |
| Pull request gate | threshold: 0 | Fail new violations immediately |
| Legacy app | Temporary threshold | Track debt and lower threshold over time |
| Third-party widget noise | hideElements | Hide only non-product widgets |
| Rule exception | ignore | Require issue link and expiry |
threshold high forever.hideElements.WCAG2AA or stricter.development
Generate test data from the schemas you already have. Read OpenAPI, JSON Schema, SQL DDL, or TypeScript models and produce deterministic factories, boundary and negative cases, relational datasets with valid foreign keys, cleanup scripts, and PII-safe synthetic data. Production records never leave the machine.
development
Diagnose flaky test failures from Playwright reports, traces, and rerun history. Classify each failure as product, test, environment, data, or unknown with cited evidence and a proposed fix. Never auto-modifies code without opt-in.
tools
Test LLM, RAG, MCP, and agentic systems end to end. Build golden datasets, run deterministic checks and LLM judges, score retrieval, probe prompt injection, verify tool use, and gate CI on thresholds. Orchestrates DeepEval, Ragas, promptfoo, and Langfuse.
development
Analyze a git diff, map affected risks, select the tests that matter, detect coverage gaps on changed lines, run configurable quality gates, and produce a go/no-go release report with cited evidence. Recommends only; never merges or deploys.