audit-a11y — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited audit-a11y (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Audit the frontend for WCAG 2.1 compliance. Default level: AA. Checks HTML semantics, images, keyboard, contrast, forms, ARIA, focus, and motion.
$ARGUMENTS — optional flags:--fix — auto-fix issues where possible (add alt text placeholders, fix ARIA, add labels)--scope=<path> — limit to specific directory or component--report — save report to _local/reports/a11y-audit-<YYYY-MM-DD>.md--level=A|AA|AAA — WCAG conformance level (default: AA)| Check | How |
|---|---|
| Framework | package.json: react, next, vue, nuxt, @angular/core, svelte |
| Rendering | SSR (Next.js, Nuxt) vs SPA (Create React App, Vite + React) vs Static |
| Component files | Glob for **/*.{tsx,jsx,vue,svelte,html} |
| CSS approach | Tailwind, CSS modules, styled-components, globals |
If no frontend files found: Print "No frontend components found. This audit is for web frontends only." and STOP.
If no --scope: scan all component/page files. Exclude node_modules/, test files, storybook files.
Each check maps to a WCAG success criterion. Results: PASS, FAIL, WARN, N/A.
1a: Heading hierarchy
<h1, <h2, <h3, <h4, <h5, <h6 across all page components<h1>? Do headings follow sequential order (no skipping from h1 to h3)?1b: Landmark regions
<main, <nav, <header, <footer, <aside, <section, role="main", role="navigation", role="banner", role="contentinfo"<main> and <nav>?1c: Lists for list content
<div> or <span> siblings with similar structure (navigation items, feature lists, pricing tiers)<ul>, <ol>, <dl>1d: No div/span for interactive elements
<div.*onClick, <span.*onClick, <div.*role="button" (should be <button>)<div.*href, <span.*href patterns (should be <a>)<div onClick> with <button onClick>, <span href> with <a href>2a: Alt text on images
<img and check for alt= attributenext/image imports and check their alt propalt="descriptive text" = PASS (informative image)alt="" = PASS (decorative image, intentionally empty)alt attribute at all = FAIL2b: Decorative images properly hidden
alt="": check they also have aria-hidden="true" or are CSS background imagesalt="" without aria-hidden (technically valid but best practice)2c: SVG accessibility
<svg — check for role="img" + aria-label or <title> element insidearia-hidden="true"2d: No text in images
banner, hero, cta, promo that might have baked-in text)3a: Focus visible
outline: none, outline: 0, :focus { outline: none }, *:focus { outline: 0 }:focus-visible with visible ring/outline):focus-visible styles with visible outline/ring3b: Tab order
tabIndex or tabindex with positive values (tabIndex={1}, tabindex="2")tabIndex={0} (make focusable) and tabIndex={-1} (programmatic focus) are fine3c: No keyboard traps
dialog, modal, Dialog, ModalonKeyDown or onKeyUp handlers with Escape handling3d: Skip to content link
skip-to-content, skip-nav, skipLink, skip-to-main, #main-content4a: Text contrast
text-* paired with bg-* on same or parent elementcolor: paired with background-color: or background:4b: Non-text contrast
4c: Color not sole indicator
5a: Labels linked to inputs
<input, <select, <textarea — for each, check:id and a corresponding <label htmlFor="..."> or <label for="..."><label> elementaria-label or aria-labelledby5b: Required fields indicated
required attribute or aria-required="true" on form inputs* in label without required attribute)required attr)5c: Error identification
aria-describedby or aria-errormessage?role="alert" or aria-live region?5d: Input purpose (autocomplete)
autocomplete attribute:autocomplete="name" or "given-name" / "family-name"autocomplete="email"autocomplete="tel"autocomplete="street-address", etc.6a: ARIA roles valid
role=" — check that each role value is a valid WAI-ARIA rolerole="form" (valid but often misused), role="text" (not valid)6b: ARIA states/properties valid
aria- attributes — check they're valid and properly valuedaria-hidden="false" on elements that should be visible (just remove it), aria-label on non-interactive elements6c: No redundant ARIA
<button role="button"> — redundant<a href="..." role="link"> — redundant<nav role="navigation"> — redundant<input type="checkbox" role="checkbox"> — redundant6d: ARIA labels on interactive elements
<svg> or icon component, no text):aria-label on the buttonaria-label with descriptive text7a: Focus on route change (SPA)
focus() calls after navigation, aria-live regions for route announcements, next/navigation usage7b: Focus return from modals
focus() call in close handler8a: Reduced motion support
prefers-reduced-motion in CSS files, Tailwind motion-reduce: or motion-safe: classes, matchMedia("(prefers-reduced-motion" in JSprefers-reduced-motion supportanimation:, transition:, @keyframes, animate- (Tailwind), framer-motion, react-spring, gsap8b: No auto-playing content
autoPlay, autoplay on <video> or <audio> elements9a: Lang attribute on HTML
lang attributeapp/layout.tsx for <html lang="...">index.htmllang attribute present with valid language codelang attribute9b: Language changes in content
lang attribute on those sections# Accessibility Audit — [Project Name]
**Date:** YYYY-MM-DD | **Level:** WCAG 2.1 [A/AA/AAA] | **Stack:** [detected]
## Score: X/Y checks passed — Grade [A-F]
| Category | Pass | Warn | Fail | N/A |
|----------|------|------|------|-----|
| Semantic HTML | X | X | X | X |
| Images & Media | X | X | X | X |
| Keyboard | X | X | X | X |
| Color & Contrast | X | X | X | X |
| Forms & Inputs | X | X | X | X |
| ARIA | X | X | X | X |
| Focus Management | X | X | X | X |
| Motion | X | X | X | X |
| Language | X | X | X | X |
## Critical Issues (must fix)
[FAIL items with WCAG criterion reference, file:line]
## Warnings
[WARN items]
## Recommendations
- Run axe-core browser extension for runtime contrast checking
- Test with screen reader (VoiceOver on Mac, NVDA on Windows)
- Test keyboard-only navigation through all workflowsGrade: A (90%+ pass), B (80%+), C (70%+), D (60%+), F (<60%). Based on applicable checks only (exclude N/A).
Fix in order of severity:
:focus-visible styles if focus outline removedlang attribute to root HTML element<div onClick> with <button> (preserve styles)alt="" placeholder to images missing alt (mark as TODO for descriptive text)aria-label to inputs missing labels (use placeholder text or field name as starting point)aria-label to icon-only buttons (use icon name or action as label)lang="en" (or detected language) to root HTML element<main> wrapper if missing@media (prefers-reduced-motion: reduce) disabling animationsautocomplete to standard form fieldsalt="" as placeholder and note "TODO: add descriptive alt text" in the report. Only a human who can see the image can write proper alt text.alt attribute EXISTS. Do NOT judge if the text is descriptive enough (e.g., alt="image" is technically present — flag it as WARN "generic alt text" but not FAIL).~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.