Built for the Customer Success team at beehiiv
CSM Mission Control
What on my book needs me today, and why?
An operational dashboard for a customer success team. It replaced a weekly ritual of stitching together Metabase tabs, HubSpot views and Zendesk searches with one screen per account.
Runs on fictional data. No sign-in or account needed, and nothing you change is saved.

- 122k
- lines of TypeScript
- 133
- API routes
- 26
- engines
- 18
- scheduled workflows
The problem
A CSM covering around 40 enterprise accounts had the data but not the picture. Utilization lived in Metabase, renewal dates and risk notes in HubSpot, support load in Zendesk, deliverability in ClickHouse, feature requests in Linear, and the actual conversations in Gmail.
Answering “which accounts are quietly going sideways?” meant half a morning of tab-switching, done inconsistently, and usually only once something had already gone wrong. The dashboard's job is to make that question cheap enough to ask every day.
What it does
The Workspace shows one account at a time: only the blocks that are true today, with every absent check named underneath, so a short screen means “nothing else is wrong” rather than “something didn't load.”
Behind it, an at-risk engine scores a book of business against eight weighted flags and explains each result. Renewal sweeps fire at 90, 60, 30 and 7 days with drafted outreach, deliverability alerts come off a ClickHouse rollup, and a request loop tracks feature requests from intake through to “live in app” and back to the customer.
A committed snapshot, not live queries
Every page reads from an AES-256-GCM encrypted snapshot committed to the repo and refreshed twice a day. The source query takes 20–40 seconds; a dashboard that runs it per page view is a dashboard nobody opens twice.
Committing the data makes the read path a file decrypt: single-digit milliseconds, identical in dev and prod. The tradeoff is data up to twelve hours old, which the header states plainly instead of hiding.
One mapping choke point
Raw rows become typed Customer objects in exactly one function. When an upstream schema change silently broke every Stripe and HubSpot deep link, a single column fallback in that mapper restored them for 592 of 598 accounts on the next sync.
Engines as pure functions
An engine takes customers plus options and returns a plain report. It doesn't know whether it's being rendered, posted to Slack by a cron, or dumped to stdout — which is why the same at-risk engine backs a dashboard tab, a CLI and a nightly sweep without a branch anywhere in it.

