Skip to content
Beta Multi-model support (OpenAI, Gemini, and more) launching soon.

accessibility-wcag-scan

Installable Ships in accessibility-auditor — or copy the raw skill below.
Open Claude.ai

Paste into Claude Code, Claude.ai, the desktop app, or the browser extension — ⌘/Ctrl+V.

ExperimentalNo security review

Accessibility WCAG 2.2 AA Scan

Perform a comprehensive WCAG 2.2 AA accessibility audit on the specified URL, page, or component. The scan combines automated engine results with AI-judged criteria that no automated tool can evaluate reliably, then produces a structured finding report.

Usage

/accessibility-wcag-scan <URL or path> [--platform sitecore|optimizely|umbraco|headless] [--scope page|component|flow] [--target 2.0|2.1|2.2] [--level A|AA|AAA]

Examples:

  • /accessibility-wcag-scan https://localhost:3000/products — full-page scan (defaults to WCAG 2.2 AA)
  • /accessibility-wcag-scan src/components/Navigation.tsx --scope component — component-level review
  • /accessibility-wcag-scan https://localhost:3000/checkout --platform umbraco --scope flow — multi-step flow
  • /accessibility-wcag-scan https://localhost:3000/ --target 2.1 --level AA — scan against an older target
  • /accessibility-wcag-scan https://localhost:3000/ --level AAA — include AAA criteria in the report

Phase 0 — Determine Target Version and Conformance Level

Do this first. Every scan must state, up front, exactly which WCAG version and conformance level it is measuring against — and every finding must carry the criterion id + its level. (This is the gap Tyler flagged: "no way to determine A / 2.1 / AA / AAA, etc.")

  1. Resolve the target. Read --target and --level if supplied. If not supplied, default to WCAG 2.2 Level AA (the RBA baseline, matching ADA / EAA / Section 508 expectations).

    • Valid versions: 2.0, 2.1, 2.2. Valid levels: A, AA, AAA.
    • State the resolved target explicitly in the report header, e.g. "Target: WCAG 2.2 Level AA".
  2. Build the in-scope criteria set from the canonical data file. The success criteria — each with its version (2.0/2.1/2.2), level (A/AA/AAA), and status (current/new/removed) — live in data/standards/wcag.json (repo root). Read it and select the criteria that apply to the target using these rules:

    • Level is cumulative. A target of AA includes every A and AA criterion. A target of AAA includes A + AA + AAA. A target of A includes only A.
    • Version is a ceiling. A target of 2.1 includes criteria whose version is 2.0 or 2.1; a 2.2 target includes 2.0 + 2.1 + 2.2. Never test a page against a criterion newer than the chosen target version.
    • Skip status: "removed". SC 4.1.1 (Parsing) was removed in WCAG 2.2 — exclude it for a 2.2 target; include it only when the target version is explicitly 2.0 or 2.1.

    Selection logic (conceptual):

    levelRank   = { A: 1, AA: 2, AAA: 3 }
    versionRank = { "2.0": 1, "2.1": 2, "2.2": 3 }
    inScope(c)  = levelRank[c.level]   <= levelRank[targetLevel]
               && versionRank[c.version] <= versionRank[targetVersion]
               && !(c.status === "removed" && versionRank[targetVersion] >= versionRank of removal)
    

    To pull the set programmatically:

    cat data/standards/wcag.json
    
    # Example: list every criterion in scope for WCAG 2.2 AA
    node -e "
    const {items}=require('./data/standards/wcag.json');
    const L={A:1,AA:2,AAA:3}, V={'2.0':1,'2.1':2,'2.2':3};
    const tL='AA', tV='2.2';
    const scope=items.filter(c=>L[c.level]<=L[tL] && V[c.version]<=V[tV] && c.status!=='removed');
    console.log('In-scope criteria:', scope.length);
    console.table(scope.map(c=>({id:c.id,level:c.level,version:c.version,name:c.name})));
    "
    
  3. Carry the level + version onto every finding. For each finding you raise, look up its criterion in wcag.json and record both the criterion id (e.g. 1.4.3), its level (A/AA/AAA), and the version that introduced it (2.0/2.1/2.2). The level/version is never guessed — it is read from the canonical file so it stays correct as the standard evolves.

  4. Flag out-of-target observations separately. If you spot an issue against a criterion above the target (e.g. an AAA gap during an AA scan, or a 2.2 issue during a 2.1 scan), do not count it as a conformance failure. Report it under an "Beyond target (informational)" subsection, tagged with its real level + version, so the client sees it without it skewing the conformance result.

The canonical, machine-readable criteria list (id, name, version, level, short description, ref URL) is data/standards/wcag.json. reference.md holds a human-readable summary that mirrors it. Do not hand-maintain a second criteria list inside this skill.


