Claude
Skills
Sign in
Back

a11y-ally

Included with Lifetime
$97 forever

Use when running comprehensive WCAG accessibility audits with axe-core + pa11y + Lighthouse, generating context-aware remediation, or testing video accessibility. Supports 3-tier browser cascade with graceful degradation.

specialized-testingaccessibilitywcaga11yvideocaptionsaudiodescvtteu-compliancescripts

What this skill does


# /a11y-ally - Comprehensive Accessibility Audit

<default_to_action>
When this skill is invoked with a URL, Claude executes ALL steps automatically without waiting for user prompts between steps.

## THIS IS AN LLM-POWERED SKILL

The value of this skill is **Claude's intelligence**, not just running automated tools:

| Automated Tools Do | Claude (This Skill) Does |
|--------------------|--------------------------|
| Flag "button has no name" | Analyze context: icon class, parent element, nearby text → generate "Add to wishlist" |
| Flag "image missing alt" | Use Vision to see the image → describe actual content |
| Flag "video has no captions" | Download video, extract frames, analyze each frame with Vision → generate real captions |
| Output generic templates | Generate context-specific, copy-paste ready fixes |

**IF YOU SKIP THE LLM ANALYSIS, THIS SKILL HAS NO VALUE.**

---

## EXECUTION MODEL

**CLAUDE EXECUTES ALL STEPS WITHOUT STOPPING.**

Do NOT wait for user prompts between steps. Execute the full pipeline:

1. **Data Collection**: Run multi-tool scan (axe-core, pa11y, Lighthouse) via Bash
2. **LLM Analysis**: Read results and analyze context for each violation
3. **Vision Pipeline**: If videos detected → download → extract frames → Read each frame → describe
4. **Intelligent Remediation**: Generate context-specific fixes using your reasoning
5. **Generate Reports**: Write all output files to `docs/accessibility-scans/{page-slug}/`

**WRONG:**
```
Claude: "I found 5 violations. Should I analyze them?"
User: "Yes"
Claude: "I see a video. Should I run the video pipeline?"
User: "Yes"
```

**RIGHT:**
```
Claude: [Runs scan] → [Analyzes violations] → [Downloads video] → [Extracts frames] →
        [Reads each frame with Vision] → [Generates captions] → [Writes all files]
        "Audit complete. Generated 4 files in docs/accessibility-scans/example/"
```

---

## STEP 1: BROWSER AUTOMATION - Content Fetching

Uses the **qe-browser** fleet skill as the browser engine. qe-browser wraps Vibium (WebDriver BiDi, 10MB Go binary) and provides the QE primitives we rely on. See `.claude/skills/qe-browser/SKILL.md`.

### 1.1: PRIMARY — qe-browser via Vibium CLI
```bash
# Navigate
vibium go "$TARGET_URL"
vibium wait load

# Capture accessibility tree without visual render
vibium a11y-tree --json > /tmp/a11y-work/tree.json

# Screenshot for Vision pipeline
vibium screenshot -o /tmp/a11y-work/page.png --full-page
```

If Vibium MCP tools are registered (`mcp__vibium__*`), prefer them; otherwise shell out to the `vibium` binary installed by `aqe init`.

### 1.2: Run axe-core + WCAG assertions via qe-browser
```bash
# Inject axe-core via vibium eval and collect violations
vibium eval --stdin <<'EOF'
const s = document.createElement('script');
s.src = 'https://cdnjs.cloudflare.com/ajax/libs/axe-core/4.10.2/axe.min.js';
document.head.appendChild(s);
await new Promise(r => s.onload = r);
const results = await axe.run();
JSON.stringify({ violations: results.violations.length, issues: results.violations });
EOF

# Enforce: no critical a11y violations + no failed network requests
node .claude/skills/qe-browser/scripts/assert.js --checks '[
  {"kind": "no_console_errors"},
  {"kind": "no_failed_requests"},
  {"kind": "selector_visible", "selector": "main, [role=main]"}
]'
```

### 1.3: FALLBACK — pa11y + Lighthouse (when axe alone is insufficient)
```bash
# Only use when you need the extra rulesets, not as the primary path
pa11y "$TARGET_URL" --reporter json > /tmp/a11y-work/pa11y.json
lighthouse "$TARGET_URL" --only-categories=accessibility --output=json --output-path=/tmp/a11y-work/lighthouse.json --chrome-flags="--headless"
```

