BUILD · COMMAND CENTER
One dashboard, zero invented numbers
Group-level marketing means every brand's paid, organic, Business Profile and review data living somewhere different. Command Center is the system I built to pull all of it into one local-first workspace, assembled from the platform APIs, cached overnight by a scheduled runner, and read by models running on my own machine.
Personal build, ongoing since 2026. Runs daily on a MacBook Air. A 15-packet build programme closed in September 2026.
- 1
- dashboard for every brand in the group
- 25
- playbooks in the runner, 20 on a schedule
- 469
- unit tests, all green at the last full run
- 0
- fabricated figures, by design


Why I built it
Reporting across a multi-brand portfolio is mostly assembly work: the same exports, the same joins, the same spreadsheet, every week. Worse, opening a workspace meant waiting on six third-party APIs to answer live, which made 'just check the numbers' a two-minute stall instead of a glance. So I built the assembly once, properly: one endpoint that fans out to every source concurrently and returns a single contract, a nightly job that pre-fetches it so the morning read is instant, and a launcher that puts every tool one keystroke away.
How it works
A boot sequence leads into a hub, and the hub opens workspaces. The data path underneath is deliberately thin: routes orchestrate, libraries do the work, and every mapper is its own testable file: GA4 sessions and revenue, Meta and Google Ads spend with status chips, UTM-derived sources and campaigns, Business Profile metrics, Business Profile reviews (a separate export with its own brand resolver), and organic social. Those sources now sit behind ports. A metrics source is an interface with a conformance test, and Windsor.ai, a CSV file and a direct GA4 client are three implementations of it, so a client brand can be pointed at its own accounts without touching the code that reads them. A CRM source is the second port, and credentials are isolated per brand rather than shared through one set of environment variables. Once a day a snapshot flattens the whole payload to one file per day, which is what the sparklines read from: real history, accumulated, rather than a trend line inferred from a single point. A separate 'Nexus' screen pulls AI and industry feeds, reads my task board out of my notes vault, runs honest health probes against each dependency, and drafts a morning brief grounded only on those lines.
What's inside it
Brands dashboard: the group performance view, with sparklines off the snapshot history, and a weekly per-brand report drafted by a model and checked line by line against the numbers it cites before it can be saved. Reviews reader: Business Profile reviews across every location, on demand rather than on every page load, because reviews are a slow-moving twelve-month window and shouldn't cost a refresh. Nexus: feeds, focus, dependency health, the grounded morning brief, and mail triage across Google and Microsoft accounts, classified by a local model and never acted on without a click. Paperlens: a fully local RAG tool for PDFs, images and transcripts (its own build, below). It doubles as the brand asset brain: every ingested image carries an asset type set by a human at ingest and a caption confidence derived from how legible the file actually was, never a model's opinion of itself. Council: six models across four providers debating a question, with a chairman that synthesises and a budget guard that keeps a real ledger so free tiers stay free tiers. Agentic runner: 25 playbooks, 20 of them on a schedule. The original set covers cache warming, WooCommerce ingest, the daily snapshot, anomaly detection against the snapshot baseline, GEO citation tracking, competitor watch, and dependency and model radar. The September 2026 wave added weekly reports, a daily standup and digest delivered as an unsent Gmail draft, voice memos and screenshots transcribed on-device straight into the notes vault, menu and price consistency diffs against the live site, a booking-funnel monitor, content briefs drafted from real GEO citation gaps, alt-text drafts for site and EDM images, and a brand-intake run that chains BWPE, the Ad Readiness Audit and GEO tracking into one note a proposal drafter can read. Every price in that proposal is left blank for me to fill in by hand. BWPE Studio and the Ad Readiness card: front ends for two sibling builds (below), plus a UTM builder, a reading queue that files articles into the vault under its real tag taxonomy, and a vertical-pack wizard for onboarding a brand that isn't in F&B. Agent Town: every Claude Code session, scheduled job and local model service on the machine rendered as a voxel town on a hex platform, one cat per agent. Anything not backed by a real signal on disk is labelled decor.
Fifteen packets in five days
Between 11 and 15 September 2026 the system went through a numbered build programme against an 80-item catalogue, run from a sibling control repo with an inventory, a licence register and a resumable state file, so a fresh session could pick up mid-programme without re-deriving context. The inventory came first. Every catalogue item was marked build, extend, skip or defer against what already existed, with the reason written down; about a third were skipped, merged or deferred because the repo already had a better version or the prerequisite didn't exist yet. The rest landed as packets. A trust layer: structural guardrails at the model gateway, a semantic cache, and a refusal-rate metric on the golden evals. A local-only switch with a fallback ladder from on-device models to cloud, and a card that shows which model is resident. The adapter ports above. A degradation drill that deliberately breaks the safe-to-break adapters and the model ladder, and asserts each one fails honestly instead of returning a plausible zero. A tier comparison that runs the same golden cases through the local and cloud rungs side by side. Every packet closed with the live proof written down: the real command, the real output, and what was explicitly not done. Two real bugs surfaced that way and were fixed the same day, including a test file that had been silently running the entire eval suite as an import side effect since it was written.
The rules it's built on
Never fabricate. A missing figure is an omitted key and an empty state, never a zero that looks like a real measurement. Health checks stay grey when they can't be verified rather than going green on a guess. Cached is not live. Every cached figure carries its real fetch timestamp and stale data says so on the screen. A cached number presented as live is a fabricated number. A failed refresh must never blank the dashboard. A playbook that fails fails loudly in its own run record and leaves the last good cache intact. Scheduling is done by the OS, not the app, so jobs still fire with the dev server down and catch up on wake instead of silently skipping a closed lid. Credentials are referenced by environment-variable name from config; the values never enter a JSON file that could end up in a screenshot. Nothing publishes. Every write path is a draft: an unsent email, an appended note in the vault, a proposal with the prices left blank. No card that ingests a stranger's text holds a publish capability, and the one approval gate that could authorise a write has been built and has never fired.
What it proves
That I can specify a data system, build it, and then operate it, including the unglamorous parts: brand-routing rules that survive campaign renames, a snapshot key format that has to stay byte-identical or the history breaks, and the discipline to write down every place reality deviated from the spec instead of quietly patching over it. And that I can run a programme against it: an 80-item catalogue triaged honestly, fifteen packets shipped with live proof, and a licence register that says which parts are mine to sell and which are my employer's data to hand back. The marketing value is simpler. I know exactly what my numbers are made of, because I built the thing that assembles them.
Stack