A "finished" AI-generated CRM.
12 problems the founder couldn't see.
LeadFlow is a typical vibe-coded app: looks done in a screenshot, falls apart in the first real session. Below is the full rescue - audit, triage, repair - exactly the process I run on client projects.
Data truly persists; storage layer is a 2-function seam for a real backend
No secrets in the client; deterministic fit scoring
Race-free state updates, validated forms, honest UI
CSV export actually exports
10 focused files, thin 100-line App shell
The 12 findings
Triaged the way I quote real rescues: blockers first (the client sees these), traps second (the client can't see these - that's what they pay for), debt last.
Blocker Fake persistence: all data in React state, "Synced to database" toast unconditional, POST to a dead URL swallowed by an empty catch.
Blocker Race conditions: every mutation wrapped in setTimeout over stale state - fast actions silently lose writes; duplicate ids break React keys.
Blocker Forms accept garbage: empty names, $NaN deal values that corrupt totals.
Trap OpenAI API key hardcoded in the client bundle - extractable by any visitor in devtools.
Trap .env with a Supabase service_role key committed to git, no .gitignore.
Trap Fake auth: any credentials log in, "admin123" hardcoded in the bundle, delete button hidden in UI only.
Trap Empty catch blocks and zero loading states - every failure is a silent frozen UI.
Trap README promises Supabase sync, RBAC, CSV export, mobile support - none exist.
Debt No viewport meta, fixed 1200px layout, 3-column grid with min-width cards: broken below 900px.
Debt Dead buttons: Export CSV, Bulk Email, Settings rendered with empty handlers.
Debt 1101-line single component: all state, both modals, data layer and styling in one file, plus two dead Button components.
Debt 343 KB bundle: moment + lodash + axios + uuid imported for one date format and two sums; console.log noise (including a partial API key) in production.
Measured, not claimed
Numbers from the build, not adjectives.
MetricBeforeAfter Data survives refreshNoYes Secrets in client bundle2 keys0 Bundle size (gzip)343 KB (114)155 KB (50) Runtime dependencies62 (react, react-dom) Largest component1101 lines~150 lines Buttons that do nothing30 Usable at 380pxNoYes
The method
Same four phases on every rescue - because the visible bug is never the only bug.
Have an app that's "90% done" for three months?
This rescue took ~5 hours end to end. The first step is always a fixed-price audit - you get this exact report for your codebase, whether or not we continue.
Full audit: AUDIT.md · Decisions: DECISIONS.md · Commit history tells the story, one fix per commit · Nikita, frontend developer - GitHub @niki-deone