# Accessibility Audit

> Audit a TypeScript/React frontend against an opinionated WCAG 2.2 AA baseline (tooling, component patterns, application shell) with optional implementation plan.

- **Type:** Skill
- **Install:** `agentstack add skill-bensheridanedwards-architectplaybook-accessibility-audit`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [BenSheridanEdwards](https://agentstack.voostack.com/s/bensheridanedwards)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [BenSheridanEdwards](https://github.com/BenSheridanEdwards)
- **Source:** https://github.com/BenSheridanEdwards/ArchitectPlaybook/tree/main/accessibility-audit

## Install

```sh
agentstack add skill-bensheridanedwards-architectplaybook-accessibility-audit
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# /accessibility-audit

Audit a TypeScript and React frontend against an opinionated accessibility baseline organised in three layers — **tooling and automation**, **component patterns**, and **application shell** — then offer to generate an implementation plan for the gaps. Targets WCAG 2.2 Level AA. The audit is fully static: it reads the codebase, never starts the development server, and never runs a live accessibility scanner. Screen-reader behaviour and focus-order verification are explicitly out of scope — they can only be verified reliably by a human.

The default mental model is React (any flavour: Vite, Create React App, Next.js, Remix). Detection is framework-agnostic, with extra hints emitted when Next.js or Remix is present because route-announcement expectations differ.

## Usage

```
/accessibility-audit                              # default: concise Top 5 + full report saved + ask about plan
/accessibility-audit --worktree                          # create an isolated Git worktree, then run the audit there
/accessibility-audit --learn                      # mid-level engineer teaching mode (detailed explanations + file/line examples)
/accessibility-audit --teach                      # alias for --learn
/accessibility-audit --severity=error             # report only violations and missing-required checks
```

**💡 Pro tip**: Add `--worktree` to run this audit in an isolated Git worktree.

This skill never accepts `--apply`. Mutating the codebase is the responsibility of a separate fix step. The implementation plan is descriptive Markdown.

## The opinionated baseline

A check resolves to one of four statuses:

- **present** — the check is fully satisfied; the audit found everything it expected.
- **partial** — some required signals resolved, others did not. The check is half-implemented.
- **missing** — the tooling, configuration, or pattern is not present at all.
- **violation** — the audit found code that actively contradicts the check (for example, an interactive `` with no keyboard handler).

`missing` and `violation` are distinct on purpose. `missing` means "the safety net isn't in place"; `violation` means "the safety net is missing _and_ there is concrete code that the safety net would have caught."

### Layer 1 — Tooling and automation

| Check                              | Expectation                                                                                                                                           | Primary detection signals                                                                                                                                                                                                                      |
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| jsx-accessibility lint plugin      | `eslint-plugin-jsx-a11y` is installed and the `recommended` (or `strict`) ruleset is enabled in the active ESLint configuration.                      | `package.json` devDependency on `eslint-plugin-jsx-a11y`; `extends` entry in `eslint.config.*` or `.eslintrc*` referencing `plugin:jsx-a11y/recommended` or `plugin:jsx-a11y/strict`; no file-level or directory-level disables of the plugin. |
| Axe in development                 | `@axe-core/react` is initialised in development mode so violations are logged to the browser console during local work.                               | devDependency on `@axe-core/react`; an entry-point file (typically `src/main.tsx`, `src/index.tsx`, or `pages/_app.tsx`) imports it and calls `axe(React, ReactDOM, ...)` behind a development guard.                                          |
| Component-test integration         | `jest-axe` or `vitest-axe` is available, and at least one component test asserts `expect(...).toHaveNoViolations()`.                                  | devDependency on `jest-axe` or `vitest-axe`; at least one test file imports the matcher and uses it.                                                                                                                                           |
| End-to-end accessibility scan      | `@axe-core/playwright` (or the Cypress equivalent) is configured, and at least one end-to-end specification runs an axe scan against a rendered page. | devDependency on `@axe-core/playwright` or `cypress-axe`; a spec file imports and invokes the scanner.                                                                                                                                         |
| Storybook accessibility addon      | If Storybook is in use, `@storybook/addon-a11y` is registered.                                                                                        | Storybook configuration file (`.storybook/main.*`) lists the addon in `addons`. Skipped silently if Storybook is not detected.                                                                                                                 |
| Continuous integration enforcement | A continuous-integration workflow step runs the unit and end-to-end accessibility checks and fails the build on violations.                           | Workflow file under `.github/workflows/`, `.gitlab-ci.yml`, or equivalent contains a step invoking the relevant test command.                                                                                                                  |

### Layer 2 — Component patterns

These checks require reading components. Use the knowledge graph to find the right entry points (god nodes for component clusters), then sample broadly. The audit reports counts and representative file references, not an exhaustive list.

| Check                                 | Expectation                                                                                                                                                                                                                            | What counts as a violation                                                                                                                                                                                                                                                                                                                 |
| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Semantic HTML over generic containers | Interactive elements use the right tag (``, ``, ``, ``); lists use ``, ``, or ``.                                                                                                                | A `` or `` with an `onClick` and no `role`, no keyboard handler, and no `tabIndex`. A list-shaped UI rendered with `` children. A clickable item that should be a `` or ``.                                                                                                                                     |
| ARIA used correctly                   | ARIA attributes appear only on elements that support them, are not redundant, and are present where required.                                                                                                                          | `aria-*` on an element where it has no effect (for example, `aria-checked` on a `` without `role="checkbox"`). Redundant ARIA (`role="button"` on ``). Icon-only buttons with no `aria-label` or `aria-labelledby`. Disclosure triggers without `aria-expanded`. Modals without `aria-modal="true"` and a labelling strategy. |
| Keyboard support                      | Every interactive element is reachable by Tab and operable by keyboard. Focus is visible.                                                                                                                                              | `outline: none` (or `outline: 0`) without a replacement focus style. Custom widgets that do not implement the WAI-ARIA Authoring Practices keyboard model. Keydown handlers that block default behaviour without re-implementing it.                                                                                                       |
| Focus management                      | Modals trap focus and restore on close; route changes move focus to a sensible target; a skip-to-content link is present and is the first focusable element.                                                                           | A modal component without focus trap and without focus restoration. A custom router with no focus handling on navigation. Auto-focus on page load on a non-form-first page.                                                                                                                                                                |
| Forms                                 | Every input has an associated ``. Errors are programmatically associated with their fields. Required fields are indicated for both screen readers and sighted users. Grouped controls use `` and ``.          | An `` whose only label is a placeholder. An error message that is rendered visually but not tied to its field by `aria-describedby`. A required field marked only with an asterisk. A radio or checkbox group without ``/``.                                                                                      |
| Images and media                      | Every `` has an `alt` attribute (empty `alt=""` is acceptable for purely decorative images). SVG icons used as content have `` or `aria-label`. Videos have captions. Auto-playing media is muted and has a pause control. | `` without `alt`. `` used as a content icon with no accessible name. `` without `muted` and without a pause control.                                                                                                                                                                                             |
| Colour and contrast                   | Text colours meet WCAG AA contrast against their backgrounds. Information is never conveyed by colour alone.                                                                                                                           | When design tokens are statically defined (CSS custom properties, Tailwind theme, theme objects), text/background pairings that fall below 4.5:1 (or 3:1 for large text). UI states differentiated only by colour (for example, an error indicated only by red text).                                                                      |
| Motion and animation                  | Long animations respect `prefers-reduced-motion`. No essential information is delivered through animation alone.                                                                                                                       | Animations longer than five seconds with no pause control. Global stylesheets with no `@media (prefers-reduced-motion: reduce)` block. Auto-rotating carousels without pause.                                                                                                                                                              |
| Text and content structure            | Headings are in document order with no skipped levels. Link text is descriptive in isolation.                                                                                                                                          | A page that jumps from `` to `` with no ``. Multiple `` per page (outside an `` context that warrants it). Link text such as "click here", "read more", or a bare URL.                                                                                                                                            |

### Layer 3 — Application shell

| Check                     | Expectation                                                                                                                                                            | Primary detection signals                                                                                                                                                            |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Document language         | `` is set to a real language code.                                                                                                                    | The HTML shell (`index.html`, `app/layout.tsx`, `pages/_document.tsx`, `app/root.tsx`) sets a non-empty `lang`.                                                                      |
| Per-route document titles | Document title updates on every navigation.                                                                                                                            | Use of the framework's title primitive (`` in Next.js metadata, `` in Vite-React, `meta` exports in Remix) on every routed view.                                      |
| Skip-to-content link      | A skip link to the main landmark exists and is the first focusable element on every page.                                                                              | An `` (or equivalent) rendered in the application shell, styled to be visible on focus.                                                                              |
| Route announcement        | Client-side navigations are announced to assistive technology.                                                                                                         | A live region in the shell, or use of the framework-provided announcer (Next.js `app/` router's `RouterAnnouncer`, Remix's built-in announcement, or a custom `aria-live` region).   |
| Viewport meta             | The viewport meta tag is present and does not disable scaling.                                                                                                         | ``. The check fails if `user-scalable=no` or `maximum-scale=1` appears.                                          |
| Landmark roles            | The application shell renders the standard landmarks once per page: `banner`, `main`, `contentinfo`. `navigation` and `complementary` appear when the design has them. | The shell uses ``, ``, ``, `` (or the explicit `role` equivalents). No duplicate landmarks of the same role without an `aria-label` differentiating them. |
| Error and not-found pages | Custom error and 404 pages have a heading, manage focus, and offer a way back to the main application.                                                                 | Presence of an error route (`app/not-found.tsx`, `app/error.tsx`, or framework equivalent). Heading present. A link or button that returns to a known landing route.                 |
| Authentication pages      | Sign-in and sign-up forms support password-manager autofill, declare input purposes, and do not trap users in moda

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [BenSheridanEdwards](https://github.com/BenSheridanEdwards)
- **Source:** [BenSheridanEdwards/ArchitectPlaybook](https://github.com/BenSheridanEdwards/ArchitectPlaybook)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-bensheridanedwards-architectplaybook-accessibility-audit
- Seller: https://agentstack.voostack.com/s/bensheridanedwards
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
