Skip to content
Back to skills

Wp Audit Ux Standards

ASecurity

The UX-NNN usability catalog for a WordPress site — forms and data entry, navigation and task flow, broken internal and external links, hover and active states, line length per breakpoint, logo and typography consistency — with the page-level and site-level split, the applicability rules that decide which criteria are N/A and keep the score honest, the owner each fix belongs to, and the standard a visual fix must meet. Use when running /wp-audit --usability, explaining or fixing a UX-NNN find...

  • 6 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 20, 2026
designgoreactperformance

Works with

  • cursor
  • cli

Security analysis

A100/100

Scanned October 7, 2026

npx -y skills add yojahny55/claude-wp-builder --skill wp-audit-ux-standards --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Wp Audit Ux Standards?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Wp Audit Ux Standards
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/yojahny55-wp-audit-ux-standards/badge)](https://www.skillsdirectory.com/skills/yojahny55-wp-audit-ux-standards)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: wp-audit-ux-standards
description: The UX-NNN usability catalog for a WordPress site — forms and data entry, navigation and task flow, broken internal and external links, hover and active states, line length per breakpoint, logo and typography consistency — with the page-level and site-level split, the applicability rules that decide which criteria are N/A and keep the score honest, the owner each fix belongs to, and the standard a visual fix must meet. Use when running /wp-audit --usability, explaining or fixing a UX-NNN finding such as UX-014 on page:/contact/, deciding whether a usability criterion is N/A on a brochure site or a catalog store, or scoring usability. Not for contrast, ARIA, focus or target size (wp-audit-a11y), Core Web Vitals or Lighthouse (wp-audit-performance), or titles and schema (wp-audit-seo-standards).
user-invocable: false
---

# Usability standards

The criteria for whether a person can use the site, which the other six auditors do not
ask: a form that marks no field as required is valid HTML, escapes correctly, loads fast and
passes WCAG, and is still harder to use than it needs to be.

## What this is not

- **Not accessibility.** Contrast, focus order, ARIA, keyboard traps and target size belong
  to `wp-audit-a11y` and stay there. Where the two touch — a link that is distinguishable
  only by colour is both — the accessibility code wins and the usability catalog does not
  restate it. Two codes for one defect inflate every count.
- **Not performance.** Core Web Vitals, budgets and Lighthouse belong to
  `wp-audit-performance`.
- **Not an opinion about taste.** Every criterion below has a pass condition somebody else
  could check and reach the same answer. "The hero could be stronger" is not a finding.

## The catalog

Codes are `UX-NNN`. The numbers are the criteria's own, zero-padded, so `UX-006` and
`UX-034` sort the way a reader expects and an id never changes meaning between runs.
**Numbers are never reused**: a retired criterion leaves a hole.

`UX-022`, `UX-023` and `UX-039` to `UX-058` are not holes. They are the browser suite's own
accessibility, SEO and performance criteria, which
`${CLAUDE_PLUGIN_ROOT}/templates/audit-suite/scripts/to-run.js` emits under this prefix —
contrast arrives as `UX-045`, which is `A11Y-003` here. They are not usability criteria and
not rows of this catalog. A new usability criterion takes the next number above `UX-058`.

Each row carries the owner its fix belongs to, in the four-way split `/wp-audit` Step 8.5
defines — `code` travels with the commit, `setting` does not, `content` needs somebody to
write a text, `manual` needs judgement. The owner is a property of where the fix lands, not
of whether the audit could apply it. Where the browser suite emits a criterion too, the
owner here is the suite's (`aplicacion()` in
`${CLAUDE_PLUGIN_ROOT}/templates/audit-suite/lib/plan.js`): a measured row replaces the
agent's in the merge, so a second classification would make a defect's owner depend on
whether `--suite` ran. A row the suite never emits keeps the owner below, whatever `plan.js`
says about it.

### A. Forms and data entry

Applicability: see *Applicability* below — the whole group is N/A on a site with no form.

