Accessibility validator: WCAG 2.1 AA, EN 301 549, EAA. Triggers: a11y, accessibility, WCAG, EAA, ARIA, contrast, keyboard, screen reader.
Scanned 5/28/2026
Install to Claude Code
npx -y skills add softspark/ai-toolkit --skill a11y-validate --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of A11y Validate?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/softspark-a11y-validate)More formats (shields.io, HTML) on the badges page.
---
name: a11y-validate
description: "Accessibility validator: WCAG 2.1 AA, EN 301 549, EAA. Triggers: a11y, accessibility, WCAG, EAA, ARIA, contrast, keyboard, screen reader."
user-invocable: true
effort: medium
disable-model-invocation: true
context: fork
agent: frontend-specialist
argument-hint: "[path] [--scope full|keyboard|contrast|forms|media|aria|motion|mobile|docs] [--standard wcag-2.1-aa|wcag-2.2-aa|en-301-549|eaa] [--severity high|warn|info] [--framework auto|react|next|nuxt|astro|gatsby|sveltekit|remix|angular|vue|react-native|flutter|static] [--output markdown|json]"
allowed-tools: Read, Grep, Glob, Bash
---
# /a11y-validate — Accessibility & EAA Compliance Scanner
$ARGUMENTS
Scan a codebase for accessibility issues using pattern-matching heuristics. Detects violations of **WCAG 2.1 Level AA**, **EN 301 549** (the EU harmonized accessibility standard), and the **European Accessibility Act** (Directive (EU) 2019/882, "EAA", in force since 28 June 2025). Read-only — never modifies files.
Complements `/seo-validate` (which only covers SEO-a11y overlap shallowly). Use this skill when the concern is legal accessibility compliance, not search engine ranking.
**Standards basis**:
- **WCAG 2.1** Level A + AA — W3C Recommendation 2018 (updated 2023).
- **WCAG 2.2** Level AA (opt-in via `--standard wcag-2.2-aa`) — adds 2.4.11 focus not obscured, 2.5.8 target size minimum, 3.2.6 consistent help, 3.3.7 redundant entry, 3.3.8 accessible authentication.
- **EN 301 549 v3.2.1** — EU harmonized standard; aligned with WCAG 2.1 AA plus additional chapters for mobile, hardware, ICT procurement, authoring tools, and functional-performance statements.
- **EAA / Directive (EU) 2019/882** — legal framework requiring EN 301 549 conformance for consumer-facing digital products and services in EU markets. Deadline: **28 June 2025**. Requires accessibility statements per member-state templates.
## Usage
```
/a11y-validate # Scan full project, auto-detect framework
/a11y-validate src/ # Scan specific path
/a11y-validate --scope keyboard # Only keyboard + focus checks
/a11y-validate --scope media # Only captions/transcripts/autoplay
/a11y-validate --scope docs # Only EAA accessibility-statement check
/a11y-validate --scope mobile # Only React Native + Flutter patterns
/a11y-validate --standard eaa # Activate EAA documentation category
/a11y-validate --standard wcag-2.2-aa # Add WCAG 2.2 criteria
/a11y-validate --severity high # Filter to HIGH findings
/a11y-validate --framework react-native # Force framework
/a11y-validate --output json # Structured JSON for CI integration
```
**Scopes:**
- `full` (default) — all 8 categories
- `keyboard` — Category 3 only
- `contrast` — Category 4 only
- `forms` — Category 5 only
- `media` — Category 6 only
- `aria` — Category 7 only
- `motion` — Category 8 motion subsection
- `mobile` — Category 8 mobile subsection (React Native / Flutter)
- `docs` — Category 8 EAA documentation subsection (fast "are we legally exposed?" scan)
**Standards:**
- `wcag-2.1-aa` (default) — 50 Level A + AA success criteria.
- `wcag-2.2-aa` — adds 2.4.11, 2.5.8, 3.2.6, 3.3.7, 3.3.8.
- `en-301-549` — wcag-2.1-aa + mobile chapter + functional-performance statements.
- `eaa` — en-301-549 + accessibility-statement documentation requirement (activates Category 8 docs).
**Severity filtering:** `--severity high` shows only HIGH, `--severity warn` shows HIGH+WARN, `--severity info` shows all. Default: all.
## What This Command Does
1. **Detect framework** from `package.json`, `pubspec.yaml`, and entry HTML.
2. **Scan the codebase** using `Grep` / `Glob` / `Read` against framework-aware patterns per category in scope.
3. **Interpret findings** with specific fixes tied to the detected framework.
4. **Report** findings sorted by severity with WCAG / EN 301 549 citations.
## Steps
### Step 1: Detect Framework
Run detection before scanning. Same logic as `/seo-validate` plus mobile entries:
| Deps / files contain | Framework | Notes |
|---|---|---|
| `next` | `next` | App Router uses `metadata` export |
| `nuxt` | `nuxt` | `useHead()` / `definePageMeta` |
| `astro` | `astro` | islands model; `client:only` affects a11y |
| `gatsby` | `gatsby` | Head API + react-helmet |
| `@sveltejs/kit` | `sveltekit` | `<svelte:head>` |
| `@remix-run/*` | `remix` | `MetaFunction` |
| `@angular/core` | `angular` | CDK `a11y` module expected |
| `vue` (no nuxt) | `vue` | a11y plugins optional |
| `react` + `vite` (no next/remix) | `react-spa` | — |
| `react-scripts` | `cra` | — |
| `react-native` | `react-native` | mobile — AccessibilityInfo API |
| `pubspec.yaml` with Flutter SDK | `flutter` | mobile — `Semantics()` widget |
| no framework deps | `static` | raw HTML |
Also detect a11y libraries: `@react-aria/*`, `@reach/*`, `@angular/cdk/a11y`, `vue-a11y`, `svelte-a11y`, `react-axe`, `axe-core`. Their presence is INFO.
### Step 2: Run Category Scans
For each category in `--scope`, apply the pattern set below using `Grep` + `Read`. Patterns adapt to the detected framework.
### Step 3: Interpret and Enrich
For each finding:
1. **Read the flagged file/lines** to confirm the match.
2. **Add a framework-specific fix** (e.g., "use `@react-aria/button`" vs "add `aria-label`").
3. **Mark confidence** — `definitive` for regex matches, `heuristic` for co-occurrence / absence / target-size estimation.
4. **Skip false positives** when context shows the concern is addressed (e.g., aria-label set via intl translation key).
### Step 4: Report
Present findings sorted by severity (HIGH → WARN → INFO), then file path.
---
## Scanner Reference
### Category 1: Semantic Structure & Landmarks
WCAG 1.3.1 (Info and Relationships), 2.4.1 (Bypass Blocks), 2.4.6 (Headings and Labels), 3.1.1 (Language of Page), 3.1.2 (Language of Parts).
| Pattern | Severity | Confidence | Description |
|---------|----------|------------|-------------|
| `<html>` missing `lang` attribute | HIGH | definitive | WCAG 3.1.1 |
| Mixed-language content without `<span lang="...">` wrapper (heuristic: non-Latin characters in otherwise-Latin content) | WARN | heuristic | WCAG 3.1.2 |
| Page/route component with >1 `<h1>` | WARN | heuristic | WCAG 1.3.1 |
| Heading level skip (h1 → h3 without h2) | WARN | heuristic | WCAG 1.3.1 |
| No landmark roles / semantic elements (`<main>`, `<nav>`, `<header>`, `<footer>`) | WARN | heuristic | WCAG 1.3.1, 2.4.1 |
| `role="presentation"` / `role="none"` on semantic element | WARN | definitive | Strips meaning; misuse of ARIA |
| Multiple `<main>` per page | HIGH | definitive | WCAG 1.3.1 — only one `<main>` allowed |
### Category 2: Text Alternatives & Non-Text Content
WCAG 1.1.1 (Non-text Content).
| Pattern | Severity | Confidence | Description |
|---------|----------|------------|-------------|
| `<img>` without `alt` attribute | HIGH | definitive | WCAG 1.1.1 — required even if empty |
| `<img alt="">` on informational image (heuristic: image inside `<article>`, `<figure>`, or with adjacent caption) | WARN | heuristic | Empty alt only for decorative |
| `<img alt="image">` / `<img alt="photo">` / `<img alt="picture">` (redundant/meaningless) | WARN | definitive | Alt should describe content |
| `<svg>` without `<title>` + `role="img"` + `aria-label`, used in interactive context | WARN | heuristic | Inline SVG needs alternative |
| Icon font (`<i class="fa-...">`, `<span class="material-icons">`) without `aria-label` or text alternative | WARN | definitive | WCAG 1.1.1 |
| `<img>` used for text content (heuristic: `alt` contains a full sentence like "Click here to...") | WARN | heuristic | WCAG 1.4.5 Images of Text |
| Complex image (`<img>` with `src` matching `chart|graph|diagram|infographic`) without long description (`aria-describedby` or `longdesc` or linked description) | WARN | heuristic | WCAG 1.1.1 for complex content |
### Category 3: Keyboard & Focus
WCAG 2.1.1 (Keyboard), 2.1.2 (No Keyboard Trap), 2.4.3 (Focus Order), 2.4.7 (Focus Visible).
| Pattern | Severity | Confidence | Description |
|---------|----------|------------|-------------|
| `tabindex` value >0 (positive) | HIGH | definitive | WCAG 2.4.3 — breaks natural tab order |
| `tabindex="-1"` on natively interactive element (`<button>`, `<a href>`, `<input>`, etc.) | WARN | definitive | Removes from tab order |
| `outline: none` or `outline: 0` on focusable selector without `:focus-visible` replacement | HIGH | definitive | WCAG 2.4.7 |
| `onClick` / `onKeyDown` handler on `<div>` / `<span>` without `role="button"` + `tabindex="0"` + keydown handler for Enter/Space | HIGH | heuristic | WCAG 2.1.1 — not keyboard-accessible |
| No skip link (`<a href="#main">`, `<a href="#content">`) on page with navigation | WARN | heuristic | WCAG 2.4.1 Bypass Blocks |
| Potential keyboard trap: `event.preventDefault()` / `event.stopPropagation()` in keydown handler on modal/dialog without Escape handling | WARN | heuristic | WCAG 2.1.2 |
| Custom dropdown / combobox without `aria-expanded` + `aria-haspopup` + keyboard handlers | WARN | heuristic | WAI-ARIA Authoring Practices |
| `autofocus` on page load on non-critical input (distracts keyboard users, moves focus unexpectedly) | WARN | definitive | Confuses assistive tech |
| `contenteditable="true"` without `aria-label` / `aria-labelledby` | WARN | definitive | WCAG 4.1.2 |
### Category 4: Color, Contrast & Visual Cues
WCAG 1.4.1 (Use of Color), 1.4.3 (Contrast Minimum), 1.4.11 (Non-text Contrast).
**Static analysis limitation**: actual contrast ratios depend on the CSS cascade, custom properties, theme switching, and background images. The skill flags patterns where contrast is AT RISK; pair with runtime tools (axe-core, Lighthouse) for definitive measurement.
| Pattern | Severity | Confidence | Description |
|---------|----------|------------|-------------|
| Hardcoded foreground+background color pairs in CSS where computed contrast is <4.5:1 (normal) or <3:1 (large text) | WARN | heuristic | WCAG 1.4.3 — verify at runtime |
| Link inside body text without underline/border AND only `color` distinguishing it | WARN | heuristic | WCAG 1.4.1 — color-only signalling |
| Error/required field indicated only by red color (no icon, text, or shape) | WARN | heuristic | WCAG 1.4.1 |
| Required form field marked only with `*` character without `aria-required="true"` + text explanation | WARN | definitive | WCAG 1.4.1 + 3.3.2 |
| CSS uses `color: red`/`color: green` as sole signal (success vs error) | WARN | heuristic | WCAG 1.4.1 |
| Focus indicator with <3:1 contrast against background (heuristic from color values) | WARN | heuristic | WCAG 1.4.11 |
| Button/input border color with <3:1 contrast against adjacent color | WARN | heuristic | WCAG 1.4.11 |
| CSS `text-shadow`/`opacity` on body text reducing effective contrast | INFO | heuristic | May affect 1.4.3 |
### Category 5: Forms, Labels & Errors
WCAG 1.3.5 (Identify Input Purpose), 3.3.1 (Error Identification), 3.3.2 (Labels or Instructions), 3.3.3 (Error Suggestion), 4.1.2 (Name, Role, Value).
| Pattern | Severity | Confidence | Description |
|---------|----------|------------|-------------|
| `<input>` / `<select>` / `<textarea>` without `<label for="...">` AND without `aria-label` / `aria-labelledby` | HIGH | heuristic | WCAG 3.3.2, 4.1.2 |
| `<label>` without `for` attribute (implicit association only works if input is a child) | WARN | definitive | WCAG 3.3.2 |
| `<input type="email"/tel/name/password/address">` without `autocomplete` attribute | WARN | definitive | WCAG 1.3.5 |
| Missing `autocomplete="one-time-code"` on OTP input with `inputmode="numeric"` | INFO | definitive | Improves user experience |
| Radio / checkbox group without `<fieldset>` + `<legend>` | WARN | heuristic | WCAG 1.3.1 |
| Error messages displayed visually but not linked via `aria-describedby` to the input | WARN | heuristic | WCAG 3.3.1 |
| `required` attribute without accompanying `aria-required="true"` (belt-and-suspenders for assistive tech consistency) | INFO | definitive | WCAG 4.1.2 (modern SR handle `required` but legacy may not) |
| Error uses `role="alert"` without being updated dynamically (static alert on page load) | INFO | heuristic | WCAG 4.1.3 |
| Placeholder used as label (no visible label, only `placeholder`) | WARN | heuristic | WCAG 3.3.2 — placeholder disappears on focus |
| `<input type="email">` without `inputmode="email"` (mobile UX) | INFO | definitive | EN 301 549 mobile |
### Category 6: Media (Audio, Video, Embeds)
WCAG 1.2.1–1.2.5 (Captions, audio description, sign language), 1.4.2 (Audio Control).
**EAA is specifically strict about media** — video without captions is a common legal-risk finding.
| Pattern | Severity | Confidence | Description |
|---------|----------|------------|-------------|
| `<video>` without `<track kind="captions">` child (or `<track kind="subtitles">` for foreign-language) | HIGH | definitive | WCAG 1.2.2 — EAA legal risk |
| `<video>` without transcript link or `<track kind="descriptions">` | WARN | heuristic | WCAG 1.2.3 / 1.2.5 |
| `<audio>` without transcript link or `<track kind="captions">` | HIGH | definitive | WCAG 1.2.1 |
| `<video autoplay>` without `muted` | HIGH | definitive | WCAG 1.4.2 — auto-playing audio |
| `<video autoplay loop>` running >5 seconds without pause control | WARN | heuristic | WCAG 1.4.2, 2.2.2 |
| YouTube/Vimeo embed URL without `cc_load_policy=1` or equivalent CC parameter | INFO | definitive | Platform-dependent captioning |
| YouTube embed via `<iframe src="https://www.youtube.com/embed/...">` without accessibility enhancements | INFO | definitive | Note: platform controls most a11y |
| Live media without real-time caption indication | WARN | heuristic | WCAG 1.2.4 |
| Background video (hero section) without pause button in DOM | WARN | heuristic | WCAG 2.2.2 |
### Category 7: ARIA, Live Regions & Dynamic Content
WCAG 4.1.2 (Name, Role, Value), 4.1.3 (Status Messages).
| Pattern | Severity | Confidence | Description |
|---------|----------|------------|-------------|
| `aria-hidden="true"` on focusable element | HIGH | definitive | Creates orphaned focus — serious a11y bug |
| `role="button"` on native `<button>` (redundant ARIA) | WARN | definitive | ARIA Authoring: avoid redundant roles |
| `role="link"` on `<a href>` / `role="heading"` on `<h1–h6>` (redundant ARIA) | WARN | definitive | Same |
| Conflicting roles (`<button role="link">`, `<a role="button">`) | WARN | definitive | WAI-ARIA — wrong role |
| Custom toggle (disclosure, menu, accordion) without `aria-expanded` + `aria-controls` | WARN | heuristic | WAI-ARIA |
| `aria-labelledby` referencing non-existent ID | HIGH | heuristic | Broken reference |
| `aria-describedby` referencing non-existent ID | HIGH | heuristic | Broken reference |
| `aria-live` region without `role="status"` / `role="alert"` AND async updates in component (heuristic) | WARN | heuristic | WCAG 4.1.3 |
| Toast/notification component without `role="status"` or `role="alert"` | WARN | heuristic | WCAG 4.1.3 |
| Modal / dialog without `role="dialog"` + `aria-modal="true"` + focus trap | WARN | heuristic | WAI-ARIA Authoring Practices |
| Tabs without proper roles (`role="tablist"` + `role="tab"` + `role="tabpanel"`) | WARN | heuristic | WAI-ARIA Authoring Practices |
### Category 8: Motion, Target Size, Mobile & EAA Docs
#### 8a. Motion & Animation
WCAG 2.2.2 (Pause, Stop, Hide), 2.3.3 (Animation from Interactions — AAA but EAA-recommended).
| Pattern | Severity | Confidence | Description |
|---------|----------|------------|-------------|
| CSS animation / transition / transform without matching `@media (prefers-reduced-motion: reduce)` override | WARN | heuristic | WCAG 2.3.3 |
| JS animation library (GSAP, framer-motion, anime.js) without `matchMedia('(prefers-reduced-motion: reduce)')` check | WARN | heuristic | WCAG 2.3.3 |
| Parallax scrolling without opt-out | WARN | heuristic | WCAG 2.3.3 |
| Infinite animation (CSS `animation: name infinite`) on content element without pause control | WARN | heuristic | WCAG 2.2.2 |
| `<marquee>` / `<blink>` (deprecated) | HIGH | definitive | WCAG 2.2.2 |
#### 8b. Target Size (WCAG 2.2 Minimum AA 2.5.8 + EN 301 549)
| Pattern | Severity | Confidence | Description |
|---------|----------|------------|-------------|
| Interactive target with declared size <24×24 px (heuristic from CSS: `width`/`height`/`padding` on buttons/links/inputs) | WARN | heuristic | WCAG 2.2 2.5.8 / EN 301 549 |
| Touch-target spacing <8 px between adjacent interactive elements | INFO | heuristic | Best practice |
#### 8c. Viewport & Zoom
| Pattern | Severity | Confidence | Description |
|---------|----------|------------|-------------|
| `<meta name="viewport">` containing `user-scalable=no` / `user-scalable=0` | HIGH | definitive | WCAG 1.4.4 — blocks zoom |
| `<meta name="viewport">` with `maximum-scale=1` / `maximum-scale=1.0` | HIGH | definitive | WCAG 1.4.4 |
| Content rendered via `<img>` for text (text-as-image) | WARN | heuristic | WCAG 1.4.5 |
#### 8d. Mobile (React Native + Flutter)
EN 301 549 mobile chapter. Critical for EAA scope since consumer apps are in-scope.
| Pattern | Severity | Confidence | Description |
|---------|----------|------------|-------------|
| **React Native**: `<TouchableOpacity>` / `<TouchableHighlight>` / `<Pressable>` without `accessibilityLabel` | HIGH | definitive | EN 301 549 mobile |
| **React Native**: `<Image>` without `accessibilityLabel` or `accessible={false}` | WARN | heuristic | EN 301 549 |
| **React Native**: Missing `accessibilityRole` on custom components that behave as buttons/links | WARN | heuristic | EN 301 549 |
| **React Native**: `Alert.alert` for error flow without `AccessibilityInfo.announceForAccessibility` fallback | INFO | heuristic | — |
| **Flutter**: Interactive widget (`GestureDetector`, `InkWell`, `TextButton`, `IconButton`) without `Semantics()` wrapper or `semanticLabel` parameter | HIGH | definitive | EN 301 549 mobile |
| **Flutter**: `Image()` / `Image.asset()` / `Image.network()` without `semanticLabel` (or `excludeFromSemantics: true` for decorative) | WARN | definitive | EN 301 549 |
| **Flutter**: Missing `ExcludeSemantics` / `MergeSemantics` where child semantics conflict | INFO | heuristic | Semantics tree cleanup |
#### 8e. EAA Accessibility Documentation
**Activated by `--standard eaa`.** EAA Article 14 + member-state transpositions require consumer-facing services to publish an accessibility statement. Missing statement = HIGH legal finding.
| Pattern | Severity | Confidence | Description |
|---------|----------|------------|-------------|
| No route at any of: `/accessibility`, `/accessibility-statement`, `/a11y`, `/dostepnosc` (PL), `/barrierefreiheit` (DE), `/declaration-accessibilite` (FR), `/declaración-accesibilidad` (ES), `/dichiarazione-accessibilita` (IT), `/toegankelijkheidsverklaring` (NL) | HIGH | heuristic | EAA Article 14 |
| Footer / sitemap lacks link to accessibility statement | HIGH | heuristic | EAA visibility requirement |
| Accessibility statement present but missing required elements: (a) conformance level (WCAG/EN 301 549), (b) list of non-conformant content, (c) feedback mechanism, (d) enforcement procedure link | WARN | heuristic | Member-state template requirement |
| No contact mechanism (email / form) for accessibility feedback referenced in statement | WARN | heuristic | EAA Article 14 |
| `robots.txt` disallows `/accessibility*` path (accidentally blocks statement from crawlers + assistive tech) | WARN | definitive | Discoverability |
See: [reference/eaa-compliance.md](reference/eaa-compliance.md) for directive text, member-state deadlines, statement templates.
---
## Output Format
```markdown
## Accessibility Validation Report
### Summary
| Metric | Value |
|--------|-------|
| Standard | wcag-2.1-aa / wcag-2.2-aa / en-301-549 / eaa |
| Scope | full / keyboard / contrast / forms / media / aria / motion / mobile / docs |
| Framework detected | next / nuxt / astro / ... / react-native / flutter / static |
| Files scanned | N |
| Public routes scanned | N |
| Accessibility statement | found / not-found |
| Findings: HIGH | N |
| Findings: WARN | N |
| Findings: INFO | N |
### Findings
#### [HIGH] src/components/VideoPlayer.tsx:42
Category: Media
Confidence: definitive
Pattern: `<video>` without `<track kind="captions">`
WCAG: 1.2.2 (Captions — Prerecorded, Level AA)
EAA: Article 4 (product/service accessibility requirements)
Fix: Add `<track kind="captions" src="/captions/en.vtt" srclang="en" label="English" default>`. If captions are unavailable, provide a transcript link.
See: reference/wcag-2-1-aa.md#guideline-12-time-based-media
#### [HIGH] public/index.html:8
Category: Viewport & Zoom
Confidence: definitive
Pattern: `<meta name="viewport" content="..., user-scalable=no">`
WCAG: 1.4.4 (Resize Text, Level AA)
Fix: Remove `user-scalable=no` and `maximum-scale=1` from the viewport meta — users must be able to zoom to 200%.
See: reference/wcag-2-1-aa.md#144-resize-text
#### [HIGH] src/routes.tsx:15
Category: EAA Accessibility Documentation
Confidence: heuristic
Pattern: No `/accessibility` / `/accessibility-statement` route detected; footer contains no a11y link
Standard: EAA Article 14 (mandatory accessibility statement)
Fix: Publish an accessibility statement conforming to your member-state template. Link it from the footer of every public page. See reference/eaa-compliance.md for template structure.
```
**Confidence values**:
- `definitive` — regex match against a known-bad pattern.
- `heuristic` — co-occurrence, absence, ordering, or derived inference (target size from CSS, contrast from hardcoded colors, ATF detection).
**Exit codes** (when `--output json`):
- `0` — no HIGH findings.
- `1` — one or more HIGH findings.
## Out of Scope (Static Analysis Cannot Detect)
The skill explicitly does NOT verify the following — pair with runtime tools:
- **Actual contrast ratios** under runtime CSS cascade, theme switching, custom properties (use `axe-core`, Lighthouse, or manual tooling).
- **Zoom / reflow behavior** at 200% / 400% (WCAG 1.4.10, 1.4.4) — requires rendering.
- **Screen reader announcement order and quality** (NVDA, JAWS, VoiceOver, TalkBack).
- **Cognitive accessibility** (WCAG 3.x is mostly process/content-driven, not pattern-matchable).
- **Actual keyboard trap behavior** — requires interaction.
- **Pronunciation / lang switches** at runtime.
- **Real-time caption accuracy**.
- **Usability / comprehension** — requires user studies.
For these, use: `axe-core`, `pa11y`, Lighthouse accessibility audit, manual assistive-tech testing, and user research with disabled participants.
## Rules
- **Read-only**: Never modify any files.
- **Framework-aware**: Detect framework first; apply correct pattern set.
- **Standards citation**: Every HIGH/WARN finding cites a WCAG success criterion (e.g., "1.3.1") or EN 301 549 clause.
- **Skip non-source files**: Binary files, lock files, vendored directories (`node_modules/`, `vendor/`, `dist/`, `build/`, `.next/`, `.nuxt/`, `.svelte-kit/`, `ios/Pods/`, `android/build/`, `.dart_tool/`).
- **No false confidence**: Label heuristic findings clearly. Color contrast and target size are ALWAYS heuristic in static analysis.
- **EAA docs category is LEGAL risk**: Missing accessibility statement when `--standard eaa` is selected is HIGH — this is a regulatory finding, not a code-quality suggestion.
- **No auto-fix**: A11y fixes often require design/content decisions that exceed pattern matching.
- **Don't flag missing ARIA when native semantics suffice**: Prefer native HTML elements; flag redundant ARIA, not absence when the native element is already there.
## Reference Documents
- [reference/wcag-2-1-aa.md](reference/wcag-2-1-aa.md) — All 50 Level A + AA success criteria with detection status (statically detectable vs runtime-only).
- [reference/wcag-2-2-aa.md](reference/wcag-2-2-aa.md) — 9 new WCAG 2.2 success criteria (2.4.11, 2.4.12, 2.4.13, 2.5.7, 2.5.8, 3.2.6, 3.3.7, 3.3.8, 3.3.9) with failure patterns, grep patterns, and framework notes.
- [reference/eaa-compliance.md](reference/eaa-compliance.md) — EU Directive 2019/882 articles, EN 301 549 v3.2.1 mapping, 28 June 2025 timeline, member-state transposition deltas, accessibility-statement templates.
- [reference/aria-patterns.md](reference/aria-patterns.md) — ARIA 1.2 Authoring Practices: landmarks, roles, states/properties, common anti-patterns, framework-specific helpers (`@react-aria`, `@angular/cdk/a11y`).
- [reference/mobile-eaa.md](reference/mobile-eaa.md) — EN 301 549 mobile chapter + React Native `AccessibilityInfo` / Flutter `Semantics()` patterns.
## Related Skills
- `/seo-validate` — SEO scanner; Category 9 covers a11y-for-SEO overlap only. For deep a11y compliance use `/a11y-validate`.
- `/cve-scan` — dependency vulnerability scanner.
- `/hipaa-validate` — HIPAA compliance scanner (similar pattern).
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!