# Full-Stack Demo Acceptance Matrix This matrix defines what “demo release ready” means for milestone #5. It ties the product promise to end-to-end behaviour, backend rules, frontend states, and QA evidence so a reviewer can validate the build without guessing what success looks like. ## Release target The milestone is accepted when a local or deployed demo user can: 1. open the Fan Passport web app; 2. view seeded World Cup 2026 teams, matches, stadiums, trivia, predictions, challenges, badges, and leaderboard data; 3. collect passport items; 4. answer trivia; 5. submit predictions; 6. unlock achievements through the gamification engine; 7. complete challenges through normal actions; 8. see XP and leaderboard movement reflected in the UI; 9. recover gracefully from empty, repeated, invalid, and failed actions. ## Acceptance matrix | Area | Required behaviour | Automated coverage | Manual QA pass criteria | Edge cases to verify | | --- | --- | --- | --- | --- | | App boot | Web app renders against a running API and shows the primary passport/dashboard experience. | `tests/e2e/demo.spec.ts`; `apps/web/src/__tests__/App.test.tsx`; optional `node scripts/qa/http-smoke.mjs`. | First load shows a meaningful heading, data-backed cards, and no console-blocking runtime error. | API unavailable, slow API, empty collections. | | API boot | Backend exposes a usable demo API, seeded content, and a health/status path for deployment smoke checks. | `apps/api/src/__tests__/passport.integration.test.ts`; optional HTTP smoke health check. | API responds locally before the frontend is opened; invalid requests return structured errors. | Missing environment values, unknown IDs, malformed JSON. | | Collect teams | User can collect a team such as England and see the team appear in passport progress. | API integration tests for collection mutation and challenge progress; E2E flow exercises collection UI. | XP increases once; the collected item becomes visibly owned; repeating the same collect action is idempotent and does not inflate XP. | Duplicate collect, unknown team ID, simultaneous double click. | | Collect matches | User can collect/watch a match and have challenge progress update. | Gamification integration test plus E2E happy path. | Match card changes state and related challenges update without requiring refresh. | Already watched match, match from unknown stage/group. | | Collect stadiums | User can collect stadiums toward the stadium completion challenge. | Backend challenge catalogue and store tests; frontend E2E interaction. | Stadium collection count increments and completion badge unlocks when threshold is met. | Duplicate stadium, all stadiums already collected, no stadiums seeded. | | Trivia | User can answer a World Cup trivia question and receive immediate correctness feedback. | API tests for correct/incorrect/repeated answer scoring; frontend unit loading and interaction checks. | Correct answer awards XP; incorrect answer records participation; repeated question does not double-award completion XP. | Missing answer, invalid option, question already answered, daily trivia unavailable. | | Predictions | User can submit a match prediction, including upset/giant-killing style predictions. | API integration test for prediction mutation and achievement evaluation; E2E prediction form. | Submitted prediction appears in the passport; challenge progress updates; editing or resubmitting has clear rules and no duplicate XP exploit. | Invalid team, impossible score, duplicate prediction, locked prediction window. | | Badges | Badges unlock from real actions, not from static UI state. | `apps/api/src/gamification.ts` covered through integration tests. | Newly unlocked badges are announced visually and remain visible after refresh/reload. | Badge already unlocked, multiple badges unlocked by one action, no badges yet. | | Challenges | Challenge progress responds to collections, trivia, and predictions. | API gamification tests and E2E complete-a-challenge path. | Progress bars/counts are understandable; completed challenge shows completed state and reward. | Progress over max threshold, challenge with no eligible content, repeated action. | | Leaderboard | User XP changes are reflected in leaderboard ranking. | API integration tests for XP/ranking; E2E validates visible movement. | Demo user moves after earning XP; ties have deterministic ordering; empty leaderboard has a friendly state. | Tie ranks, zero-XP user, many users, same user duplicated. | | Loading states | Frontend shows loading indicators while API requests are pending. | React unit tests should assert initial/loading render; E2E can throttle network manually. | No blank screen; controls that mutate state prevent accidental duplicate submissions while pending. | Slow first load, slow mutation, refresh during pending request. | | Empty states | Frontend explains what to do when no items are collected or no leaderboard entries exist. | Unit tests cover initial empty passport render. | Empty copy offers a next action; empty does not look broken. | New user, reset store, filtered lists with no results. | | Error states | API and network failures surface user-friendly messages. | API tests assert structured errors; frontend tests assert error alert/banner behaviour. | User sees retryable error copy; developer console does not fill with unhandled promise rejections. | API down, 500, 404 unknown ID, validation failure, timeout. | | Accessibility | Core flows are keyboard and screen-reader friendly. | `apps/web/src/__tests__/App.test.tsx`; optional `node scripts/qa/a11y-static-check.mjs`; Playwright role locators in E2E. | Keyboard can complete collection, trivia, and prediction flows; focus remains visible; status updates are announced. | Small screen, reduced motion, high contrast, repeated alerts. | | Responsive | Demo works on mobile, tablet, and desktop widths. | Playwright config can run projects/viewports; manual responsive checklist in QA docs. | No horizontal scrolling at 375px; leaderboard/cards remain usable; form controls have touch-friendly targets. | Long team names, long stadium names, narrow viewport, landscape mobile. | | Release docs | A public reviewer can run, test, and deploy the demo from repository docs. | README commands, deployment doc, release checklist, this matrix. | A clean checkout can install dependencies, start API/web, run tests, and follow the demo script. | Missing env file, stale lockfile, port conflict, CORS base URL mismatch. | ## Evidence expected before public update For a public crowdfunding update, capture the following evidence from a clean machine or fresh container: - install command completed successfully; - API test suite completed successfully; - web unit test suite completed successfully; - Playwright E2E demo suite completed successfully; - at least one screenshot each of: - initial dashboard, - successful collection, - trivia answer result, - prediction submitted, - badge/challenge completed, - leaderboard after XP movement, - mobile viewport; - optional smoke output from: - `node scripts/qa/http-smoke.mjs --api --web `; - `node scripts/qa/a11y-static-check.mjs`. ## Release decision rule The demo can be published when: - all automated tests pass in a clean install; - no critical accessibility findings remain from automated or manual review; - core flows complete without page refreshes; - repeated actions do not create XP or badge exploits; - deployment URLs and CORS/API base settings are documented for the chosen host; - the demo script can be performed in under ten minutes by someone who did not build the app.