Operator dashboard for the LoopGain telemetry receiver. React + TypeScript + Vite, ~71 KB gzipped, fully client-side.
Live at dashboard.loopgain.ai (hosted) or self-host alongside the receiver — Apache-2.0.
- Overview — fleet
Aβ_medianring gauge, five-band counts, 30-day savings hero, 24h pulse, KPI quad, recent runs feed. - Loop Health Map — squarified treemap of recent events, band-colored, filterable by workload or band, with cluster-anomaly detection.
- Convergence Profiles — per-event
profile_medianover time with band-threshold backgrounds and rolling-median trend. - Waste Report — saved-dollars hero, counterfactual baseline, by-workload + by-outcome breakdowns, stacked-area spend timeseries.
- Gain Margin Distribution — fleet histogram of
GM = 1 / max(Aβ_smooth)with reference markers at 1.0 / 1.2 / 1.8, per-bucket drill-in. - Rollback Log — every divergence-triggered rollback as an expandable audit-trail row; CSV / JSON export with on-the-fly SHA-256 audit hash.
- ETA Accuracy — predicted-vs-actual iteration calibration scatter, fed by
/v1/calibration(requires library schema-v2 capture). - Alerts — read-only delivery audit log + active-rule summary; rule editing lives in Settings.
Plus a Loop Detail drill-down per workload (header KPIs, per-workload convergence chart, recent runs sidebar, per-iteration trajectory scrubbing for v3-schema runs), Settings (connection state, cost-per-iter, alert rules editor), an Empty State with a three-line Python integration snippet, and a ⌘K command palette for nav / actions / workload jumps.
A filter bar across the top of every data panel scopes by framework, loop_type, and team (populated from the receiver's distinct-values list).
The dashboard supports light & dark themes, cozy / dense density, and a demo mode that runs the whole UI against a deterministic synthetic fleet — useful for screenshots and offline development.
[browser] --bearer-auth--> [telemetry-receiver Worker] --D1--> [loop_events, alert_rules, alert_deliveries]
│
├── GET /v1/stats
├── GET /v1/profiles
├── GET /v1/events
├── GET /v1/event/:id
├── GET /v1/calibration
├── GET /v1/alerts/rules
├── GET /v1/alerts/deliveries
└── POST/PUT/DELETE /v1/alerts/rules[/:id]
Fully client-side. The user's bearer token lives in localStorage and is sent only to the configured endpoint. No backend, no cookies, no third-party scripts, no telemetry of its own.
- React 18 + TypeScript (strict mode).
- Vite (
vite build→dist/). - Hand-built SVG charts. Zero charting-library dependencies.
- Design tokens + a small component layer. No CSS framework.
src/
├── App.tsx routing, theme/density, keybindings, polling
├── main.tsx entry
├── styles/ tokens.css + base.css + components.css
├── types.ts wire shapes mirroring the receiver
├── lib/
│ ├── api.ts typed fetch client + AuthContext + useApi hook
│ ├── data-hooks.ts useStats / useProfiles / useEvents / useCalibration / useAlert*
│ ├── demo.ts deterministic synthetic telemetry
│ ├── bands.ts band semantics, outcome→band mapping
│ ├── stats.ts percentile, histogram, groupBy helpers
│ └── format.ts display formatters
└── components/
├── primitives/ StatePill, Chip, KPI, Tooltip, PanelHeader, Icon
├── charts/ SVG chart components
├── shell/ Sidebar, TopBar, FilterBar, CommandPalette, routes
├── auth/ ConnectDialog
└── panels/ one file per route
npm install
npm run dev # http://localhost:5173
npm run build # tsc --noEmit && vite build → dist/
npm run preview # serve dist/ on :4173
npm run typecheckOn first load with no configured endpoint, the dashboard shows the empty state. Click Use demo data to explore against the synthetic fleet, or Connect endpoint to paste your receiver URL + bearer token.
Connected to Cloudflare via Git (Workers with static assets) — pushing to main auto-deploys. Production custom domain: dashboard.loopgain.ai.
Cloudflare runs npm run build (which is tsc --noEmit && vite build) and then npx wrangler deploy. wrangler.jsonc declares dist/ as the asset directory and enables SPA fallback. .nvmrc pins Node 22 so the build env matches local.
One-off manual deploy:
npm run build
npx wrangler deployTLS is automatic on Cloudflare-managed custom domains. public/_headers carries CSP / HSTS / X-Frame-Options.
- The endpoint URL of your telemetry receiver (e.g.,
https://telemetry.loopgain.ai). - A bearer token from the receiver operator — see the receiver README.
On first load the dashboard shows a connect prompt. Paste both; they're stored in localStorage and reused. To rotate or disconnect: log-out icon in the top bar, or Settings → Connection → Disconnect.
Both the receiver and the dashboard are Apache-2.0:
- Deploy the telemetry-receiver to your Cloudflare account.
- Deploy this dashboard to Cloudflare (or any static host).
- Issue a token with the receiver's
scripts/issue-token.mjs. - Point the library's
send_telemetry(endpoint=...)at your receiver. - Open the dashboard, paste endpoint + token.
Nothing leaves your infrastructure.