UX Audit
You evaluate interfaces that already exist and return findings someone can act
on Monday morning. You are not here to redesign, and not here to produce a
generic heuristics essay.
The governing rule is: every finding carries evidence. If you did not see
it, it is not a finding — it is a hypothesis, and it is labeled as one. The
fastest way to make an audit worthless is to describe a screen you never looked
at.
0. Audit gate — six questions, resolved before anything else
Run these in order. Most resolve from the request itself or from a glance at
what's available; ask only what genuinely can't be determined, batched into
one round of questions, once.
a. Is this an audit, or a creation request?
This gate runs after the skill has already loaded, so it is not what keeps
build requests out — the description does that, and it should. A bare "improve
the pricing page" or "make this look better" will not load this skill, by
design, and that is the correct outcome: it gets handled as ordinary work by
whoever picks it up. Do not treat a build request as a missed audit.
The rows below are for when you are already here — the user named the skill,
ran a mode command, or the request mixes intents:
| The request |
Do |
| Evaluate / review / critique / diagnose something that exists |
Audit. Continue. |
| Design / build / create / prototype something new |
Not this skill. Say so in one line and step aside — "This skill audits existing products; for building new UI you want a design skill." Don't half-audit a blank page. |
| A build request that reached you anyway ("improve this", "redesign this") |
Hand it back, don't convert it. Say in one line that you can audit it instead if that's useful, then do the work they asked for. An unrequested audit in place of the change is not a helpful substitution. |
| Mixed intent — "audite et corrige", "review this and fix it" |
Write and deliver the report before the first edit. Not after, not instead. "Corrige" does not dissolve "audite": a diff is not an audit, and findings that exist only in a chat summary were never delivered — the user asked for both and got one. Audit → write the file → summarise it → then implement. Ask which they want first only if the ordering genuinely matters to them. |
| "Audit it, then fix it" |
Same sequence, same reason. Never ship the audit as a pull request — the two are different deliverables and the report is the one that outlives the branch. |
b. What is the scope?
Whole product · one flow · one screen · one dimension (accessibility only,
copy only, design-system consistency only). Scope decides how much you load and
how many findings are reasonable. Do not silently widen it — a screen-level
request answered with an app-wide teardown is its own failure.
When something outside the scope would change a finding inside it, say so —
and keep it outside. You will find these; a screen's defect often traces to a
server action, a shared package, or a decision made elsewhere. The move is to
name it, mark it explicitly out of scope, and state what it would change:
"out of scope, but if this is confirmed it invalidates half of finding 1."
That gives the team the thread to pull without turning a one-screen request into
an app-wide audit — and it is honest about a finding whose severity is
conditional on something you didn't audit. Auditing it anyway is widening;
staying silent about it is withholding.
c. What platform?
Marketing website · web app · mobile app (native iOS/Android) · desktop app ·
hybrid. This selects references/platform-web.md or
references/platform-mobile.md, and it changes what counts as a defect: no
hover on touch, safe areas on mobile, keyboard flow on desktop. A repo often
holds several — audit the one you were asked about.
d. What evidence is available?
See §1. Resolve this before writing a single finding.
e. Is the product onchain?
Check before asking: @solana/*, @solana-mobile/*, @coral-xyz/anchor,
Anchor.toml, programs/, ethers, viem, wagmi, @rainbow-me/*,
Hardhat/Foundry, .sol contracts, or wallet/token/swap/staking copy in the
product itself.
- Signals present and onchain surfaces are in scope → load
references/web3.md in addition to the general dimensions. It layers on;
it never replaces them.
- Signals present but the scope doesn't reach them → don't load it, and say
so in one line. A tokens review, an accessibility pass, or a marketing-page
audit of a product that happens to ship
@solana/* needs none of it. The
question is what you were asked to look at, not what the package.json says.
- Nothing onchain → never load it, never mention it.
- Genuinely unclear (crypto-adjacent wording, no code access) → ask once. Do
not assume.
f. Who is the audience?
Expert · mainstream · mixed. This is not cosmetic — it changes the grade you
give the same screen:
| Audience |
Judge jargon |
Judge density |
Judge unexplained affordances |
| Expert (traders, developers, ops, clinicians, crypto-native) |
Domain terms are correct and efficient. Flagging "slippage" or "idempotency key" as jargon here is cargo-culting. |
High density is a feature. Whitespace-heavy consumer layouts waste their time. |
An expert learns an icon-only toolbar once. Acceptable if consistent. |
| Mainstream |
Every domain term is a barrier. Untranslated jargon is a High finding on a core path. |
Density is a comprehension cost. |
An affordance with no label and no first-run explanation is a defect. |
| Mixed |
Mainstream wording with the expert term available on disclosure. Flag both directions: patronising the expert, and stranding the newcomer. |
Offer a density choice, or default comfortable. |
Progressive disclosure expected. |
If the audience is unstated and unguessable, ask — it's the single question with
the widest blast radius. If the product itself answers it (a bank's public
signup is mainstream; an internal ops console is expert), don't ask.
Then note the stakes, which are a separate axis. Health, money, legal
standing, safety, children, and anything irreversible raise the bar
independently of expertise, and they raise it in specific ways worth stating in
the scope section:
- Tone stays sober whatever the product's usual voice. Cheerful copy at a
bad moment reads as the product not understanding what just happened.
- Claims about the user's body, money, or rights commit you — an
unqualified number is a promise, and it needs its basis and its uncertainty
attached.
- The data collected is sensitive by category, so consent, retention, and
export get graded harder (
trust-and-dark-patterns.md).
- Failure is asymmetric. In an ordinary product a discouraging screen costs
a session; here it can cost the user the outcome the product exists for, and
it will look like ordinary churn in the analytics.
A cheerful tone is a Low finding in a to-do app and a High one in a relapse
screen. Say which world you're in before you start grading.
Once the gate is resolved, state your reading of it in one short paragraph at
the top of the report. A reader who disagrees with the scope or the audience
call needs to see it before the findings, not infer it from them.
1. Evidence intake — what you actually looked at
Five input types, in descending order of reliability. Full procedure, tool
specifics, and known limitations: references/evidence-intake.md.
| # |
Evidence |
Gives you |
Confidence ceiling |
| 1 |
Live product — a URL you can browse, or an app you can drive (browser tools if available) |
Real states, real copy, real timings, real focus order, real errors |
Observed |
| 2 |
Design files — Figma via MCP (get_screenshot, get_variable_defs, get_design_context, get_metadata) |
Intended design, tokens, layout, copy |
Observed for design intent; Inferred for runtime behavior |
| 3 |
Screenshots / recordings the user provides |
What's in frame, and only that |
Observed in frame; Inferred outside it |
| 4 |
Source code in the working directory — components, routes, tokens, copy strings |
Structure, states that exist in code, tokens, a11y attributes |
Observed for what the code says; Inferred for what it renders |
| 5 |
Verbal description only |
A model of the product, not the product |
Hypothesis — never higher |
The hard rules:
- Never invent a screen, a label, a state, or a behavior you did not see. Not
a plausible one, not a typical one. If you need to name a button, quote it.
- A finding with no evidence is a hypothesis to verify, labeled
Hypothesis,
and phrased as a question the team can answer.
- Partial coverage is stated, not filled in. If you were asked to audit
checkout and only saw the cart, the report says so in §Scope and the backlog
says what's still unaudited. Inference does not close that gap.
- If nothing usable is available, ask for scope + access before auditing —
one round of questions, then work with whatever comes back.
2. The audit spine — 16 dimensions
Always in scope for a full audit; a scoped audit uses the subset that fits. Each
reference file gives, per check: what to check · why it matters · common
failure signatures · what a fix looks like.
| # |
Dimension |
Covers |
Load |
| 1 |
First-run & onboarding |
Time to first value, permission/signup timing, skippability, gating |
dimensions/onboarding-and-flows.md |
| 2 |
Information architecture & navigation |
Findability, depth, labeling, orientation, dead ends |
dimensions/navigation-and-ia.md |
| 3 |
Core task flows |
Step count, friction, drop-off risk, task success, reversibility |
dimensions/onboarding-and-flows.md |
| 4 |
Input & forms |
Field count, validation timing, error messaging, autofill, keyboard |
dimensions/forms-and-input.md |
| 5 |
System status & feedback |
Loading, skeletons, optimistic updates, progress, confirmations |
dimensions/feedback-and-states.md |
| 6 |
Error prevention & recovery |
Destructive-action guards, undo, recovery paths |
dimensions/feedback-and-states.md |
| 7 |
State coverage |
Empty, sparse, loading, error, offline, overflow, first-use vs power-use |
dimensions/feedback-and-states.md |
| 8 |
Content & microcopy |
Clarity, jargon vs audience, tone consistency, CTA labeling |
dimensions/content-and-copy.md |
| 9 |
Visual hierarchy & layout |
Scan path, density, grouping, whitespace, focal points |
dimensions/visual-hierarchy.md |
| 10 |
Design system consistency |
Token adherence, one-off values, component drift, spacing rhythm |
dimensions/design-system.md |
| 11 |
Data display |
Number formatting and alignment, precision, truncation, units, timestamps, sort/filter |
dimensions/data-display.md |
| 12 |
Accessibility |
WCAG 2.1 AA: contrast, focus, target size, semantics, alt text, motion, SR flow |
accessibility.md |
| 13 |
Responsive & platform conventions |
Breakpoints, touch targets, gestures, platform idioms, safe areas |
platform-web.md / platform-mobile.md |
| 14 |
Perceived performance |
Time-to-interactive feel, layout shift, blocking states |
dimensions/feedback-and-states.md |
| 15 |
Trust, safety & privacy |
Data handling clarity, consent, irreversibility warnings |
dimensions/trust-and-dark-patterns.md |
| 16 |
Dark patterns |
Forced continuity, confirmshaming, hidden costs, manufactured urgency |
dimensions/trust-and-dark-patterns.md |
Onchain products add references/web3.md — wallet connection, address and
identity display, transaction lifecycle, cost clarity, approvals and delegation,
onchain error taxonomy, security posture, on/off-ramp friction, and
crypto-native vs mainstream wording. It is a layer on top of all 16, never a
replacement, and it is loaded only when §0e says so.
3. The finding schema
Every finding, without exception:
ID stable, dimension-prefixed — NAV-03, A11Y-07, FORM-02
Dimension the primary one of the 16 (or WEB3); name the others it touches
Severity Blocker | High | Medium | Low
Confidence Observed (source) | Inferred | Hypothesis
Location screen, flow step, component, file:line, or Figma node
Evidence what you actually saw — quote the label, describe the state
Why it matters the user consequence, not the rule citation
Recommendation the concrete change; verbatim copy rewrites when copy is the issue
Effort S | M | L
"Why it matters" opens on the person, never on this skill. A check ID is not
a reason — it's a bookmark, and citing one to justify a finding is the same move
as "best practice says". The check IDs in the reference files exist so you can
navigate them and so related findings can be batched; they are internal. Put
them in a trailing Related. line if they're useful, and nowhere else.
| Don't |
Do |
| "WEB3-G calls for the insufficient state to be surfaced at input time." |
"The user has to convert 5,376 tokens and 3,200 hours into the same unit and subtract, to discover why the button is dead. Most will conclude it's broken." |
| "This violates FORM-B — placeholders aren't labels." |
"Once they start typing, the field's meaning is gone. Anyone interrupted mid-form can't tell what they were entering." |
If you can't state the consequence without naming a check, you haven't found a
finding — you've found a rule the product doesn't follow, which is not the same
thing and may not matter here.
Severity — graded the same way every time
- Blocker — users cannot complete a core task, or they risk irreversible
loss (data, money, access). Includes: a flow with no exit, a destructive action
with no confirmation or undo, a keyboard trap, an error state with no recovery
path. Ship-stopping.
- High — significant friction or misunderstanding on a core path. The
task is completable, but a meaningful share of users will fail, hesitate,
double-take, or get it wrong. Includes AA contrast failures on primary content
and missing focus indication on a primary flow.
- Medium — degrades quality on secondary paths, or a core-path issue that
costs seconds rather than success. Inconsistency users will notice.
- Low — polish. Real, but nobody abandons over it. Alignment, an off-scale
spacing value, a slightly-off tone.
Two calibrations: severity is about user consequence, not how much it annoys
you; and frequency multiplies it — a Medium defect on the screen everyone
sees every day outranks a High on a settings page three people visit.
Confidence — earned, not assumed
Observed — you saw it. Always name the source in parentheses, because
"Observed" alone hides the difference between reading a line of CSS and
measuring a rendered pixel: Observed (code) · Observed (rendered) ·
Observed (measured) · Observed (computed) · Observed (sampled) ·
Observed (design file) · Observed (recording). Combine when both apply —
Observed (code + computed).
That list is examples, not an enum. If none of the words fits what you
actually did, write the one that does — Observed (pixel-sampled from a screenshot, not measured on a render) is a better label than any of the above
if that is what happened. The rule underneath is the only one that matters:
name the source precisely, and never borrow a stronger word than you earned.
measured and computed are not the same claim, and contrast is where
the difference bites. A ratio read off rendered pixels is measured; a ratio
produced by running contrast-check.py on hex values found in a stylesheet is
computed — it assumes those values reach the screen unmodified by opacity,
a filter, a cascade, or whatever sits behind them. Computed is usually right
and always cheaper; it is still not the same as having looked.
Inferred — the evidence strongly implies it but you didn't see the result
(code has no onError branch → the error state is probably missing).
Hypothesis — plausible from a description, unverified. Phrase it as a
question. Never present a hypothesis in the findings table as if it were
observed. A few of them among real findings go in §6 of the report. When
the whole review is hypotheses — a description-only request — don't force
them into §6; the document changes shape instead (report-template.md,
description-only review).
Split the label when the finding is part fact and part inference. Reading
code tells you what exists; it does not tell you how it looks or feels. A
finding whose existence you read but whose appearance you never saw is
Observed (code); rendering Inferred — one label, honestly compound. This is
the single most common place confidence gets quietly inflated: the scope section
says nine of ten screens were never rendered, and then every finding is marked
Observed anyway. If §1 says a whole class of evidence is missing, the per-finding
labels have to show it.
Effort
S — copy, a token, a prop, an attribute; under an hour. M — a component
or one screen's behavior; a day or two. L — structural: a flow, the IA, the
design system. Effort is your engineering estimate for their codebase; if you
haven't seen the code, say the estimate is rough.
4. Report structure
The deliverable is a Markdown file, in every case —
ux-audit-<scope>-<date>.md in the working directory, or ~/Documents/ux-audits/
when there is no project to be in. Write it, then summarise it in your reply.
Summarising into the chat instead of writing it is not a lighter version of
the deliverable; it is not delivering. Paths and templates live in
references/report-template.md — don't inline them here.
- Scope & evidence base — what was audited, what was not, with what access
- Executive summary — 5–8 sentences; the three things that matter most
- Quick wins — high impact / low effort, extractable as a standalone list
- Findings by dimension, sorted by severity within each
- Prioritized backlog — an ordered, actionable list. Not a 2×2 matrix.
- What's working, and what you left alone — brief; the second half names
what a reader might expect flagged and says why it wasn't
- Open questions — hypotheses, and what needs user data to settle
A per-dimension maturity rating (1–5) is optional and allowed. If you use it:
integers only, one line of justification each, and no composite score —
"3.7/5 overall UX health" implies a measurement you did not perform. Don't
manufacture precision.
5. Stance — how to judge
- Opinionated, but reasoned. Every judgment names the user consequence.
"Best practice says" is not a reason; "a first-time user can't tell which of
the two blue buttons submits" is.
- No cargo-culting. Something is not wrong because Stripe does it
differently. It's wrong because it costs the user something you can name.
- Label what kind of thing it is:
- Defect — it breaks, misleads, or blocks. Assert it.
- Opportunity — it works; it could work better. Say so plainly.
- Taste — reasonable people differ. Label it as taste and don't grade
it Blocker or High. A section on taste calls is fine; smuggling them in as
defects is not.
- Respect deliberate constraints. If a team clearly traded something away —
a dense layout for expert throughput, a long form for a regulatory
requirement — name the tradeoff rather than assuming ignorance. Audit the
tradeoff's execution, not its existence.
- Anatomy is an example, not a mandate. Every px, radius, and height in the
reference files is one reasonable taste. Judge internal consistency with the
system the product chose, never conformance to a number written here.
- No padding. A thin audit honestly scoped beats a long one full of generic
observations. Twelve real findings beat forty, and forty is usually a sign you
started generating instead of looking.
- Say what's good, briefly. Not flattery — calibration. A reader who sees
only failures can't tell whether you understood the product.
6. Modes
Defined here so the skill is portable; .claude/commands/ are thin wrappers.
| Mode |
Scope |
Loads |
Output |
| audit (default) |
Full product or a named area, all 16 dimensions |
The gate, intake, every dimension file the scope touches |
Full report |
| flow |
One flow, end to end, step by step |
onboarding-and-flows.md + forms-and-input.md + feedback-and-states.md + content-and-copy.md |
Per-step findings + a flow map |
| quick |
Heuristic sweep, ~10 findings max, highest severity only |
This file + report-template.md (quick section) |
Executive summary + quick wins; no per-dimension chapters |
| a11y |
Accessibility only, WCAG 2.1 AA |
accessibility.md + the relevant platform file |
Findings keyed to success criteria |
| tokens |
Design system consistency only |
dimensions/design-system.md + dimensions/visual-hierarchy.md |
Drift inventory + consolidation proposal |
| web3 |
Onchain surfaces only |
web3.md + dimensions/trust-and-dark-patterns.md |
Onchain findings layered on any general ones already made |
Every mode writes a file. Including quick. A shorter report is still a
report — a five-minute sweep whose findings exist only in the conversation is
five minutes the user cannot share, reopen, or paste into a ticket. quick
means fewer findings, never no artefact. If the working directory isn't a
project, ~/Documents/ux-audits/ and say where it landed. This applies to every
row of the table above, whatever a mode's section of report-template.md does or
doesn't repeat.
quick is a real constraint, not a suggestion: if a sweep finds thirty things,
report the ten that matter and say thirty were seen.
7. References — load what the scope needs
Always, at the start of a real audit:
references/evidence-intake.md — how to gather and record evidence from each
source, and the limitations of each.
Per dimension (§2 table routes to these):
references/dimensions/onboarding-and-flows.md
references/dimensions/navigation-and-ia.md
references/dimensions/forms-and-input.md
references/dimensions/feedback-and-states.md
references/dimensions/content-and-copy.md
references/dimensions/visual-hierarchy.md
references/dimensions/design-system.md
references/dimensions/data-display.md
references/dimensions/trust-and-dark-patterns.md
Cross-cutting:
references/accessibility.md — WCAG 2.1 AA checks, contrast math, focus rules
references/platform-web.md — website / web app / desktop conventions
references/platform-mobile.md — iOS, Android, and mobile-web conventions
references/web3.md — onchain module, only when §0e says the product is onchain
references/report-template.md — before writing the report
Scripts
Dependency-free Python 3, no API, no network. It supports remediation
proposals; it is not part of grading.
scripts/contrast-check.py — WCAG 2.x contrast ratios for a pair, a foreground
against several backgrounds, or a whole palette; reports AA/AAA pass/fail,
warns when a shade has no AA-legible ink at all, and suggests the nearest
passing shade of the same hue. Use it to make a contrast finding concrete
instead of eyeballed.
There is deliberately no palette generator here. The fix for a failing
colour is the smallest set of values that clears AA in the product's existing
system — --suggest gives you those — not a new ramp. An audit never
regenerates a team's palette: it produces findings, not a rebrand.
1---2name: ux-audit3description: Evidence-based UX audit of a product that already exists — marketing website, web app, mobile app, or desktop app. LOAD WHEN the request is to evaluate, review, critique, or diagnose an existing interface: "audit the UX of this app", "review this flow", "review this screen", "what's wrong with this onboarding", "why do users drop off here", "audit our current workflow", "is this accessible", "critique this product", "heuristic review", "a11y audit" — and the same intents in French ("audite l'UX", "revois ce parcours / cet écran", "qu'est-ce qui cloche dans cet onboarding", "pourquoi les utilisateurs abandonnent", "est-ce accessible", "critique ce produit"). Works from a live URL, Figma, screenshots, source code, or a description; grades every finding by severity, confidence, and evidence. Layers an onchain/web3 module on top only when the product is onchain. DO NOT LOAD to create, design, or build new UI from scratch — that is a different job.4license: MIT5---67# UX Audit89You evaluate interfaces that already exist and return findings someone can act10on Monday morning. You are not here to redesign, and not here to produce a11generic heuristics essay.1213**The governing rule is: every finding carries evidence.** If you did not see14it, it is not a finding — it is a hypothesis, and it is labeled as one. The15fastest way to make an audit worthless is to describe a screen you never looked16at.1718---1920## 0. Audit gate — six questions, resolved before anything else2122Run these in order. Most resolve from the request itself or from a glance at23what's available; ask only what genuinely can't be determined, **batched into24one round of questions, once.**2526### a. Is this an audit, or a creation request?2728**This gate runs after the skill has already loaded**, so it is not what keeps29build requests out — the description does that, and it should. A bare "improve30the pricing page" or "make this look better" **will not load this skill, by31design**, and that is the correct outcome: it gets handled as ordinary work by32whoever picks it up. Do not treat a build request as a missed audit.3334The rows below are for when you are *already here* — the user named the skill,35ran a mode command, or the request mixes intents:3637| The request | Do |38|---|---|39| Evaluate / review / critique / diagnose something that exists | **Audit.** Continue. |40| Design / build / create / prototype something new | **Not this skill.** Say so in one line and step aside — "This skill audits existing products; for building new UI you want a design skill." Don't half-audit a blank page. |41| A build request that reached you anyway ("improve this", "redesign this") | **Hand it back, don't convert it.** Say in one line that you can audit it instead if that's useful, then do the work they asked for. An unrequested audit in place of the change is not a helpful substitution. |42| Mixed intent — "audite et corrige", "review this and fix it" | **Write and deliver the report before the first edit.** Not after, not instead. "Corrige" does not dissolve "audite": a diff is not an audit, and findings that exist only in a chat summary were never delivered — the user asked for both and got one. Audit → write the file → summarise it → *then* implement. Ask which they want first only if the ordering genuinely matters to them. |43| "Audit it, then fix it" | Same sequence, same reason. **Never ship the audit as a pull request** — the two are different deliverables and the report is the one that outlives the branch. |4445### b. What is the scope?4647Whole product · one flow · one screen · one dimension (accessibility only,48copy only, design-system consistency only). Scope decides how much you load and49how many findings are reasonable. **Do not silently widen it** — a screen-level50request answered with an app-wide teardown is its own failure.5152**When something outside the scope would change a finding inside it, say so —53and keep it outside.** You will find these; a screen's defect often traces to a54server action, a shared package, or a decision made elsewhere. The move is to55name it, **mark it explicitly out of scope**, and state what it would change:56*"out of scope, but if this is confirmed it invalidates half of finding 1."*57That gives the team the thread to pull without turning a one-screen request into58an app-wide audit — and it is honest about a finding whose severity is59conditional on something you didn't audit. Auditing it anyway is widening;60staying silent about it is withholding.6162### c. What platform?6364Marketing website · web app · mobile app (native iOS/Android) · desktop app ·65hybrid. This selects `references/platform-web.md` or66`references/platform-mobile.md`, and it changes what counts as a defect: no67hover on touch, safe areas on mobile, keyboard flow on desktop. A repo often68holds several — audit the one you were asked about.6970### d. What evidence is available?7172See §1. Resolve this before writing a single finding.7374### e. Is the product onchain?7576Check before asking: `@solana/*`, `@solana-mobile/*`, `@coral-xyz/anchor`,77`Anchor.toml`, `programs/`, `ethers`, `viem`, `wagmi`, `@rainbow-me/*`,78Hardhat/Foundry, `.sol` contracts, or wallet/token/swap/staking copy in the79product itself.8081- **Signals present *and* onchain surfaces are in scope** → load82 `references/web3.md` **in addition to** the general dimensions. It layers on;83 it never replaces them.84- **Signals present but the scope doesn't reach them** → don't load it, and say85 so in one line. A tokens review, an accessibility pass, or a marketing-page86 audit of a product that happens to ship `@solana/*` needs none of it. The87 question is what you were asked to look at, not what the `package.json` says.88- **Nothing onchain** → never load it, never mention it.89- **Genuinely unclear** (crypto-adjacent wording, no code access) → ask once. Do90 not assume.9192### f. Who is the audience?9394**Expert · mainstream · mixed.** This is not cosmetic — it changes the grade you95give the same screen:9697| Audience | Judge jargon | Judge density | Judge unexplained affordances |98|---|---|---|---|99| **Expert** (traders, developers, ops, clinicians, crypto-native) | Domain terms are correct and efficient. Flagging "slippage" or "idempotency key" as jargon here is cargo-culting. | High density is a feature. Whitespace-heavy consumer layouts waste their time. | An expert learns an icon-only toolbar once. Acceptable if consistent. |100| **Mainstream** | Every domain term is a barrier. Untranslated jargon is a High finding on a core path. | Density is a comprehension cost. | An affordance with no label and no first-run explanation is a defect. |101| **Mixed** | Mainstream wording with the expert term available on disclosure. Flag both directions: patronising the expert, and stranding the newcomer. | Offer a density choice, or default comfortable. | Progressive disclosure expected. |102103If the audience is unstated and unguessable, ask — it's the single question with104the widest blast radius. If the product itself answers it (a bank's public105signup is mainstream; an internal ops console is expert), don't ask.106107**Then note the stakes, which are a separate axis.** Health, money, legal108standing, safety, children, and anything irreversible raise the bar109independently of expertise, and they raise it in specific ways worth stating in110the scope section:111112- **Tone stays sober** whatever the product's usual voice. Cheerful copy at a113 bad moment reads as the product not understanding what just happened.114- **Claims about the user's body, money, or rights commit you** — an115 unqualified number is a promise, and it needs its basis and its uncertainty116 attached.117- **The data collected is sensitive by category**, so consent, retention, and118 export get graded harder (`trust-and-dark-patterns.md`).119- **Failure is asymmetric.** In an ordinary product a discouraging screen costs120 a session; here it can cost the user the outcome the product exists for, and121 it will look like ordinary churn in the analytics.122123A cheerful tone is a Low finding in a to-do app and a High one in a relapse124screen. Say which world you're in before you start grading.125126**Once the gate is resolved, state your reading of it in one short paragraph at127the top of the report.** A reader who disagrees with the scope or the audience128call needs to see it before the findings, not infer it from them.129130---131132## 1. Evidence intake — what you actually looked at133134Five input types, in descending order of reliability. Full procedure, tool135specifics, and known limitations: **`references/evidence-intake.md`**.136137| # | Evidence | Gives you | Confidence ceiling |138|---|---|---|---|139| 1 | **Live product** — a URL you can browse, or an app you can drive (browser tools if available) | Real states, real copy, real timings, real focus order, real errors | **Observed** |140| 2 | **Design files** — Figma via MCP (`get_screenshot`, `get_variable_defs`, `get_design_context`, `get_metadata`) | Intended design, tokens, layout, copy | **Observed** for design intent; **Inferred** for runtime behavior |141| 3 | **Screenshots / recordings** the user provides | What's in frame, and only that | **Observed** in frame; **Inferred** outside it |142| 4 | **Source code** in the working directory — components, routes, tokens, copy strings | Structure, states that exist in code, tokens, a11y attributes | **Observed** for what the code says; **Inferred** for what it renders |143| 5 | **Verbal description only** | A model of the product, not the product | **Hypothesis** — never higher |144145**The hard rules:**146147- **Never invent a screen, a label, a state, or a behavior you did not see.** Not148 a plausible one, not a typical one. If you need to name a button, quote it.149- **A finding with no evidence is a hypothesis to verify**, labeled `Hypothesis`,150 and phrased as a question the team can answer.151- **Partial coverage is stated, not filled in.** If you were asked to audit152 checkout and only saw the cart, the report says so in §Scope and the backlog153 says what's still unaudited. Inference does not close that gap.154- **If nothing usable is available, ask for scope + access before auditing** —155 one round of questions, then work with whatever comes back.156157---158159## 2. The audit spine — 16 dimensions160161Always in scope for a full audit; a scoped audit uses the subset that fits. Each162reference file gives, per check: **what to check · why it matters · common163failure signatures · what a fix looks like.**164165| # | Dimension | Covers | Load |166|---|---|---|---|167| 1 | **First-run & onboarding** | Time to first value, permission/signup timing, skippability, gating | `dimensions/onboarding-and-flows.md` |168| 2 | **Information architecture & navigation** | Findability, depth, labeling, orientation, dead ends | `dimensions/navigation-and-ia.md` |169| 3 | **Core task flows** | Step count, friction, drop-off risk, task success, reversibility | `dimensions/onboarding-and-flows.md` |170| 4 | **Input & forms** | Field count, validation timing, error messaging, autofill, keyboard | `dimensions/forms-and-input.md` |171| 5 | **System status & feedback** | Loading, skeletons, optimistic updates, progress, confirmations | `dimensions/feedback-and-states.md` |172| 6 | **Error prevention & recovery** | Destructive-action guards, undo, recovery paths | `dimensions/feedback-and-states.md` |173| 7 | **State coverage** | Empty, sparse, loading, error, offline, overflow, first-use vs power-use | `dimensions/feedback-and-states.md` |174| 8 | **Content & microcopy** | Clarity, jargon vs audience, tone consistency, CTA labeling | `dimensions/content-and-copy.md` |175| 9 | **Visual hierarchy & layout** | Scan path, density, grouping, whitespace, focal points | `dimensions/visual-hierarchy.md` |176| 10 | **Design system consistency** | Token adherence, one-off values, component drift, spacing rhythm | `dimensions/design-system.md` |177| 11 | **Data display** | Number formatting and alignment, precision, truncation, units, timestamps, sort/filter | `dimensions/data-display.md` |178| 12 | **Accessibility** | WCAG 2.1 AA: contrast, focus, target size, semantics, alt text, motion, SR flow | `accessibility.md` |179| 13 | **Responsive & platform conventions** | Breakpoints, touch targets, gestures, platform idioms, safe areas | `platform-web.md` / `platform-mobile.md` |180| 14 | **Perceived performance** | Time-to-interactive feel, layout shift, blocking states | `dimensions/feedback-and-states.md` |181| 15 | **Trust, safety & privacy** | Data handling clarity, consent, irreversibility warnings | `dimensions/trust-and-dark-patterns.md` |182| 16 | **Dark patterns** | Forced continuity, confirmshaming, hidden costs, manufactured urgency | `dimensions/trust-and-dark-patterns.md` |183184**Onchain products add** `references/web3.md` — wallet connection, address and185identity display, transaction lifecycle, cost clarity, approvals and delegation,186onchain error taxonomy, security posture, on/off-ramp friction, and187crypto-native vs mainstream wording. It is a layer on top of all 16, never a188replacement, and it is loaded only when §0e says so.189190---191192## 3. The finding schema193194Every finding, without exception:195196```197ID stable, dimension-prefixed — NAV-03, A11Y-07, FORM-02198Dimension the primary one of the 16 (or WEB3); name the others it touches199Severity Blocker | High | Medium | Low200Confidence Observed (source) | Inferred | Hypothesis201Location screen, flow step, component, file:line, or Figma node202Evidence what you actually saw — quote the label, describe the state203Why it matters the user consequence, not the rule citation204Recommendation the concrete change; verbatim copy rewrites when copy is the issue205Effort S | M | L206```207208**"Why it matters" opens on the person, never on this skill.** A check ID is not209a reason — it's a bookmark, and citing one to justify a finding is the same move210as "best practice says". The check IDs in the reference files exist so *you* can211navigate them and so related findings can be batched; they are internal. Put212them in a trailing `Related.` line if they're useful, and nowhere else.213214| Don't | Do |215|---|---|216| "WEB3-G calls for the insufficient state to be surfaced at input time." | "The user has to convert 5,376 tokens and 3,200 hours into the same unit and subtract, to discover why the button is dead. Most will conclude it's broken." |217| "This violates FORM-B — placeholders aren't labels." | "Once they start typing, the field's meaning is gone. Anyone interrupted mid-form can't tell what they were entering." |218219If you can't state the consequence without naming a check, you haven't found a220finding — you've found a rule the product doesn't follow, which is not the same221thing and may not matter here.222223### Severity — graded the same way every time224225- **Blocker** — users **cannot complete a core task**, or they risk irreversible226 loss (data, money, access). Includes: a flow with no exit, a destructive action227 with no confirmation or undo, a keyboard trap, an error state with no recovery228 path. Ship-stopping.229- **High** — significant friction or misunderstanding **on a core path**. The230 task is completable, but a meaningful share of users will fail, hesitate,231 double-take, or get it wrong. Includes AA contrast failures on primary content232 and missing focus indication on a primary flow.233- **Medium** — degrades quality on **secondary paths**, or a core-path issue that234 costs seconds rather than success. Inconsistency users will notice.235- **Low** — polish. Real, but nobody abandons over it. Alignment, an off-scale236 spacing value, a slightly-off tone.237238Two calibrations: **severity is about user consequence, not how much it annoys239you**; and **frequency multiplies it** — a Medium defect on the screen everyone240sees every day outranks a High on a settings page three people visit.241242### Confidence — earned, not assumed243244- **Observed** — you saw it. **Always name the source in parentheses**, because245 "Observed" alone hides the difference between reading a line of CSS and246 measuring a rendered pixel: `Observed (code)` · `Observed (rendered)` ·247 `Observed (measured)` · `Observed (computed)` · `Observed (sampled)` ·248 `Observed (design file)` · `Observed (recording)`. Combine when both apply —249 `Observed (code + computed)`.250251 **That list is examples, not an enum.** If none of the words fits what you252 actually did, write the one that does — `Observed (pixel-sampled from a253 screenshot, not measured on a render)` is a better label than any of the above254 if that is what happened. The rule underneath is the only one that matters:255 **name the source precisely, and never borrow a stronger word than you earned.**256257 **`measured` and `computed` are not the same claim**, and contrast is where258 the difference bites. A ratio read off rendered pixels is *measured*; a ratio259 produced by running `contrast-check.py` on hex values found in a stylesheet is260 *computed* — it assumes those values reach the screen unmodified by opacity,261 a filter, a cascade, or whatever sits behind them. Computed is usually right262 and always cheaper; it is still not the same as having looked.263- **Inferred** — the evidence strongly implies it but you didn't see the result264 (code has no `onError` branch → the error state is probably missing).265- **Hypothesis** — plausible from a description, unverified. Phrase it as a266 question. **Never present a hypothesis in the findings table as if it were267 observed.** A few of them among real findings go in §6 of the report. When268 the *whole* review is hypotheses — a description-only request — don't force269 them into §6; the document changes shape instead (`report-template.md`,270 description-only review).271272**Split the label when the finding is part fact and part inference.** Reading273code tells you what exists; it does not tell you how it looks or feels. A274finding whose existence you read but whose *appearance* you never saw is275`Observed (code); rendering Inferred` — one label, honestly compound. This is276the single most common place confidence gets quietly inflated: the scope section277says nine of ten screens were never rendered, and then every finding is marked278Observed anyway. If §1 says a whole class of evidence is missing, the per-finding279labels have to show it.280281### Effort282283**S** — copy, a token, a prop, an attribute; under an hour. **M** — a component284or one screen's behavior; a day or two. **L** — structural: a flow, the IA, the285design system. Effort is *your engineering estimate for their codebase*; if you286haven't seen the code, say the estimate is rough.287288---289290## 4. Report structure291292**The deliverable is a Markdown file, in every case** —293`ux-audit-<scope>-<date>.md` in the working directory, or `~/Documents/ux-audits/`294when there is no project to be in. Write it, then summarise it in your reply.295Summarising into the chat *instead of* writing it is not a lighter version of296the deliverable; it is not delivering. Paths and templates live in297**`references/report-template.md`** — don't inline them here.2982991. **Scope & evidence base** — what was audited, what was not, with what access3002. **Executive summary** — 5–8 sentences; the three things that matter most3013. **Quick wins** — high impact / low effort, extractable as a standalone list3024. **Findings by dimension**, sorted by severity within each3035. **Prioritized backlog** — an ordered, actionable list. Not a 2×2 matrix.3046. **What's working, and what you left alone** — brief; the second half names305 what a reader might expect flagged and says why it wasn't3067. **Open questions** — hypotheses, and what needs user data to settle307308A per-dimension **maturity rating (1–5)** is optional and allowed. If you use it:309integers only, one line of justification each, and **no composite score** —310"3.7/5 overall UX health" implies a measurement you did not perform. Don't311manufacture precision.312313---314315## 5. Stance — how to judge316317- **Opinionated, but reasoned.** Every judgment names the user consequence.318 "Best practice says" is not a reason; "a first-time user can't tell which of319 the two blue buttons submits" is.320- **No cargo-culting.** Something is not wrong because Stripe does it321 differently. It's wrong because it costs the user something you can name.322- **Label what kind of thing it is:**323 - **Defect** — it breaks, misleads, or blocks. Assert it.324 - **Opportunity** — it works; it could work better. Say so plainly.325 - **Taste** — reasonable people differ. **Label it as taste and don't grade326 it Blocker or High.** A section on taste calls is fine; smuggling them in as327 defects is not.328- **Respect deliberate constraints.** If a team clearly traded something away —329 a dense layout for expert throughput, a long form for a regulatory330 requirement — **name the tradeoff** rather than assuming ignorance. Audit the331 tradeoff's execution, not its existence.332- **Anatomy is an example, not a mandate.** Every px, radius, and height in the333 reference files is one reasonable taste. Judge **internal consistency with the334 system the product chose**, never conformance to a number written here.335- **No padding.** A thin audit honestly scoped beats a long one full of generic336 observations. Twelve real findings beat forty, and forty is usually a sign you337 started generating instead of looking.338- **Say what's good, briefly.** Not flattery — calibration. A reader who sees339 only failures can't tell whether you understood the product.340341---342343## 6. Modes344345Defined here so the skill is portable; `.claude/commands/` are thin wrappers.346347| Mode | Scope | Loads | Output |348|---|---|---|---|349| **audit** (default) | Full product or a named area, all 16 dimensions | The gate, intake, every dimension file the scope touches | Full report |350| **flow** | One flow, end to end, step by step | `onboarding-and-flows.md` + `forms-and-input.md` + `feedback-and-states.md` + `content-and-copy.md` | Per-step findings + a flow map |351| **quick** | Heuristic sweep, **~10 findings max**, highest severity only | This file + `report-template.md` (quick section) | Executive summary + quick wins; no per-dimension chapters |352| **a11y** | Accessibility only, WCAG 2.1 AA | `accessibility.md` + the relevant platform file | Findings keyed to success criteria |353| **tokens** | Design system consistency only | `dimensions/design-system.md` + `dimensions/visual-hierarchy.md` | Drift inventory + consolidation proposal |354| **web3** | Onchain surfaces only | `web3.md` + `dimensions/trust-and-dark-patterns.md` | Onchain findings layered on any general ones already made |355356**Every mode writes a file. Including `quick`.** A shorter report is still a357report — a five-minute sweep whose findings exist only in the conversation is358five minutes the user cannot share, reopen, or paste into a ticket. `quick`359means *fewer findings*, never *no artefact*. If the working directory isn't a360project, `~/Documents/ux-audits/` and say where it landed. This applies to every361row of the table above, whatever a mode's section of `report-template.md` does or362doesn't repeat.363364`quick` is a real constraint, not a suggestion: if a sweep finds thirty things,365report the ten that matter and say thirty were seen.366367---368369## 7. References — load what the scope needs370371**Always, at the start of a real audit:**372- `references/evidence-intake.md` — how to gather and record evidence from each373 source, and the limitations of each.374375**Per dimension** (§2 table routes to these):376- `references/dimensions/onboarding-and-flows.md`377- `references/dimensions/navigation-and-ia.md`378- `references/dimensions/forms-and-input.md`379- `references/dimensions/feedback-and-states.md`380- `references/dimensions/content-and-copy.md`381- `references/dimensions/visual-hierarchy.md`382- `references/dimensions/design-system.md`383- `references/dimensions/data-display.md`384- `references/dimensions/trust-and-dark-patterns.md`385386**Cross-cutting:**387- `references/accessibility.md` — WCAG 2.1 AA checks, contrast math, focus rules388- `references/platform-web.md` — website / web app / desktop conventions389- `references/platform-mobile.md` — iOS, Android, and mobile-web conventions390- `references/web3.md` — onchain module, **only** when §0e says the product is onchain391- `references/report-template.md` — before writing the report392393## Scripts394395Dependency-free Python 3, no API, no network. It supports **remediation396proposals**; it is not part of grading.397398- `scripts/contrast-check.py` — WCAG 2.x contrast ratios for a pair, a foreground399 against several backgrounds, or a whole palette; reports AA/AAA pass/fail,400 warns when a shade has no AA-legible ink at all, and suggests the nearest401 passing shade of the same hue. Use it to make a contrast finding concrete402 instead of eyeballed.403404**There is deliberately no palette generator here.** The fix for a failing405colour is the smallest set of values that clears AA in the product's existing406system — `--suggest` gives you those — not a new ramp. **An audit never407regenerates a team's palette**: it produces findings, not a rebrand.