Phase 1 — Environment Check

Before running the scan, verify what tools are available:

npx @axe-core/cli --version 2>/dev/null && echo "axe-cli available"
npx playwright --version 2>/dev/null && echo "playwright available"

If neither is available, proceed with static analysis only (Phases 3–5) and note the limitation.


Phase 2 — Automated Scan (axe-core)

Run the axe engine against the target. Choose the axe tag set to match the version+level resolved in Phase 0 — don't test against criteria outside the target. axe tags map to WCAG version+level as follows:

Target axe tags to pass
2.0 A wcag2a
2.0 AA wcag2a,wcag2aa
2.1 AA wcag2a,wcag2aa,wcag21a,wcag21aa
2.2 AA (default) wcag2a,wcag2aa,wcag21a,wcag21aa,wcag22aa
add AAA append wcag2aaa (note: axe AAA coverage is partial — most AAA criteria stay AI-judged)

Example for the default WCAG 2.2 AA target:

npx @axe-core/cli <URL> \
  --tags wcag2a,wcag2aa,wcag21a,wcag21aa,wcag22aa \
  --reporter json \
  --save axe-results.json

If Playwright is available (preferred for JS-heavy SPAs and CMS edit modes):

node -e "
const { chromium } = require('playwright');
const AxeBuilder = require('@axe-core/playwright').default;
(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  await page.goto(process.argv[2]);
  await page.waitForLoadState('networkidle');
  const results = await new AxeBuilder({ page })
    .withTags(['wcag2a','wcag2aa','wcag21a','wcag21aa','wcag22aa']) // adjust to the Phase 0 target
    .analyze();
  const fs = require('fs');
  fs.writeFileSync('axe-results.json', JSON.stringify(results, null, 2));
  await browser.close();
})();
" "<URL>"

Parse axe-results.json and extract: violations (with impact level), passes, incomplete (needs-review).


Phase 3 — AI-Judged Criteria

Automated tools reliably catch ~30–40% of WCAG issues. Evaluate the following manually by reading the page source/component code:

3.1 Alt Text Quality (SC 1.1.1)

  • Images with alt="" — is emptiness intentional (decorative) or a gap?
  • Functional images (linked, button): does alt describe the action, not just the image?
  • Complex images (charts, infographics): is there a long description or aria-describedby?
  • CMS-managed images: are alt fields required in the content model or optional?

3.2 Reading Order (SC 1.3.2)

  • Does the DOM order match the visual reading sequence?
  • Are CSS order, position:absolute, or Grid placement creating a mismatch?
  • For carousels/tabs: does focus move logically when panels change?

3.3 Focus Sequence (SC 2.4.3 + 2.4.11 WCAG 2.2)

  • Does focus move in a meaningful order through interactive elements?
  • Are any focused elements fully obscured by sticky headers, chat widgets, or cookie banners? (SC 2.4.11 — new in WCAG 2.2)
  • Are focus indicators visible? Check CSS outline: none / outline: 0 overrides.

3.4 Form Instructions and Labels (SC 1.3.1, 3.3.1, 3.3.2)

  • Every input has a programmatically associated label (<label for> or aria-labelledby).
  • Required fields are indicated both visually and programmatically.
  • Error messages are associated with their field via aria-describedby.
  • Inline validation doesn't remove the user's entered value.

3.5 Accessible Authentication (SC 3.3.8 — new in WCAG 2.2 AA)

  • Login, registration, or 2FA flows do NOT require cognitive function tests (solving puzzles, transcribing distorted text, memorising arbitrary codes) unless an alternative method is provided.
  • CAPTCHA: is there an audio or other non-cognitive alternative?
  • Magic links, SSO, biometrics, or copy-paste from password manager are all compliant paths.

3.6 Target Size (SC 2.5.8 — new in WCAG 2.2 AA)

  • Touch/click targets that are smaller than 24×24 CSS pixels must have adequate spacing so the surrounding offset area reaches 24×24 px.
  • Icon-only buttons, close buttons, and inline links in dense lists are highest risk.

3.7 Redundant Entry (SC 3.3.7 — new in WCAG 2.2 A)

  • Multi-step forms: data entered in an earlier step is auto-populated or selectable in later steps.
  • Checkout flows (address → review → confirm) should not re-ask for the same data.

3.8 Consistent Help (SC 3.2.6 — new in WCAG 2.2 A)

  • If a help mechanism (chat widget, phone number, FAQ link) appears on multiple pages, it appears in the same location relative to the page structure on every page.

Phase 4 — Platform-Specific Checks

Sitecore XM Cloud / SXA

  • Experience Editor drag-and-drop UI: are editing controls keyboard-accessible outside edit mode?
  • JSS component rendering: SSR/hydration gap — do components have valid ARIA before JS loads?
  • Sitecore Forms: every field label, error, and hint must be server-rendered, not injected by JS.
  • Navigation components: check for duplicate <nav> landmarks without distinguishing aria-label.