| Code | Criterion | How to detect | Passes when | Severity | Owner |
|---|---|---|---|---|---|
| UX-001 | Required and optional fields are distinguishable | `required`/`aria-required`, label text, or a visible mark; check it is not colour alone | the distinction is visible and survives colour blindness | WARNING | code |
| UX-002 | Field size matches the expected value | `size`, `maxlength`, `cols`/`rows`, rendered width against the datum | a postcode field is not as wide as an address | INFO | manual |
| UX-010 | Focus lands in the first field | `autofocus`, or JS that focuses on load | the first relevant field takes focus, and no page steals focus where it should not | INFO | code |
| UX-011 | Consequential actions confirm first | a confirm step before delete, pay, or an irreversible send | the consequence is stated before it happens | WARNING | code |
| UX-012 | Success is reported | a success message, a confirmation page, a toast | the user is told the action worked, not left at a silent reload | WARNING | code |
| UX-013 | Invalid fields are highlighted and explained | error states, `aria-invalid`, a message tied to the field | the error is visible on the field and says how to fix it | WARNING | code |
| UX-016 | Forms validate before submitting | `type`, `pattern`, `min`/`max`, `required`, or JS validation | plainly invalid input does not reach the server | WARNING | code |
| UX-024 | Error messages say what to do | read the message text | "Enter an email like name@domain.com", not "Error 3" | WARNING | content |
| UX-035 | Focus moves to the first field in error | JS that focuses the first invalid field after submit | the user lands on what they must fix | INFO | code |
| UX-037 | No unnecessary registration | walk the key flows | nothing demands an account for a task that does not need one | WARNING | manual |
| UX-038 | The privacy policy is easy to find | a link in the footer and beside any form asking for personal data | reachable from where the data is asked for | WARNING | code |

### B. Navigation and task flow

| Code | Criterion | How to detect | Passes when | Severity | Owner |
|---|---|---|---|---|---|
| UX-003 | Every page has an exit | a cancel/close/back control in modals and flows | the current task can be abandoned without being trapped | WARNING | code |
| UX-004 | Multi-step processes go back | the wizard or stepper pattern | a working Previous that keeps what was entered | WARNING | code |
| UX-017 | The home page links the important sections | the home's primary navigation | the key sections are one click from home | INFO | content |
| UX-020 | Search is visible on every page | `input[type="search"]`, a search form, a search icon | search is present and in the same place throughout | INFO | code |
| UX-021 | Home is reachable from everywhere | the logo or a Home link resolving to `/` on every template | consistent and visible on every page | WARNING | code |
| UX-025 | The user can tell where they are | breadcrumbs, an active section, a section title | the position in the hierarchy is identifiable | INFO | code |
| UX-036 | Navigation is ordered logically | read the menu order | frequency, task flow or theme — some order a person could name | INFO | manual |

### C. Links

| Code | Criterion | How to detect | Passes when | Severity | Owner |
|---|---|---|---|---|---|
| UX-014 | No broken internal links | collect the internal `href`s of the pages in scope, deduplicated and capped, and **follow them** | every internal link resolves | CRITICAL | code |
| UX-015 | No broken external links | the same, for external hosts | no 404 and no DNS failure | WARNING | code |
| UX-018 | Links are identifiable at rest | the `a` rule in its default state | recognisable without hovering, and not by colour alone | WARNING | code |
| UX-019 | Image links carry alternative text | `a > img` with no `alt`, or an empty `alt` with no other label | every image link tells a screen reader where it goes | WARNING | content |
| UX-027 | Link text matches its destination | compare the link text with the destination's `<title>`/H1 | the text predicts the page; no "click here" | INFO | content |
| UX-028 | Internal and external links are distinguishable | an icon, a stated `target="_blank"`, wording | the user knows they are leaving before they click | INFO | code |

