ISSUE 02
LIVETypeScriptClaude APIHubSpotGong
CONTEXT
Freshpaint's revenue data is complete and nearly unusable.Deals live in HubSpot, call transcripts live in Gong, and competitive context lives on the open web, but none of them answer the questions the business actually asks: are we on pace this quarter, how much pipeline is left to find, and what did buyers say they wanted.Every answer meant a manual CRM pull, a spreadsheet, and hours of reading transcripts, and two people picking two definitions of the same word produced numbers that couldn't be reconciled.
BUILD
One Node/TypeScript and React service on a single Fly.io machine with no database: in-process cron jobs compute dashboard snapshots to JSON on a volume, and the routes serve the files.Every document-producing call pairs a prompt builder with a Zod schema, and a response that fails validation goes back to Claude once with the error before the call gives up.Models are picked per call, so routine transcript summarization runs on Haiku and only judgment-heavy work reaches Opus, with the shared account context prompt-cached across nine parallel section calls.The account-plan pipeline fans out across HubSpot, Gong, web research, and ad libraries, streams progress over SSE, and repairs the generated org chart in code rather than trusting the model with tree structure.The metric definitions got as much work as the model calls: pace against a prorated goal instead of raw attainment, coverage against the quota still to find, and report totals that throw rather than ship if they don't reconcile.Every integration is read-only, so nothing the system infers can touch the CRM.
RESULT
Live on Fly.io behind Google sign-in restricted to Freshpaint.Sales, account management, marketing, and field each get a view shaped for their decision off one data spine, the CRO briefing regenerates four times every weekday, and an account plan that used to take hours of transcript reading now takes about a minute.
SCREENSHOTS