Files
school_compare/docs/superpowers/plans/2026-07-02-ux-audit.md
T
2026-07-02 10:14:34 +01:00

20 KiB
Raw Blame History

SchoolCompare UX/UI Audit Execution Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Execute the journey-led UX/UI audit of live schoolcompare.co.uk defined in docs/superpowers/specs/2026-07-02-ux-audit-design.md, producing a prioritized (P0P3) audit report at docs/superpowers/specs/2026-07-02-ux-audit-report.md.

Architecture: Five journey walk-throughs (traffic-ordered) at two viewports using Playwright browser tools against the live site, each producing a committed notes file with friction points, "works well" observations, and axe-core scan results. A cross-cutting cohesion pass compares components across pages. A final synthesis task converts notes into the prioritized report.

Tech Stack: Playwright MCP browser tools (mcp__plugin_playwright_playwright__*), axe-core 4.x injected from CDN, markdown notes committed to git.

Global Constraints

  • Audit the live site https://schoolcompare.co.uk — do not start any local server (CLAUDE.md).
  • Viewports: mobile 390×844 (primary) and desktop 1440×900. Mobile findings weigh more (56% of traffic).
  • A finding is valid only if it cites: a Nielsen/NN-g heuristic violation, a WCAG 2.2 AA failure, a mobile-usability standard, or an observed task-flow obstruction. No taste-only findings.
  • Every finding: evidence → argument (why it hurts parents) → recommendation → uplift indication (which analytics number moves, direction, small/moderate/large band with reasoning — never invented percentages).
  • Read-only with respect to the site: browse and inspect only; never submit forms that create/modify data (search and filter interactions are fine).
  • Notes live in docs/superpowers/specs/2026-07-02-ux-audit-notes/; screenshots go to the session scratchpad (referenced by filename in notes, not committed).
  • Analytics baseline for weighting (30 days): entries / 63%, /compare 20%, /rankings 6%; exits / 46%, /compare 32%, /rankings 13%; views / 52%, /compare 27%, /rankings 12%, /admissions 5%; school pages ~1% each (SEO long tail); 56% mobile.

Note on tool schemas: Playwright tools are deferred. Before first use in any task, load them: ToolSearch with query select:mcp__plugin_playwright_playwright__browser_navigate,mcp__plugin_playwright_playwright__browser_resize,mcp__plugin_playwright_playwright__browser_snapshot,mcp__plugin_playwright_playwright__browser_take_screenshot,mcp__plugin_playwright_playwright__browser_evaluate,mcp__plugin_playwright_playwright__browser_click,mcp__plugin_playwright_playwright__browser_type,mcp__plugin_playwright_playwright__browser_press_key,mcp__plugin_playwright_playwright__browser_console_messages


Task 1: Audit scaffolding + axe-core harness verified on the homepage

Files:

  • Create: docs/superpowers/specs/2026-07-02-ux-audit-notes/axe-snippet.js
  • Create: docs/superpowers/specs/2026-07-02-ux-audit-notes/TEMPLATE.md

Interfaces:

  • Produces: axe-snippet.js — a self-contained async JS function body for browser_evaluate that loads axe-core from CDN (idempotent) and returns {violationCount, violations: [{id, impact, description, nodes: count, sampleTargets}]} filtered to WCAG 2.2 A/AA rules. All journey tasks run this verbatim on each page state.

  • Produces: TEMPLATE.md — the notes-file structure every journey task copies.

  • Step 1: Write the axe harness snippet

Create docs/superpowers/specs/2026-07-02-ux-audit-notes/axe-snippet.js:

// Body for playwright browser_evaluate: () => { ...this content... }
// Loads axe-core 4.x from CDN (skips if already present), runs WCAG A/AA scan.
return (async () => {
  if (!window.axe) {
    await new Promise((resolve, reject) => {
      const s = document.createElement('script');
      s.src = 'https://cdn.jsdelivr.net/npm/axe-core@4.10.2/axe.min.js';
      s.onload = resolve;
      s.onerror = () => reject(new Error('axe failed to load'));
      document.head.appendChild(s);
    });
  }
  const results = await window.axe.run(document, {
    runOnly: { type: 'tag', values: ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'wcag22aa'] }
  });
  return {
    url: location.pathname,
    violationCount: results.violations.length,
    violations: results.violations.map(v => ({
      id: v.id,
      impact: v.impact,
      description: v.help,
      nodes: v.nodes.length,
      sampleTargets: v.nodes.slice(0, 3).map(n => n.target.join(' '))
    }))
  };
})();
  • Step 2: Write the notes template

Create docs/superpowers/specs/2026-07-02-ux-audit-notes/TEMPLATE.md:

# Journey N: <name> — audit notes

**Pages visited:** <paths>
**Viewports:** 390×844, 1440×900

## Task attempt log
<What was attempted, step by step, and where time/attention went. Note seconds-to-goal where measurable.>

## Friction points
For each:
- **F<N>. <short title>**
  - Evidence: <screenshot filename(s), observed behaviour, axe rule id if applicable>
  - Criterion violated: <heuristic / WCAG SC / mobile standard / task obstruction>
  - Argument: <why this hurts a parent completing the task>
  - Severity guess: <P0/P1/P2/P3 — provisional, finalized in synthesis>

## Works well — keep
- <observation, with why it works>

## Axe results
- <path> @ <viewport>: <violationCount> violations — <ids with impact>

## Manual WCAG spot checks
- Touch targets ≥24px on interactive elements: <pass/fail + examples>
- Keyboard: tab order, focus visibility (desktop only): <pass/fail + examples>
- Zoom 200% text reflow (desktop only): <pass/fail>

## Screenshots
- <filename>: <what it shows>
  • Step 3: Verify the harness against the live homepage

Load Playwright tool schemas (see Global Constraints note). Then:

  1. browser_resize to 390×844.
  2. browser_navigate to https://schoolcompare.co.uk/.
  3. browser_evaluate with the contents of axe-snippet.js as the function body.

Expected: a JSON result with violationCount (any number ≥ 0) and no thrown error. If the CDN is blocked, switch the src to https://unpkg.com/axe-core@4.10.2/axe.min.js in the file and re-verify.

  • Step 4: Take a baseline screenshot to confirm capture works

browser_take_screenshot with filename home-mobile-baseline.png. Expected: file saved, path returned.

  • Step 5: Commit
git add docs/superpowers/specs/2026-07-02-ux-audit-notes/
git commit -m "chore(audit): axe harness and notes template for UX audit"

Task 2: Journey 1 — Home → find my school (63% of entries, 46% exits)

Files:

  • Create: docs/superpowers/specs/2026-07-02-ux-audit-notes/journey-1-home-find-school.md (copy structure from TEMPLATE.md)

Interfaces:

  • Consumes: axe-snippet.js via browser_evaluate; TEMPLATE.md structure.

  • Produces: journey-1-home-find-school.md — notes consumed by Task 8 synthesis.

  • Step 1: Mobile walk-through (390×844)

  1. browser_resize 390×844, browser_navigate https://schoolcompare.co.uk/.
  2. browser_snapshot — record what is above the fold: is the search input visible without scrolling? What competes for attention? Screenshot j1-home-mobile-fold.png.
  3. Scroll the full page (browser_press_key End or evaluate window.scrollTo), screenshot j1-home-mobile-full.png. Note content order: does featured/secondary content precede the primary task?
  4. Task attempt A (school by name): type a real school name into search, e.g. Welland Primary (known from analytics). Record: keystrokes-to-results, result quality (is the right school first?), loading feedback, and taps needed to reach /school/146678-welland-primary-school. Screenshot the results state j1-search-results-mobile.png.
  5. Task attempt B (postcode): return home, search a plausible postcode (e.g. B91 3 area for Solihull, or any valid UK postcode like SW1A 1AA). Record: is postcode search discoverable/labelled? Distance shown? Sensible ordering? Screenshot j1-postcode-results-mobile.png.
  6. Record time-to-school-page for both attempts against the spec's ~15s target.
  7. Run axe snippet on: home (initial) and home (results visible). Record results.
  • Step 2: Desktop walk-through (1440×900)