**Why we dropped playwright-extra + puppeteer-extra-plugin-stealth from the primary path:**
- 300MB+ of Node deps vs Vibium's 10MB binary
- Redundant: Vibium uses WebDriver BiDi which is less fingerprintable than raw CDP
- Simpler: one tool instead of a cascade

### 1d: PARALLEL MULTI-PAGE AUDIT (Optional)

For auditing multiple URLs simultaneously, use parallel execution:

```javascript
// /tmp/a11y-work/parallel-audit.js
const { chromium } = require('playwright-extra');
const stealth = require('puppeteer-extra-plugin-stealth')();
const { AxeBuilder } = require('@axe-core/playwright');

chromium.use(stealth);

const MAX_CONCURRENT = 6;  // Maximum parallel auditors

async function auditUrl(browser, url) {
  const context = await browser.newContext();
  const page = await context.newPage();

  try {
    await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 });
    await page.waitForTimeout(2000);

    const axeResults = await new AxeBuilder({ page })
      .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'wcag22aa'])
      .analyze();

    return { url, success: true, violations: axeResults.violations };
  } catch (error) {
    return { url, success: false, error: error.message };
  } finally {
    await context.close();
  }
}

async function parallelAudit(urls) {
  const browser = await chromium.launch({ headless: true });
  const results = [];

  // Process in chunks of MAX_CONCURRENT
  for (let i = 0; i < urls.length; i += MAX_CONCURRENT) {
    const chunk = urls.slice(i, i + MAX_CONCURRENT);
    console.log(`Auditing batch ${Math.floor(i/MAX_CONCURRENT) + 1}: ${chunk.length} URLs`);

    const chunkResults = await Promise.all(
      chunk.map(url => auditUrl(browser, url))
    );
    results.push(...chunkResults);
  }

  await browser.close();
  return results;
}

// Usage: node parallel-audit.js url1 url2 url3 ...
const urls = process.argv.slice(2);
if (urls.length > 0) {
  parallelAudit(urls).then(results => {
    console.log(JSON.stringify(results, null, 2));
  });
}
```

**Usage for multi-page audit:**
```bash
node parallel-audit.js https://example.com https://example.com/about https://example.com/contact
```

### 1e: SITE CRAWL MODE (Optional)

For comprehensive site audits, crawl and audit all pages:

```javascript
// /tmp/a11y-work/crawl-audit.js
async function crawlAndAudit(startUrl, maxPages = 50) {
  const browser = await chromium.launch({ headless: true });
  const visited = new Set();
  const toVisit = [startUrl];
  const results = [];
  const baseUrl = new URL(startUrl).origin;

  while (toVisit.length > 0 && results.length < maxPages) {
    const url = toVisit.shift();
    if (visited.has(url)) continue;
    visited.add(url);

    console.log(`[${results.length + 1}/${maxPages}] Auditing: ${url}`);

    const context = await browser.newContext();
    const page = await context.newPage();

    try {
      await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000 });

      // Extract same-domain links for crawling
      const links = await page.evaluate((base) => {
        return [...document.querySelectorAll('a[href]')]
          .map(a => a.href)
          .filter(href => href.startsWith(base) && !href.includes('#'))
          .filter(href => !href.match(/\.(pdf|jpg|png|gif|css|js)$/i));
      }, baseUrl);

      // Add new links to queue
      links.forEach(link => {
        if (!visited.has(link) && !toVisit.includes(link)) {
          toVisit.push(link);
        }
      });

      // Run accessibility audit
      const axeResults = await new AxeBuilder({ page })
        .withTags(['wcag2a', 'wcag2aa', 'wcag22aa'])
        .analyze();

      results.push({ url, violations: axeResults.violations });
    } catch (e) {
      results.push({ url, error: e.message });
    }

    await context.close();
  }

  await browser.close();
  return { pagesAudited: results.length, results };
}

// Usage: node crawl-audit.js https://example.com 50
const [startUrl, maxPages] = process.argv.slice(2);
crawlAndAudit(startUrl, parseInt(maxPages) || 50).then(r => console.log(JSON.stringify(r, null, 2)));
```

---

## STEP 2: COMPREHENSIVE WCAG SCAN (Multi-Tool, Parallel, Resilient)

**IMPORTANT:** This step uses THREE accessibility testing tools for maximum coverage:
- **axe-core**: Industry standard, exce

Related in specialized-testing