# Ux Audit

> Heuristic usability and accessibility audit of existing web pages — load a rendered page, evaluate it against Nielsen's 10 usability heuristics + WCAG 2.2 (A/AA) + responsive behavior + the page's own goal, and return prioritized findings with a concrete fix for each. Use whenever the task is to review, audit, critique, or "find usability/UX problems" on one or more web pages, do an accessibility…

- **Type:** Skill
- **Install:** `agentstack add skill-kevin-burns-claude-skills-ux-audit`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [kevin-burns](https://agentstack.voostack.com/s/kevin-burns)
- **Installs:** 0
- **Category:** [Web & Browser](https://agentstack.voostack.com/c/web-and-browser)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [kevin-burns](https://github.com/kevin-burns)
- **Source:** https://github.com/kevin-burns/claude-skills/tree/main/ux-audit
- **Website:** https://techblog.kevinburns.de

## Install

```sh
agentstack add skill-kevin-burns-claude-skills-ux-audit
```

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

## About

# UX Audit

Audit an **existing, rendered** page against a fixed rubric and return findings the caller
can act on. The discipline that makes this useful: **audit what's actually on screen, cite
the heuristic or success criterion, and propose a concrete fix.** A finding with no
location and no fix is noise; a "problem" you assumed without observing the page is worse.

This is distinct from neighbours:
- **design-council** deliberates *one* high-stakes design decision (preserves dissent).
  Use it for "should we restructure this flow?", not "audit these 12 pages."
- **webapp-testing** checks that features *work*. UX audit checks whether they're *usable
  and accessible* even when they work.

## Inputs you need

- The page(s): a URL, a local file, or a running dev server. For a *series* of pages, the
  `ux-auditor` agent fans out — one auditor per page (see that agent).
- The page's **goal** — what is the user there to do? You can't judge usability without it.
  If not given, infer it from the page and state your assumption in the finding set.
- Viewports to check (at least one mobile ~375px and one desktop ~1280px). Responsive
  problems only show up if you actually resize.

## Render the page first — don't audit blind

Audit the rendered DOM and the visual result, not the raw source. Use whatever browser
driver is installed (prefer `agent-browser`, fall back to `playwright-cli`; the CLI binary
is `playwright-cli`, **not** `playwright`):

```bash
# preference order — use whichever exists
if command -v agent-browser >/dev/null 2>&1; then echo agent-browser
elif command -v playwright-cli >/dev/null 2>&1; then echo playwright-cli
else echo NONE; fi
```

For each page capture: a **screenshot** at each viewport, the **rendered HTML/DOM**, and
(where the driver allows) computed styles for contrast and a tab-order walk for keyboard
checks. The screenshot is your evidence; reference it in findings.

**Isolate the session — the #1 cause of bad audits under fan-out.** Both drivers default
to a single shared browser session via a background daemon. When several audits run at once
(the fan-out pattern), they collide on that shared session and you get *cross-contamination*
— evals returning another page's DOM. Always give each audit its **own named session** and
close it when done. This, not the tool, is what broke an early run of this skill.

**Time-box the driver.** If it still doesn't render cleanly within a few tries, switch
drivers or drop to a static audit and *say so* — don't sink 30 calls into fighting it.

### agent-browser recipe (preferred — handles local files and concurrency cleanly)
```bash
S="uxaudit-$$"                                  # unique session per audit (fan-out safe)
agent-browser --session "$S" --allow-file-access open "file:///abs/path/page.html"
agent-browser --session "$S" --allow-file-access open "https://example.com"   # remote too
```
- **Local files load directly** with `--allow-file-access` — no HTTP server needed.
- **`eval` via `--stdin`** avoids all shell-quoting corruption (the trap that wastes calls);
  return a string with `JSON.stringify(...)`:
  ```bash
  agent-browser --session "$S" eval --stdin  {
    const noAlt = Array.from(document.images).filter(i => !i.alt).length;
    const p = document.querySelector("p"); const s = getComputedStyle(p);
    const b = document.querySelector("button"); const r = b.getBoundingClientRect();
    return { noAlt, color: s.color, bg: s.backgroundColor, target: r.width + "x" + r.height };
  })())
  EOF
  ```
- **Evidence & viewports:** `snapshot -i` (a11y refs/roles), `screenshot --annotate`
  (numbered labels — ideal for icon-only buttons), `screenshot --full`. For mobile, set
  viewport via config/flags or audit at the iOS profile (`-p ios`).
- **Always** `agent-browser --session "$S" close` when done.

### playwright-cli recipe (fallback — binary is `playwright-cli`, not `playwright`)
- **Serve local files over HTTP** — `file://` URLs often don't load. Start a throwaway
  server and target `http://localhost`:
  ```bash
  ( cd "$DIR" && python3 -m http.server 8731 & )      # or `uv run python -m http.server`
  playwright-cli open                                  # start the browser
  playwright-cli goto "http://localhost:8731/page.html"  # goto, not open-with-arg
  ```
  `open ` may stay on `about:blank`; always `goto` explicitly after `open`.
- **`eval` takes a function and the value prints under `### Result`.** Use `() => ...`
  form; a bare expression containing `=>` is misparsed as a function-to-apply. Return a
  string (`JSON.stringify(...)`) so the result is unambiguous:
  ```bash
  playwright-cli eval "() => { const b=document.querySelector('button'); const r=b.getBoundingClientRect(); return JSON.stringify({w:r.width,h:r.height}); }"
  ```
- **High-yield evals:** images missing `alt`, inputs whose `.labels` is empty, computed
  `color`/`backgroundColor` for contrast, `getBoundingClientRect()` for target size.
- **Viewports & evidence:** `playwright-cli resize 375 812` then `screenshot`, repeat at
  `1280 900`. `playwright-cli snapshot` dumps the accessibility tree (names/roles).
- Always `playwright-cli close` when done.

If no driver is installed (or you abandoned a flaky one), set `"driver": "static-only"`,
audit the static HTML + any screenshot the user provides, and flag in `notes` that
dynamic/contrast/keyboard/viewport checks were not performed. An honest partial audit beats
a guess.

## The rubric

Walk all three lenses. Don't stop at accessibility — usability and responsiveness catch
different failures.

### 1. Nielsen's 10 usability heuristics
1. **Visibility of system status** — does the UI show what's happening (loading, saved,
   selected, where-am-I)?
2. **Match with the real world** — language/concepts the user knows, not system jargon.
3. **User control & freedom** — undo, cancel, back, clear exits from unwanted states.
4. **Consistency & standards** — same thing looks/acts the same; platform conventions.
5. **Error prevention** — constraints, confirmations, sensible defaults that stop mistakes.
6. **Recognition over recall** — options visible; don't make users remember across steps.
7. **Flexibility & efficiency** — accelerators for experts without blocking novices.
8. **Aesthetic & minimalist design** — no competing clutter; signal over noise.
9. **Help users recover from errors** — plain-language errors that say what and how to fix.
10. **Help & documentation** — findable, task-oriented help where needed.

### 2. WCAG 2.2 — target Level A & AA
Check the high-yield criteria first:
- **Text alternatives** — meaningful `alt` on informative images; empty `alt=""` on
  decorative ones.
- **Contrast (1.4.3 / 1.4.11)** — text ≥ 4.5:1 (≥ 3:1 for large text ≥ 18.66px bold /
  24px); UI components & graphics ≥ 3:1. Measure from computed colours, don't eyeball.
- **Keyboard (2.1.1) & focus visible (2.4.7)** — everything operable by keyboard; a
  visible focus indicator; logical tab order; no keyboard traps.
- **Labels & names (1.3.1 / 4.1.2)** — form controls have associated ``s; controls
  expose an accessible name; ARIA used correctly (or not at all).
- **Headings & structure (1.3.1 / 2.4.6)** — one logical heading outline; landmarks
  (`main`, `nav`, `header`); descriptive page ``.
- **Target size (2.5.8, new in 2.2)** — interactive targets ≥ 24×24 CSS px (or spaced).
- **Resize/reflow (1.4.10)** — usable at 320px width / 400% zoom without horizontal scroll.
- **Don't rely on colour alone (1.4.1)** — state shown by more than hue.

### 3. Responsive & device behaviour
- Layout holds at mobile (~375px) and desktop (~1280px); no overflow, overlap, or cut-off
  controls. Tap targets aren't cramped. Content reflows rather than requiring zoom/scroll.

## Severity — so the caller can triage

Match the fleet's review scale (same as `code-reviewer`):
- **blocking** — users can't complete the page's goal, or a WCAG **Level A** failure shuts
  out a group (e.g. unlabeled critical control, keyboard trap, no alt on the only CTA icon).
- **major** — serious friction or a WCAG **AA** failure (contrast below 4.5:1, focus not
  visible, confusing error with no recovery).
- **minor** — polish: inconsistency, clutter, small-but-real friction.

Reserve `blocking` for "this stops someone," and back every finding with what you observed.

## Return format (final message) — JSON only

One object per audited page. (When fanned out, the agent merges these.)

```json
{
  "page": "url-or-path",
  "goal": "what the user is here to do (stated or inferred)",
  "viewports_checked": ["375x812", "1280x900"],
  "driver": "agent-browser | playwright-cli | static-only",
  "summary": { "blocking": 0, "major": 0, "minor": 0 },
  "findings": [
    {
      "severity": "blocking | major | minor",
      "lens": "usability | accessibility | responsive",
      "ref": "Nielsen #5 | WCAG 1.4.3 | responsive@375px",
      "location": "selector or region, e.g. 'form#signup > button.submit'",
      "evidence": "what you observed (+ screenshot ref / measured value)",
      "suggested_fix": "concrete change to make",
      "confidence": "high | medium | low"
    }
  ],
  "notes": "assumptions, what couldn't be checked, empty if none"
}
```

Be precise over exhaustive. Ten located, fixable findings beat forty vague ones. If you
couldn't render the page, say what you could and couldn't assess rather than inventing
problems.

## Privacy

The audited pages and any findings about a specific product are often the client's
property — keep the *page content and results* out of any shared/committed location. This
skill and the `ux-auditor` agent are generic and publishable; the data they process is not.

## Source & license

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

- **Author:** [kevin-burns](https://github.com/kevin-burns)
- **Source:** [kevin-burns/claude-skills](https://github.com/kevin-burns/claude-skills)
- **License:** MIT
- **Homepage:** https://techblog.kevinburns.de

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-kevin-burns-claude-skills-ux-audit
- Seller: https://agentstack.voostack.com/s/kevin-burns
- 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%.