Optimizely CMS (Content Cloud)

  • Block editor reading order: does the rendered block sequence match the editor block order?
  • Personalisation variants: each variant must independently pass WCAG — not just the default.
  • Optimizely Forms: field groups need <fieldset> + <legend>; radio/checkbox groups are highest risk.

Umbraco

  • Grid / Block List editor: block components must declare their own landmark and heading structure.
  • Members area login: evaluate against SC 3.3.8 (Accessible Authentication) — no CAPTCHAs without alt.
  • Rich Text editor output: heading hierarchy, list markup, link text quality.

Headless / Composable (Next.js, Astro, React)

  • Client-side navigation: focus must return to a logical target (page <h1> or skip link) on route change.
  • React hydration: avoid aria-hidden on server HTML that gets removed after hydration.
  • Astro islands: ensure each island manages its own focus trap on modals/drawers.

Phase 5 — Severity Rating and Conformance Mapping

Map every finding (automated + AI-judged) using this schema. Every row must carry the criterion SC id, its Level (A/AA/AAA), and the WCAG Version (2.0/2.1/2.2) — all three read from data/standards/wcag.json, never guessed:

| ID | SC | Level | Version | Description | Severity | Conformance | Effort | Notes |

The Level and Version columns are what let the reader (and a VPAT) see at a glance whether a finding is an A vs AA vs AAA gap, and which WCAG release it traces to. They are looked up from the canonical file so they stay correct as the standard evolves.

Severity scale:

  • critical — blocks access for users with disabilities; legal exposure; must fix before release
  • serious — significantly degrades the experience; fix in current sprint
  • moderate — creates friction; fix in next sprint
  • minor — best-practice gap; fix in backlog

Conformance ratings (VPAT vocabulary):

  • Supports — fully meets the criterion
  • Partially Supports — meets with exceptions (document them)
  • Does Not Support — criterion is not met
  • Not Applicable — criterion does not apply to this product/page

Phase 6 — Report Output

Produce a Markdown report following the structure in templates.md. Include:

  1. Target statement — state the resolved WCAG version + conformance level (e.g. "Target: WCAG 2.2 Level AA") at the very top, plus the count of in-scope criteria from Phase 0.
  2. Executive summary — overall conformance level, critical/serious count, scope.
  3. Conformance table — one row per in-scope criterion, each showing SC id, name, level, version, conformance rating, finding count.
  4. Detailed findings — grouped by guideline, each with: SC id, level, version, severity, element/location, description, remediation pointer.
  5. WCAG version-specific new criteria status — for a 2.2 target, explicit pass/fail for the 2.2 additions (2.4.11, 2.5.7, 2.5.8, 3.2.6, 3.3.7, 3.3.8); for a 2.1 target, the 2.1 additions.
  6. Beyond target (informational) — any criterion above the target (higher level or newer version) you observed, tagged with its real level + version, not counted as conformance failures.
  7. Platform-specific notes — only if a platform was specified.
  8. Next steps — link to /accessibility-remediation-plan for backlog generation, /accessibility-vpat-acr for formal reporting.

Reference files

  • data/standards/wcag.json (repo root) — CANONICAL, machine-readable. Every success criterion with its id, name, version (2.0/2.1/2.2), level (A/AA/AAA), status, short description, and ref URL. This is the single source of truth the skill reads to determine target scope and to tag each finding's level + version. Edit the standard here, not inline.
  • reference.md — human-readable summary that mirrors wcag.json plus the WCAG 2.2 quick-test checklist and how-to-use prose. Pointer to the canonical file; not a second source of truth.
  • templates.md — Report template, finding record schema, conformance table skeleton.
  • examples.md — Real-world finding examples per criterion with before/after code.
Technical details
Plugin
accessibility-auditor
Author
Dakota Smith
Skill name
accessibility-wcag-scan
Maturity
experimental
Security review
No security review
Owners
  • design
  • engineering
  • security
Argument hint
<URL or component path> [--platform sitecore|optimizely|umbraco|headless] [--scope page|component|flow] [--target 2.0|2.1|2.2] [--level A|AA|AAA]
Allowed tools
  • Read
  • WebFetch(domain:localhost)
  • WebFetch(domain:*.localhost)
  • Bash(npx axe *)
  • Bash(npx playwright *)
  • Bash(npx @axe-core/cli *)
  • Bash(node *)
  • Bash(cat *)
  • Bash(ls *)
  • Write
  • Edit
Source
plugins/accessibility-auditor/skills/accessibility-wcag-scan/SKILL.md

Edit this skill on GitHub — opens GitHub's web editor. No git knowledge needed.