**`UX-014` is followed, not inferred.** A link that looks internal and 404s is the finding;
a list of hrefs is not. When the links cannot be followed, report `UNMEASURED` with the
list, never `PASS`. The sweep is scoped, not exhaustive — each link requested once,
at most 50 HTTP requests per page, a CDN challenge `UNMEASURED` rather than broken — and it
runs through Step 2 of `${CLAUDE_PLUGIN_ROOT}/agents/wp-audit-ux.md`, which drives
`${CLAUDE_PLUGIN_ROOT}/bin/link-sweep.mjs`. Run that procedure; do not rebuild it here.

**One row per page, not per link.** Three broken links on `/contact/` are one finding,
`UX-014 : page:/contact/`, whose evidence lists all three with their status codes. A row per
link turns one bad footer into forty findings that are one fix, and it matches nothing the
suite emits — `/wp-audit` Step 7 merges on `check` + `resource`, so both sides have to count
the same way or the duplicate survives.

### D. Interaction and visual feedback

| Code | Criterion | How to detect | Passes when | Severity | Owner |
|---|---|---|---|---|---|
| UX-005 | Action elements react to hover | `:hover` rules and `cursor` | every action element gives visible feedback | INFO | code |
| UX-008 | The current menu item is marked | `active`/`aria-current="page"` and the style behind it | the selected item is clearly different | WARNING | code |
| UX-009 | Action elements have room between them | the rendered gap between adjacent action elements, from `getBoundingClientRect()` — the harness lists pairs closer than 8 px | adjacent action elements do not induce a wrong tap. A target smaller than 24×24 is `A11Y-028`, not this row | WARNING | code |
| UX-026 | Button text names the action | read the button labels | "Save changes", not "OK" where OK is ambiguous | INFO | content |
| UX-030 | Icons match what they mean | compare each icon with its function | a magnifier searches, a cart buys | INFO | manual |
| UX-031 | Selected icons differ from unselected | the icon's active state | the selected state is unmistakable | INFO | manual |

### E. Legibility

| Code | Criterion | How to detect | Passes when | Severity | Owner |
|---|---|---|---|---|---|
| UX-006 | Line length | measure the **rendered** characters per line, per breakpoint | ≤85 characters. 86–100 is a warning; over 100 fails | WARNING | code |
| UX-007 | Text blocks are 5–8 lines | the length of unbroken blocks | text is segmented rather than a wall | INFO | content |
| UX-032 | Typography is consistent site-wide | `font-family` and the type scale, compared across templates | one system, not one per template | WARNING | manual |

**`UX-006` is measured at every breakpoint and names the one that fails.** The same
paragraph with no `max-width` runs about 43 characters on a phone, 76 on a tablet and 142
on a desktop. A finding that does not name the screen cannot be acted on, and the inverse
case is real too — a theme that never reduces its type can overflow on mobile and not on
desktop. Report the longest line per breakpoint.

### F. Visual identity

| Code | Criterion | How to detect | Passes when | Severity | Owner |
|---|---|---|---|---|---|
| UX-029 | The product's identity is present | `<link rel="icon">`, the logo, colour tokens, the type family | the brand is recognisable and consistent | WARNING | code |
| UX-033 | Images, tables and charts are sharp | rendered sharpness, `srcset`, modern formats | crisp on standard and high-density screens | INFO | code |
| UX-034 | The logo is in the same place on every page | compare headers across pages | one position throughout | WARNING | code |

## Page-level and site-level

Most criteria are answered **per page**, which is why a report is organised page by page.
Some can only be answered by comparing pages, and answering those once per page produces
the same finding N times and still does not say what changed between them.

- **Site-level** — `UX-029`, `UX-032`, `UX-034`, `UX-036`, `UX-038`, `UX-015`, `UX-028`.
  Evaluate once, comparing across the audited pages. When one reveals an inconsistency,
  name the pages it differs between.
- **Home only** — `UX-017`.
- **Everything else is page-level.** A criterion that fails on some pages and not others is
  reported on each page it fails on. That is not duplication: the fix is per template, and
  a single site-level row would hide which page is wrong.

The two carry different resources, and the resource is half of a finding's ledger identity:
a page-level finding is `page:/contact/`, a site-level one is `site`. Writing a site-level
finding with no resource at all leaves its identity to whatever the renderer falls back to,
which is not a contract anyone stated.

