Source: /Users/mkazi/Tools/_shared/audits/MK-QuizFlow.json (Agent A, evidence-based, spot-checked by Agent B on 2026-07-17).
Legacy stack: React 18.3 SPA + Vite 6 + Tailwind v4 + zustand 5, ~2,930 lines, optional (dead) Express server.
A client-side BYOK (bring-your-own OpenRouter key) tool: extract text from an uploaded PDF in the browser with pdf.js, send it to OpenRouter, render an interactive MCQ quiz with preview/edit, scoring, history, share-by-URL, and JSON export/import. All data in localStorage. An Express file-storage backend exists in server/ but is unused and undeployed.
Build: PASS (tsc + vite, 4.05 s; 793 kB single JS bundle, no code splitting). Tests: 13/13 pass but largely hollow (see below).
| Finding | Evidence |
|---|---|
| Stats tracking never wired — tiles show permanent zeros | useStatsStore actions have zero call sites outside the store |
| “Regenerate” button silently discards the quiz | QuizGenerator.tsx:394-400 calls handleCancelPreview |
| SPA deep links 404 in production | live check: /history returns HTTP 404; vercel.json lacks SPA fallback |
| Progress bar is simulated | setInterval + Math.random()*15 capped at 90% |
| Entire backend is dead | backendService server functions never imported; Express app never deployed |
| Tests are hollow | expect(true).toBe(true); store test tests a re-implemented mock; coverage excludes nearly all app code |
.env.example advertises vars no code reads |
only VITE_API_URL is referenced |
| GitHub nav link points at the wrong repo | App.tsx:64 → 37-PDF-to-Quiz-Generator |
| README is template inflation | fake “100/100” badges, nonexistent Gitleaks step, wrong live URLs; docs/FEATURES.md is literal placeholder text |
deploy-vercel.yml uses a nonexistent action |
vercel/action-deploy@v1 |
| Footer says v1.0.0, package.json says 2.2.0 | version drift |
Math.random() for quiz/question IDs (not auth-relevant; still not collision-safe).JSON.parsed with no schema validation — malformed payloads crash the quiz view.DELETE /api/data, open CORS, no rate limit, no body limits, logs full request bodies..env committed._legacy_reference/, gitignored)src/services/aiService.ts — PDF extraction loop, fetchWithRetry, prompt + JSON contractsrc/types/quiz.ts — clean domain modelsrc/components/QuizGenerator.tsx — preview-and-prune flow, keyboard nav, feedback/scoring UX (to be decomposed)backendService.ts, quizStore.ts)quizStore.ts, settings.ts, stats.ts — stats as a reference for what v2 must actually wire up)src/index.css) — evolved, not copied, into the v2 design systempublic/favicon.svg, firebase.json header set, useAudio.ts tone synthExplicitly NOT ported: server/ Express app, dist-server/, the 36-file docs/ marketing filler, all 8 legacy GitHub workflows, the 5-platform deployment config sprawl.
crypto.randomUUID() for all IDs.Decision. All five products in this program rebuild on Next.js (App Router, src/, TypeScript strict, Tailwind v4), even where an audit recommended keeping the existing client-only stack.
Rationale. The product spec requires server-rendered public content hubs (guides/use-cases at scale), serverless AI routes (/api/ai/* behind the Vercel AI Gateway, so users don’t have to paste keys into localStorage), and SEO (per-route metadata, sitemap, JSON-LD) that a client-only SPA cannot satisfy. Uniform stack also lets the orchestrator share CI, security headers, and deployment handling across the five squads.
The audit’s own recommendation, recorded honestly. For this repo, Agent A recommended migration conditionally: “as a single BYOK client tool, the current Vite SPA is fine and the cheapest production path is a two-line vercel.json rewrite fix. Migration is justified by the stated product direction, not the current code. … If scope stays ‘one small client tool’, do NOT migrate — just fix the rewrite.” The orchestrator’s product direction (content hub + serverless AI + SEO) is exactly the expansion case the audit conditioned on, so for QuizFlow the audit and the ADR converge; the dissent that migration is unnecessary for the current scope stands recorded. This ADR will be restated in ARCHITECTURE.md.
Consequences. ~1 day migration cost (audit estimate); kills the 5-platform config sprawl; AI calls move server-side; the legacy SPA deep-link 404 class of bug disappears with file-system routing.