Repeat Step 1's navigation and task attempt A at 1440×900 (screenshots j1-home-desktop-fold.png, j1-search-results-desktop.png). Additionally: tab through the page with keyboard — record focus visibility and whether search → results → school link is keyboard-operable. Test 200% zoom (browser_evaluate document.body.style.zoom is NOT valid for this — instead resize to 720×450 which approximates 200% reflow at 1440) and note any loss of content/overlap.

  • Step 3: Write notes file

Fill journey-1-home-find-school.md per template. Every friction point needs evidence + criterion + argument. Explicitly answer: "why do 46% of visitors exit at home?" — list the plausible causes observed.

  • Step 4: Commit
git add docs/superpowers/specs/2026-07-02-ux-audit-notes/journey-1-home-find-school.md
git commit -m "docs(audit): journey 1 notes — home to school search"

Task 3: Journey 2 — Cold landing on a school detail page (SEO long tail)

Files:

  • Create: docs/superpowers/specs/2026-07-02-ux-audit-notes/journey-2-school-detail-cold.md

Interfaces:

  • Consumes: axe-snippet.js, TEMPLATE.md.

  • Produces: journey-2-school-detail-cold.md for Task 8.

  • Step 1: Mobile cold landing (390×844)

Navigate directly (no prior site context — this simulates a Google arrival) to https://schoolcompare.co.uk/school/136916-the-castle-school. Then assess in order:

  1. First-screen orientation: within one screen, can a parent tell what site this is, what school this is, and what the site offers? Screenshot j2-school-mobile-fold.png.
  2. Scroll the entire page. Screenshots at each major section (j2-school-mobile-<section>.png). For each data block (results, Ofsted, characteristics, admissions): is it comprehensible to a non-specialist? Is jargon (RWM, expected standard, progress scores) explained in place?
  3. Next-step paths: is there an obvious "compare this school" and "schools near this one" action? How many taps to a comparison including this school? Record the exact path or its absence.
  4. Repeat the cold landing for a contrasting school https://schoolcompare.co.uk/school/146678-welland-primary-school (different data availability) — note any layout breakage or missing-data handling. Screenshot anomalies only.
  5. Run axe snippet on both school pages. Record results.
  • Step 2: Desktop pass (1440×900)

Reload .../136916-the-castle-school at desktop. Screenshot j2-school-desktop-fold.png. Check: hero/map rendering, chart legibility, keyboard focus through interactive elements, link affordance (do school-page links look clickable?).

  • Step 3: Write notes file

Fill journey-2-school-detail-cold.md. Explicitly answer: "a parent lands here from Google — what would make them stay and use the site rather than bounce back to search results?"

  • Step 4: Commit
git add docs/superpowers/specs/2026-07-02-ux-audit-notes/journey-2-school-detail-cold.md
git commit -m "docs(audit): journey 2 notes — cold landing on school detail"

Task 4: Journey 3 — Building a comparison (27% of views, 32% exits)

Files:

  • Create: docs/superpowers/specs/2026-07-02-ux-audit-notes/journey-3-compare.md

Interfaces:

  • Consumes: axe-snippet.js, TEMPLATE.md.

  • Produces: journey-3-compare.md for Task 8.

  • Step 1: Mobile walk-through (390×844)

  1. Navigate to https://schoolcompare.co.uk/compare directly (20% of sessions enter here). Screenshot empty state j3-compare-empty-mobile.png. Is the empty state instructive — does it tell a parent what to do first?
  2. Add two schools via whatever mechanism the page offers (search within compare, or navigate to school pages and use their compare action — record which paths exist). Count taps from empty state to a two-school comparison. Screenshot j3-compare-two-schools-mobile.png.
  3. Assess the comparison output on mobile: are charts/tables legible at 390px? Horizontal scrolling? Can you tell which school is which (colour + label, not colour alone — WCAG 1.4.1)? Are metric names explained?
  4. Remove a school; add a third. Any state loss, confusing controls, or dead ends? Does the selection persist if you navigate away and back?
  5. Run axe snippet on empty state and populated state. Record results.
  • Step 2: Desktop pass (1440×900)