## Applicability, and why it changes the score

A site is not worse for lacking a feature it was never meant to have. Before scoring,
decide which criteria apply to **this** site. This list is the only statement of
applicability; every criterion not on it applies to every site.

- no form and no data entry → all of group A (Forms and data entry)
- no action with consequences (delete, pay, an irreversible send) → `UX-011`
- no account and no personal data asked for → `UX-037`, `UX-038`
- no modal and no multi-step flow → `UX-003`, `UX-004`
- no navigation menu → `UX-008`, `UX-036`
- no external links → `UX-015`, `UX-028`
- no image used as a link → `UX-019`
- no images, tables or charts → `UX-033`
- a single page → `UX-021`, `UX-025`, `UX-034`; and `UX-017` asks only whether the page's
  own navigation reaches each of its sections
- fewer than 10 published pages and posts, and no blog, shop or other archive → `UX-020`
- no text block over 5 lines → `UX-006`, `UX-007`
- no icons → `UX-030`, `UX-031`
- a catalog store (`site.store_tier` = `catalog`, recorded by `/wp-audit` Step 2.3) has no
  cart, checkout or payment → `UX-004`, `UX-011`, `UX-012` and `UX-037` are never scored
  against those flows, and are `N/A ("catalog: nothing purchasable")` when no other flow
  carries them. `unknown` is not `catalog`: it audits as a store. Read the recorded tier;
  never infer it from whether a checkout page happens to exist

**N/A is excluded from the denominator and reported separately.** On a brochure site where
16 of the 36 criteria are N/A, 15 passed is 15/20 — a measurement. Scored as 15/36, against
sixteen criteria that never applied, it punishes the site for its own shape.

**When in doubt, the criterion applies.** N/A means "this site genuinely lacks the thing
the criterion evaluates". It never means "this applies and is not implemented" — that is a
failure, and the difference is the whole point. A site with a form and no required marks
fails `UX-001`; a site with no form at all is N/A on it.

And a criterion whose applicability cannot be decided from what was measured is
`UNMEASURED`, with what would decide it. Not a pass.

## Measurement, not inference

Every finding carries what produced it: the selector, the `href` followed and its status
code, the measured characters per line and the breakpoint, the computed value. A criterion
answered from reading a template rather than loading a page is an inference, and it is
reported as one — `UNMEASURED` with the command or the URL that would settle it.

Rendered measurements come from `${CLAUDE_PLUGIN_ROOT}/bin/ux-probe.mjs`, which the agent's
Step 2 runs in a single browser launch: the longest line per breakpoint, the gaps between
action elements, link styling at rest, image links with no name, required fields with no
mark, and the `href`s `UX-014` and `UX-015` follow. `--suite`
(`${CLAUDE_PLUGIN_ROOT}/templates/audit-suite/`) is a second measured path for the
criteria it covers. With no browser at all, the criteria that need a rendered page are
`UNMEASURED`, and the ones a file scan can answer still run.

## The standard a fix has to meet

Almost every fix in a row whose Owner is `code` is a visual change, and `UX-018`, `UX-005`,
`UX-009` and `UX-006` move layout. So a fix to one of these is only correct when it is
evidenced the same way a finding is:

- **Consent.** A change to how the site looks is the client's decision, not the audit's. A
  criterion that fails is reported; it is not quietly restyled into passing.
- **Equivalence, measured.** The computed values that were not the target of the fix are
  identical after it — `color`, `backgroundColor`, `fontSize`, `fontFamily`, `borderWidth`,
  `borderRadius`, and the element's box. A value that moved and was not meant to is a
  regression, whatever the finding says.
- **Coverage.** Desktop and mobile, and every element carrying the class — not the one the
  finding named.

A tag swap is not exempt, though it looks safest: the browser styles the new element
itself. Step 4 of `${CLAUDE_PLUGIN_ROOT}/agents/wp-audit-ux.md` holds the measurement that
satisfies this standard, and the case that taught it.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.