Interactive QA pass — post WEB-AG-5 (S3–S7 runtime)
Live interactive QA run against https://pride-website.vercel.app/ on 24 April 2026 (post f66e56a CLAUDE.md level-up). All deferred runtime checks from WEB-AG-5 sessions 3–7 executed in one sweep via Chrome MCP. Desktop viewport 1440×900 and mobile viewport 390×844.
Overall
PASS. The site is runtime-correct on every surface tested. No runtime 500s on rendered pages (except one /events/[slug] edge case, see FINDING-F). Chrome produced zero console errors/warnings on homepage load after cache refresh. Reduced-motion honoured via a global CSS catch-all. All WEB-AG-5 S3–S7 primary acceptance criteria verified.
Pass tally by surface
| Surface | Status | Key verifications |
|---|---|---|
/ (Home) | ✅ | 9-section slab rhythm intact; PRIDE. three-stop gradient locked (pink→gold→pink); venue capacities 200/70/100; Reviews fallback 4.7/453; Instagram 4 fallback images; 3 marquees at 55s/60s/45s |
/events | ✅ | Empty state clean (no content seeded); 404 page correct on missing routes |
/events/[slug] | ⚠️ | HTTP 500 on invalid slug — should be 404 (FINDING-F) |
| Nav | ✅ | More disclosure ARIA correct (aria-haspopup, aria-controls="more-menu", aria-expanded); Escape closes + focus return; click-outside closes; Tab navigates into menu items |
| Mobile drawer | ✅ | role="dialog", aria-modal="true", body { overflow: hidden } scroll lock, focus moves into drawer, Escape closes + focus return, full unmount after animation |
| Footer | ✅ | meet@ mailto only, no personal phones, 8-colour rainbow band on prideFlow 22s linear infinite |
/cocktail-lounge | ✅ | SUPERBIA. H1, capacity 70, cocktail-ink rgb(11, 17, 32) navy bg, cocktail-cream rgb(243, 233, 214) text, menu “Coming soon” fallback correct |
/functions | ✅ | THROW IT\nHERE. two-line H1, no Packages section (D1 honoured), “SPACE DETAILS COMING SOON” (D6 honoured), 8-field enquiry form incl. honeypot, “Send Enquiry” submit, proper <label for> associations |
/artists | ✅ | ON OUR\nSTAGE. two-line H1, neon blooms present, 12 chips (8 disciplines + 4 experience), chip toggle flips aria-pressed and is mutually exclusive, Instagram-only (no Facebook icon per D8) |
/about | ✅ | BlobHero with shimmer animation (heroShimmer 8s), full rainbow gradient on ABOUT US text, “EST. 2018 · FOOTSCRAY” eyebrow, OUR VALUES (INCLUSION, INDEPENDENCE = 2 blobs), OUR TEAM (4 Staff Member placeholders), PhotoBreak uses drag-white-gown.jpg as CSS background-image |
/contact | ✅ | SAY HELLO H1, 5 topic chips (Say hi default pressed, Book/function, Press & collab, Feedback, Something else), hidden input[name="subject"] updates to chip LABEL (“Book / function”) not key — matches spec exactly, TikTok link present (https://tiktok.com/@prideofourfootscray), only meet@ email, zero phones |
/find-us | ✅ | FIND US H1, Google Maps iframe using hex place-ID 0x6ad76547429ac83b (no new API key), 3 transport cards (Train/Tram/Parking, no bike), Accessibility section with stairs note, “Superbia Cocktail Lounge” wording, no Hours card (hours live in footer) |
/employment | ✅ | Centred “WORK WITH PRIDE” H1 with pride-gradient on PRIDE word (5-stop pink→gold→cyan→purple→pink), mailto:meet@prideofourfootscray.bar CTA, no BlobHero primitive used (correct per S6), Current Openings empty-state copy |
/merch | ⚠️ | Renders cleanly with “No merch live right now. New drop soon.” empty state. H1 “Merch” mixed case inconsistent with rest of site (FINDING-G) |
/404 (missing route) | ✅ | Custom 404 page with “Party not found. Looks like you took a wrong turn at the DJ booth.” copy + “Take Me Home” CTA |
| Reduced motion | ✅ | Global @media (prefers-reduced-motion: reduce) catch-all sets animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important on *, ::before, ::after. All 10 animations on / respect this automatically |
Findings — actionable
FINDING-F (HIGH) — /events/[slug] 500s on missing slug
Observation. GET /events/nonexistent-slug-for-qa returns HTTP 500 (“A server error occurred. Reload to try again.”) instead of HTTP 404. This means any Sanity fetch miss on the event detail route throws to Vercel’s generic error page rather than rendering the custom 404.
Impact. SEO (500s hurt crawl budget), UX (users see Vercel chrome instead of our on-brand 404), resilience (any Sanity issue taking down the slug page).
Fix. In src/app/events/[slug]/page.tsx, call notFound() from next/navigation when getEventBySlug(slug) returns null / undefined, wrapped in proper try/catch so transient Sanity errors don’t 500 either. Write as Claude Code spec WEB-BUG-1.
FINDING-G (MEDIUM) — /merch H1 casing inconsistent
Observation. <h1>Merch</h1> is mixed case. Every other H1 on the site is ALL CAPS (SUPERBIA., THROW IT HERE., SAY HELLO, FIND US, WORK WITH PRIDE, etc.).
Impact. Visual inconsistency — small but jarring if a user lands on merch from a link preview vs. other pages.
Fix. Update MerchStore.tsx or wherever the H1 lives to “MERCH” or “REP THE WEST.” or similar on-brand uppercase. Trivial chore.
FINDING-A (LOW a11y) — No <header> element
Observation. Site nav is a direct child of <body>, not wrapped in a <header> landmark.
Impact. Semantic HTML / landmark navigation for screen readers. Axe probably still passes (nav is a landmark on its own) but WCAG 1.3.1 and common practice favour wrapping site-wide nav in <header>.
Fix. Wrap the global <nav> in src/components/layout/Navigation.tsx inside a <header>. Trivial.
FINDING-B (LOW a11y) — aria-current="page" missing on active nav link
Observation. Home link has its visual-active style (text-primary colour) but no aria-current="page" attribute. usePathname active state is applied visually but not announced to assistive tech.
Impact. Screen readers won’t announce which page the user is on.
Fix. In Navigation.tsx, add aria-current={isActive ? 'page' : undefined} to each link. Trivial.
FINDING-C (INFO) — More disclosure doesn’t have arrow-key cycling
Observation. S3 spec called for arrow-key cycling inside the More dropdown. Actual behaviour: ArrowDown doesn’t move focus into menu items; the pattern relies on Tab.
Impact. None, actually. The pattern implemented is a pure disclosure (aria-haspopup="true" + aria-expanded, no role="menu"), and per WAI-ARIA Authoring Practices, disclosure patterns don’t require arrow-key support — Tab suffices. The S3 spec was over-specified relative to the chosen pattern. Keyboard access is fully functional.
Fix. No action needed. Amend S3 spec retroactively or leave as informational. The claim “arrow-key cycling” should be removed from future spec copies.
FINDING-D (LOW UX) — Hamburger aria-label doesn’t swap
Observation. When mobile drawer is open, the hamburger still has aria-label="Open menu". Should toggle to “Close menu” when aria-expanded="true".
Impact. Screen readers hear stale label when the drawer is open.
Fix. aria-label={isOpen ? 'Close menu' : 'Open menu'} in Navigation.tsx.
FINDING-E (KNOWN) — Footer TikTok chore
Confirmed. Footer has Instagram + Facebook, no TikTok. Contact sidebar has TikTok. Already logged as queue item #7.
FINDING-H (MEDIUM a11y) — Open Stage form inputs lack <label for> association
Observation. OpenStageForm inputs on /artists render visible label text via wrapping divs but inputs have no id, no name, no <label for>, no aria-label, no aria-labelledby. Compare to /functions and /contact forms which use proper <label for> associations.
Impact. Screen readers will announce “edit, blank” without field context.
Fix. Add id + <label htmlFor> or aria-label to every OpenStageForm input. If the form is controlled (React state drives submission, not FormData), the missing name attributes are intentional — but labels are still required for a11y.
FINDING-I (INFO) — About page Team placeholders are text-only
Observation. /about Team section has 4 “Staff Member” h3 placeholders, no <img> tags (About page has zero <img> tags total — PhotoBreak uses CSS background-image).
Impact. When team photos land, they need to be <img> with proper alt attributes. Currently would-be-visual-placeholders are text-only.
Fix. Blocked on content population (item #2 in queue). Once Mat/Emily supply team photos, Anti-gravity or Claude Code adds <img alt> per team member.
FINDING-J (INFO) — Reviews section Google attribution suppressed
Observation. Reviews section renders fallback reviews (Sarah J., Marcus T., etc.) without Google attribution text. S4 spec said attribution is “gated on live placeData” — when we’re on fallback, the gate correctly suppresses.
Impact. None. Working as designed. Worth noting for when Google Places API returns real reviews, the attribution should appear.
Blocked by content population (item #2 in queue)
These runtime checks could not be executed because Sanity has no seeded content:
- EventCard hover lift + sold-out Badge variant=“error” — no events seeded
- EventsList chip filter
aria-pressedtoggle — no events seeded, so no categories derived - Event detail tickets CTA
variant="tickets"active + disabled — no slug routes available - Cocktail menu items — no
menuItemdocs withcategory=="cocktails" - Functions hero capacity populated — no
venueSpacedocs (currently “COMING SOON” fallback) - Artist cards + profile links on
/artists— no artist docs seeded - Functions enquiry form success path — requires server action test w/ Sanity write token
- Contact form submission + 48hr reply expectation — requires Resend env
- Open Stage form submission — requires Sanity writeClient +
SANITY_API_TOKEN - About page team photos — requires Mat/Emily to upload staff images
Deferred not blocked by content
- Safari cross-browser verification — WEB-META-5 candidate, needs Playwright webkit or manual Mac QA. Not run in this pass.
- Lighthouse spot check — S7 baseline stands (/: 100/92/100 mobile). Could rerun but no reason to expect regression from docs-only commit
f66e56a. - AnnouncementBanner dismiss + localStorage persistence — banner is dormant (component exists but not mounted in
layout.tsx). Per session scope decision, not tested.
Recommendations — spec queue
New entries for Claude Code:
- WEB-BUG-1 (HIGH): Fix
/events/[slug]500 → 404 vianotFound()call insrc/app/events/[slug]/page.tsxwith try/catch for Sanity errors. - WEB-A11Y-1 (MEDIUM bundle): Four-in-one a11y cleanup — wrap nav in
<header>, addaria-current="page"to active links, toggle hamburgeraria-labelbased on state, add<label for>/aria-labelto OpenStageForm inputs. - WEB-CHORE-1 (LOW): Merch H1 casing fix + footer TikTok link (combined trivial chore — one commit).
Queue-wise this replaces “Footer TikTok chore” (was #7) with a three-item spec pack. WEB-META-2 lint cleanup and WEB-META-3 CSP hardening remain next after content population.
Related pages
- website
- web-ag-5-qa-findings — S7 Lighthouse + axe baseline this pass builds on
- WEB-META-1 CLAUDE.md level-up — codified rules this pass operates under