Repeat comparison-building at desktop. Screenshot j3-compare-two-schools-desktop.png. Keyboard-operate the add/remove flow; record focus behaviour. Check chart tooltips/legends for mouse-only interactions.

  • Step 3: Write notes file

Fill journey-3-compare.md. Explicitly answer: "compare is 32% of exits — is that task-complete satisfaction (fine) or abandonment (problem)? What observed evidence points either way?"

  • Step 4: Commit
git add docs/superpowers/specs/2026-07-02-ux-audit-notes/journey-3-compare.md
git commit -m "docs(audit): journey 3 notes — building a comparison"

Task 5: Journey 4 — Rankings → shortlist (12% of views)

Files:

  • Create: docs/superpowers/specs/2026-07-02-ux-audit-notes/journey-4-rankings.md

Interfaces:

  • Consumes: axe-snippet.js, TEMPLATE.md.

  • Produces: journey-4-rankings.md for Task 8.

  • Step 1: Mobile walk-through (390×844)

  1. Navigate to https://schoolcompare.co.uk/rankings. Screenshot default state j4-rankings-mobile.png.
  2. Is the default ranking explained (which metric, which year, what the numbers mean)? Would a parent understand what "top" means here?
  3. Filter to a local authority (e.g. Solihull). Count taps; is the filter discoverable on mobile? Screenshot filtered state j4-rankings-filtered-mobile.png.
  4. Change the ranking metric. Is the metric picker comprehensible (plain-language labels vs. jargon)?
  5. Tap through to a school from the list; navigate back — is filter state preserved? (Back-navigation state loss is a classic mobile task-killer.)
  6. Run axe snippet on default and filtered states. Record results.
  • Step 2: Desktop pass (1440×900)

Repeat at desktop, screenshot j4-rankings-desktop.png. Check table semantics (real <table> with headers vs. divs — screen-reader implications), sortability affordances, keyboard operation of filters.

  • Step 3: Write notes file + commit

Fill journey-4-rankings.md.

git add docs/superpowers/specs/2026-07-02-ux-audit-notes/journey-4-rankings.md
git commit -m "docs(audit): journey 4 notes — rankings"

Task 6: Journey 5 — Admissions content (5% of views, light pass)

Files:

  • Create: docs/superpowers/specs/2026-07-02-ux-audit-notes/journey-5-admissions.md

Interfaces:

  • Consumes: axe-snippet.js, TEMPLATE.md.

  • Produces: journey-5-admissions.md for Task 8.

  • Step 1: Single mobile pass (390×844)

  1. Navigate to https://schoolcompare.co.uk/admissions. Screenshot j5-admissions-mobile.png.
  2. Light checks only: readability (line length, heading hierarchy), whether the recently added SchoolCompare tool cross-links are present and useful, whether the page's look matches the rest of the site (this feeds the cohesion pass), and one axe scan.
  3. Check discoverability in reverse: from the home page, how does a parent find this content at all? (5% views may be a discoverability problem rather than a demand problem — note evidence either way.)
  • Step 2: Write notes file + commit

Fill journey-5-admissions.md (shorter than the others is expected).

git add docs/superpowers/specs/2026-07-02-ux-audit-notes/journey-5-admissions.md
git commit -m "docs(audit): journey 5 notes — admissions"

Task 7: Cross-cutting cohesion pass

Files:

  • Create: docs/superpowers/specs/2026-07-02-ux-audit-notes/cohesion-pass.md

Interfaces:

  • Consumes: all journey screenshots (scratchpad) and notes files; live site; optionally nextjs-app source for token verification.

  • Produces: cohesion-pass.md for Task 8.

  • Step 1: Component comparison across pages

