Accessibility Audit Toolkit
A comprehensive WCAG 2.1 compliance toolkit that gives frontend teams everything they need to build inclusive web applications. Includes automated audit configurations for axe-core and Lighthouse, screen reader testing scripts for NVDA/VoiceOver/JAWS, a complete ARIA pattern library with copy-paste components, and a structured checklist that maps every WCAG 2.1 success criterion to actionable code changes. Stop guessing at accessibility — ship with confidence.
Key Features
- WCAG 2.1 Level AA Checklist — 78 success criteria mapped to specific HTML/ARIA fixes with code examples for each
- axe-core Configuration Pack — Pre-built rule sets for CI pipelines, including custom rules for SPA-specific issues like focus management
- Screen Reader Testing Scripts — Step-by-step test scripts for NVDA (Windows), VoiceOver (macOS/iOS), and TalkBack (Android)
- ARIA Pattern Library — 25+ accessible component patterns: modals, tabs, accordions, comboboxes, data grids, and tree views
- Lighthouse CI Integration — GitHub Actions workflow that blocks PRs failing accessibility thresholds
- Color Contrast Analyzer — Utility functions to validate contrast ratios against WCAG AA/AAA standards programmatically
- Keyboard Navigation Audit — Focus trap utilities, skip-link patterns, and roving tabindex implementations
Quick Start
- Extract the archive into your project root
- Install the axe-core dev dependency:
npm install --save-dev @axe-core/react axe-core
- Add the audit script to your app's development entry point:
// src/lib/a11y-dev.ts
import React from 'react';
import ReactDOM from 'react-dom';
if (process.env.NODE_ENV === 'development') {
import('@axe-core/react').then((axe) => {
axe.default(React, ReactDOM, 1000, {
rules: [
{ id: 'color-contrast', enabled: true },
{ id: 'label', enabled: true },
{ id: 'aria-roles', enabled: true },
],
});
});
}
- Run the Lighthouse CI audit:
npx lhci autorun --config=./a11y-toolkit/lighthouserc.json
Architecture / How It Works
The toolkit is organized into four layers that work independently or together:
accessibility-audit-toolkit/
├── checklist/ # WCAG 2.1 criterion-by-criterion checklist
│ ├── perceivable.md # 1.x criteria (images, captions, contrast)
│ ├── operable.md # 2.x criteria (keyboard, timing, seizures)
│ ├── understandable.md # 3.x criteria (readable, predictable, input)
│ └── robust.md # 4.x criteria (parsing, name/role/value)
├── configs/ # Automated testing configurations
│ ├── axe-core.config.ts # axe-core rule customization
│ ├── lighthouserc.json # Lighthouse CI thresholds
│ └── jest-axe.setup.ts # Jest + axe integration
├── patterns/ # ARIA component patterns
│ ├── dialog-modal.tsx # Accessible modal with focus trap
│ ├── tabs.tsx # ARIA tabs with roving tabindex
│ ├── combobox.tsx # Autocomplete combobox pattern
│ └── ... # 22 more patterns
└── scripts/ # Screen reader test scripts
├── nvda-test-plan.md
├── voiceover-test-plan.md
└── keyboard-audit.md
Usage Examples
Jest + axe-core Integration Test
import { render } from '@testing-library/react';
import { axe, toHaveNoViolations } from 'jest-axe';
import { LoginForm } from './LoginForm';
expect.extend(toHaveNoViolations);
test('LoginForm has no accessibility violations', async () => {
const { container } = render(<LoginForm />);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
Configuration
axe-core Rule Customization (axe-core.config.ts)
export const axeConfig = {
rules: {
// Enforce stricter contrast for large text
'color-contrast-enhanced': { enabled: true },
// Disable rules that conflict with your design system
'region': { enabled: false },
},
// Only audit the main content area (skip third-party widgets)
context: '#app-root',
// Set minimum impact level to report
resultTypes: ['violations', 'incomplete'],
};
Lighthouse CI Thresholds (lighthouserc.json)
{
"ci": {
"assert": {
"assertions": {
"categories:accessibility": ["error", { "minScore": 0.95 }],
"color-contrast": "error",
"label": "error",
"image-alt": "error"
}
}
}
}
Best Practices
- Test with real screen readers — automated tools catch ~30% of accessibility issues; manual testing catches the rest
- Add accessibility tests to CI — use the included GitHub Actions workflow to block inaccessible PRs before merge
- Use semantic HTML first — reach for ARIA only when native elements can't express the interaction pattern
- Test keyboard navigation paths — every interactive element must be reachable and operable via keyboard alone
-
Announce dynamic content — use
aria-liveregions for toast notifications, form errors, and loading states - Validate with real users — schedule quarterly testing sessions with users who rely on assistive technology
Troubleshooting
| Issue | Cause | Fix |
|---|---|---|
| axe reports violations inside third-party components | axe scans the full DOM by default | Set context in config to scope scanning to your app root |
| Focus trap doesn't work in modal | Portal renders outside the trap container | Mount the focus trap inside the portal wrapper, not outside it |
| Lighthouse CI fails but site looks fine | Score thresholds are set too strict for initial adoption | Lower minScore to 0.85, then increment by 0.02 each sprint |
| Screen reader skips dynamic content | Missing aria-live attribute on updated region |
Add aria-live="polite" to the container that receives dynamic updates |
This is 1 of 11 resources in the Frontend Developer Pro toolkit. Get the complete [Accessibility Audit Toolkit] with all files, templates, and documentation for $29.
Or grab the entire Frontend Developer Pro bundle (11 products) for $129 — save 30%.
Top comments (0)