I had a dashboard with 14 marketing integrations. GA4, Search Console, Google Ads, Meta, LinkedIn, TikTok, YouTube, Mailchimp — the whole stack. Users could connect any of them. OAuth worked. Badges turned green. "Active."
One of them actually did anything.
I didn't know this. The UI looked right. Green dots across the board. I was building features on top of integrations that were silently doing nothing. I asked Claude to audit the entire codebase against the product vision. Not fix bugs. Tell me what's real.
The Dispatch
MeetKai is an AI CMO product I was building. Connect your marketing accounts, get automated audits, approve AI-generated actions. Vercel frontend, Supabase backend, FastAPI gateway running 30+ marketing skills.
I wrote a dispatch prompt:
Me: go # MeetKai Dashboard — Full Gap Analysis
Date: 2026-04-05
Purpose: Dispatch prompt for an agent to audit the entire MeetKai dashboard codebase against the product vision, identify every gap, and produce a prioritized work list.
I expected a bug list. Missing error handling, broken API routes. Normal stuff.
Claude went through every file in the repo. The gap analysis landed in a spec doc. It was not a bug list.
25% Done
Claude: Overall: 25-30% complete. Here's the brutal truth:
- 1 of 14 providers actually works (GA4). GSC is broken by a one-line provider name mismatch. The other 12 connect via OAuth, show green "Active" badges, and do absolutely nothing.
- Action execution is theater — static markdown templates with
[Business Name]placeholders, not real AI output- The notification toggles save preferences but have no delivery infrastructure
Thirteen integrations showing green badges. Users clicking "Sync" on provider cards where the button had no onClick handler. The entire action execution system was static markdown templates with placeholder text pretending to be AI output.
The GSC integration — Google Search Console, one of the two most important data sources for the product — was dead because of a single string mismatch between what the frontend sent and what the backend expected. One typo. The whole integration was a corpse with a green badge.
This wasn't a half-built prototype that looked half-built. It looked finished. Polished design. OAuth flows completing successfully. Connected status showing in the UI. You'd think everything was working and wonder why the data was empty.
A feature that errors out gets caught in testing. A feature that succeeds and does nothing — that ships to production. It erodes trust for months before anyone figures it out.
Shell and Weapon
Then Claude dropped this:
Claude: Here's what we're actually sitting on: a Next.js dashboard that's 25% done bolted onto a gateway + agent + content engine that's 70% done. The frontend is a shell. The backend is a weapon. They're barely talking to each other.
I had to sit with that for a minute. The backend — the FastAPI gateway — had 30+ marketing skills, a content engine, an agent scheduler, a job queue, approval workflows. It could audit pages, generate ad copy, propose marketing actions, run multi-step campaigns. All of it was built and working.
The frontend didn't know any of it existed.
I'd been thinking about this as a bug-fix problem. Fix the 14 providers. Wire up the notifications. Make the action buttons work. But that framing was wrong. The real problem was architectural. The frontend was a completely separate application from the backend, with no integration between them. Fixing individual features would take months and still leave two disconnected systems.
Three Options, One Obvious Answer
Claude laid out the architecture choices:
Claude: The core architectural question is: how should the dashboard talk to the Kai brain?
- A) Direct integration — The Next.js app imports the Python content engine directly (requires a bridge or rewrite)
- B) Gateway-first — The dashboard becomes a frontend for the existing FastAPI gateway
- C) Hybrid + CopilotKit — Gateway for structured operations + CopilotKit for chat
Option A means rewriting the Python backend in JavaScript or building a bridge layer. A month of work to solve a problem nobody has.
Option C adds CopilotKit as a dependency for a chat feature the Vercel AI SDK already handles natively. More framework, more complexity, same result.
We went with B. The dashboard becomes a thin frontend for the gateway. Every button click, every chat message, every scheduled task routes through the same API. The gateway has the skills. The dashboard calls them.
Your frontend should be a client for your backend. Not a parallel implementation. Not an abstraction layer. A client. I've watched three projects in the past month where teams rebuilt backend logic in the frontend "for performance" and ended up maintaining two versions of the same thing.
Who Opens This at 9am
Next was the interaction model.
Claude: What's the user's primary interaction model?
- A) Dashboard-first, chat-assists — Widgets, cards, tables. Chat slides out as a helper.
- B) Chat-first, dashboard-monitors — The chat IS the product. Dashboard pages become monitoring.
My instinct was chat-first. Feels more "AI native." Talk to your marketing agent, it does things. That's the pitch.
Then I thought about who actually opens this. Small business owners. They open an app at 9am. They want a number. Is marketing working? What needs attention? What did the AI do overnight? They want answers on screen, not a blinking cursor waiting for a prompt.
Claude: Business owners don't care about the interface paradigm. They care about "is my marketing working and what should I do next."
Dashboard-first, chat-second. The dashboard loads with answers. Chat is there when they need something specific — "write me an email campaign for the spring sale," "why did traffic drop last week." Chat is an input surface. Not the product.
Get this decision wrong and you're rewriting your frontend in three months. Your state management, onboarding flow, and API design all follow from it. We almost went chat-first because it sounded cooler.
The Smallest Thing Worth Charging For
The gap analysis showed 14 providers, 30+ skills, analytics, audits, content engine, agent scheduler. Six months of work if you're not careful.
Claude: What's the launch slice — the smallest version a business owner would pay for?
The killer loop is: Connect → Audit → See what's wrong → AI fixes it → See it get better
Five things make the cut:
- Fix GA4 + GSC, add 2-3 more working providers
- Auto-run audit when accounts connect
- Show scores, issues, and AI fixes in the dashboard
- Chat to trigger skills
- Real action execution through the gateway
Everything else waits. Ten remaining providers. Advanced analytics. The agent scheduler. Scope for later. The loop — connect, audit, act, approve — is enough to charge money for.
Here's what the final architecture looks like:
TRIGGERS BRAIN OUTPUT
───────────────── ────────────────── ────────
Click "Run Audit" → → Audit result
Chat: "write emails" → Skill Router + Gateway → Email drafts
Cron: daily 6am → (same execution path) → Analytics brief
Webhook: score drop → → Action proposal
Chat isn't special here. It's one of five input surfaces into the same brain. Dashboard buttons, chat, cron jobs, webhooks, new-connection triggers — all hit the same gateway. Same skills. Same approval flow.
I spent weeks building features on top of integrations that didn't work. Every one of those features was wasted time. The audit took one session. I should have run it before I wrote a single line of new code.
The thing I keep coming back to is the green badges. Thirteen of them. All lying. Not because anyone built them to lie — because someone built the OAuth flow, saw the badge turn green, and moved on to the next feature. Nobody went back and checked whether the data was actually flowing. The UI said it worked. That was enough.
It wasn't enough. Run the audit first. Read the code, not the interface.
What's the worst thing a codebase audit turned up for you — not a bug, but something that looked like it was working and wasn't?
Top comments (0)