Using the screenshots already captured plus targeted re-visits, compare across /, /compare, /rankings, /admissions, and a school page:

  1. Typography: collect computed styles via browser_evaluate on each page — e.g. [...document.querySelectorAll('h1,h2,h3,body p, button, a')].slice(0,40).map(e => ({tag: e.tagName, size: getComputedStyle(e).fontSize, weight: getComputedStyle(e).fontWeight, family: getComputedStyle(e).fontFamily.split(',')[0]})) — and diff the scales page-to-page. Record any page using off-scale sizes.
  2. Colour: same technique for color, backgroundColor on buttons/links/chips; flag near-duplicate colours (e.g. two blues doing the same job) and any accent colour used inconsistently.
  3. Components: buttons, chips, cards, empty states, loading states — screenshot side-by-side candidates and note variant drift (different radii, padding, casing, icon usage for the same semantic role).
  4. Navigation & page furniture: header/footer consistency, page-title patterns, back-link behaviour, breadcrumbs presence/absence across page types.
  5. Recent additions check (from spec): map-blended hero, characteristic chips, admissions cross-links — do they feel native to the rest of the site?
  • Step 2: Verify against source where ambiguous

Where a visual inconsistency could be intentional, check nextjs-app styles (grep for the relevant component/tokens) to determine whether a design token exists and is being bypassed, or no token exists. Record which — it changes the recommendation (enforce token vs. create token).

  • Step 3: Write notes file + commit

Fill cohesion-pass.md with the same evidence → criterion → argument structure (criterion here is typically "consistency and standards" heuristic).

git add docs/superpowers/specs/2026-07-02-ux-audit-notes/cohesion-pass.md
git commit -m "docs(audit): cross-cutting cohesion pass notes"

Task 8: Synthesis — prioritized audit report

Files:

  • Create: docs/superpowers/specs/2026-07-02-ux-audit-report.md
  • Read: all files in docs/superpowers/specs/2026-07-02-ux-audit-notes/, spec docs/superpowers/specs/2026-07-02-ux-audit-design.md

Interfaces:

  • Consumes: journey notes 15, cohesion notes.

  • Produces: the final deliverable report.

  • Step 1: Consolidate and deduplicate findings

Read all six notes files. Merge duplicate findings (same root cause observed in several journeys becomes one finding listing all occurrences). Discard any finding lacking evidence or a cited criterion — the spec forbids taste-only findings.

  • Step 2: Assign final priorities and uplift indications

For each finding assign P0P3 per the spec's definitions (traffic-weighted impact × severity), and an uplift line: metric (one of: home 46% exit rate; share of sessions reaching a school page; compare 32% exit rate; rankings→school click-through; school-page bounce-back-to-Google; accessibility compliance), direction, band (small/moderate/large) with one-sentence reasoning. Sanity rules: a P0/P1 must sit on /, /compare, /rankings, or the school-page template; admissions-only findings cap at P2 unless a WCAG failure.

  • Step 3: Write the report

Structure (from spec):

# SchoolCompare UX/UI Audit — 2026-07-02

## Method summary
<viewports, journeys, tools, analytics baseline — half a page>

## What works today — keep
<explicit list with why; protects against change-for-change's-sake>

## Findings

### P0 — Urgent
<each: title, evidence (screenshots/axe ids), criterion, argument, recommendation, uplift>

### P1 — High
### P2 — Medium
### P3 — Nice-to-have

## Accessibility summary
<axe violation table by page/viewport + manual check results; overall WCAG 2.2 AA posture>

## Suggested implementation sequence
<grouped batches of related fixes, ordered by uplift-per-effort; each batch sized as a plausible follow-up project>
  • Step 4: Self-check the report against the spec

Verify: every finding has all four elements (evidence/argument/recommendation/uplift); "works well" section is non-empty; uplift bands never state invented percentages; P0/P1 findings all sit on high-traffic paths; report answers the spec's three goals (a) speed-to-information, (b) end-to-end cohesion, (c) standards compliance. Fix inline.

  • Step 5: Commit
git add docs/superpowers/specs/2026-07-02-ux-audit-report.md
git commit -m "docs(audit): prioritized UX/UI audit report"