Conversation
Add an at-a-glance Overview as the authenticated index route. It answers "is everything OK, and what needs my attention" before an operator drills into a specific page. - System-status strip: a calm one-liner when all clear, otherwise only the problems (unreachable providers, budgets over/near limit, high error rate), each linking to the page that fixes it. - KPI tiles: spend today, spend and request volume over the last 30 days with period-over-period deltas, error rate, budget health, providers healthy, and active keys/users. Status tiles are color plus a word (never hue alone) so they read for colorblind operators. - Recent-activity preview linking to the full request log. Pure frontend: composes existing hooks (usage summary, provider health, usage logs, budgets, keys, users); no backend change. First-run gating stays outside the page so the query fan-out never fires on a fresh gateway with no provider. Budget health reuses the per-user cap math (max_budget * user_count), excluding unlimited and user-less budgets. Shared formatters and the delta helper move into lib/format.ts and components/ui.tsx (consumed by UsagePage too). Trend sparklines and adopting a charting library are tracked in #353. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
WalkthroughChangesThe dashboard now opens on an authenticated overview page with spend, usage, error, provider, budget, key, user, and recent-activity information. Shared formatting and status components were added, sidebar routing was updated, tests expanded, and static dashboard assets regenerated. Dashboard overview
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
… overview The overview surfaced a recent-logs fetch error both in the top-level banner and in the recent-activity block's own banner. Drop it from the top-level aggregate so it reports once. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
# Conflicts: # src/gateway/static/dashboard/assets/index-BkBGW75P.js # src/gateway/static/dashboard/index.html
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/gateway/static/dashboard/assets/index-CMrAhRSl.css (1)
1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winLint the source CSS, not this generated bundle.
Stylelint reports many duplicate declarations and generated-browser-compatibility patterns in this minified artifact. Please exclude
src/gateway/static/dashboard/from source Stylelint rules and validateweb/srcinstead; do not hand-edit the bundle, since rebuilding will overwrite it.As per coding guidelines, regenerate and commit dashboard assets after source changes.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/gateway/static/dashboard/assets/index-CMrAhRSl.css` at line 1, Exclude src/gateway/static/dashboard/ from Stylelint’s source lint targets and configure validation to run against web/src instead. Do not edit the generated dashboard bundle manually; after applying source changes, rebuild the dashboard assets and commit the regenerated output.Sources: Coding guidelines, Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/gateway/static/dashboard/assets/index-CMrAhRSl.css`:
- Line 1: Exclude src/gateway/static/dashboard/ from Stylelint’s source lint
targets and configure validation to run against web/src instead. Do not edit the
generated dashboard bundle manually; after applying source changes, rebuild the
dashboard assets and commit the regenerated output.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 8024e707-c01c-40e6-8f4d-6fcb8f9e0cde
📒 Files selected for processing (14)
src/gateway/static/dashboard/assets/index-C6QL6228.jssrc/gateway/static/dashboard/assets/index-CFHe63sp.jssrc/gateway/static/dashboard/assets/index-CMrAhRSl.csssrc/gateway/static/dashboard/assets/index-DeR1bneA.csssrc/gateway/static/dashboard/index.htmlweb/src/App.tsxweb/src/components/AppShell.tsxweb/src/components/ui.tsxweb/src/lib/format.tsweb/src/lib/overview.test.tsweb/src/lib/overview.tsweb/src/pages/OverviewPage.test.tsxweb/src/pages/OverviewPage.tsxweb/src/pages/UsagePage.tsx
Making Overview the index route means the landing page now has tile-links
whose accessible names substring-collide with sidebar items ("Providers
healthy", "Active users", "No budgets configured"). Scope the nav link
lookups to the navigation landmark so getByRole("link", { name }) stays
unambiguous on the overview.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a new authenticated dashboard landing page (“Overview”) that surfaces spend, traffic, and health signals at a glance, and refactors shared formatting/UI helpers to support it.
Changes:
- Introduces
OverviewIndex(index-route gating) andOverviewPage(status strip, KPI tiles, recent activity preview) with unit tests. - Consolidates shared formatting and delta helpers into
web/src/lib/format.ts, and extendsStatCardto support status pills and whole-tile navigation. - Updates sidebar navigation to add an “Overview” item and fixes active-link behavior for the index route; adjusts Playwright selectors to avoid link-name collisions on the new page.
Reviewed changes
Copilot reviewed 11 out of 15 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| web/src/pages/UsagePage.tsx | Switches to shared formatUsd/formatTokens/formatPct/deltaFraction and shared DeltaHint. |
| web/src/pages/OverviewPage.tsx | Adds the new Overview index + page UI (tiles, status strip, recent activity). |
| web/src/pages/OverviewPage.test.tsx | Adds component-level tests for Overview rendering, strip behavior, and index redirect gating. |
| web/src/lib/overview.ts | Implements derived “health” grading helpers for error rate, provider reachability, and budgets. |
| web/src/lib/overview.test.ts | Adds unit tests for the overview health grading helpers. |
| web/src/lib/format.ts | Adds shared aggregate-format helpers (formatUsd, formatTokens, formatPct, deltaFraction). |
| web/src/components/ui.tsx | Enhances StatCard with status accents/pills and optional whole-card navigation; centralizes DeltaHint. |
| web/src/components/AppShell.tsx | Adds “Overview” sidebar item and supports NavLink end on the index route. |
| web/src/App.tsx | Makes Overview the authenticated index route via OverviewIndex. |
| web/e2e/dashboard.spec.ts | Scopes navigation link lookups to the sidebar landmark to avoid ambiguity on the Overview page. |
| src/gateway/static/dashboard/index.html | Updates dashboard asset hashes for the rebuilt frontend bundle. |
khaledosman
left a comment
There was a problem hiding this comment.
Review by Claude Code (driven by @khaled).
Solid change. Verified: query keys are genuinely stable (windows frozen, no Date.now() in render, no refetch loop), first-run gating fans out queries only after a provider is confirmed, budget math (cap * user_count, excluding unlimited/user-less) matches the Budgets page and is well tested, per-tile isolation means one failing query does not blank the page, and accessibility is disciplined (status always pairs color with a word/glyph). Bundle rebuilt and committed as required.
No blockers. Inline: two minors worth attention (overnight staleness, all-clear-during-load) plus a token nit. Also:
- No e2e assertion of the Overview page itself:
dashboard.spec.tsonly rescopes nav link lookups; nothing navigates to the new index route and asserts the strip/tiles render. Component coverage is strong so this is minor. formatUsdnow hardcodesen-USwhereUsagePage's oldusdCompactused browser locale (Intl.NumberFormat(undefined, ...)). Behavior change for non-US locales, but consistent with the rest offormat.ts. Flagging so it is an intentional call.
Verdict: approve-with-nits.
- Status strip no longer claims "All systems normal" while any source query is loading or has failed; it shows a neutral line instead, so it never contradicts the error banner. The all-clear budget phrase now reflects the real state (e.g. "No budgets configured") instead of always "within limit". - KPI tiles gate on data presence, not isLoading, so a failed query reads as "—" (unknown) rather than a misleading $0.00 / 0/0 real zero. - Window bounds advance when the tab is refocused on a new local day, so a tab left open overnight stops aggregating yesterday, while staying stable within a day to keep query keys steady. - Add format.test.ts coverage for the shared primitives (deltaFraction guards, formatUsd, formatTokens boundaries, formatPct). - Document emerald as the sanctioned healthy/success status color alongside red/amber in the frontend design-token guidance. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@web/src/lib/format.test.ts`:
- Around line 31-42: Update formatTokens so values that round to 1000.0k, such
as 999_999, promote to the million format and display as 1.0M. Revise the
corresponding formatTokens test expectation while preserving existing formatting
for values below that rounded boundary.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 6e14ae68-f960-4d4a-96a6-d84d80ece778
📒 Files selected for processing (8)
.github/skills/frontend-standards/SKILL.md.github/skills/frontend-standards/design-tokens.mdsrc/gateway/static/dashboard/assets/index-BnmiwDLj.jssrc/gateway/static/dashboard/index.htmlweb/e2e/dashboard.spec.tsweb/src/lib/format.test.tsweb/src/pages/OverviewPage.test.tsxweb/src/pages/OverviewPage.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
- src/gateway/static/dashboard/index.html
- web/src/pages/OverviewPage.test.tsx
- web/src/pages/OverviewPage.tsx
| describe("formatTokens", () => { | ||
| it("compacts at the k and M boundaries", () => { | ||
| expect(formatTokens(512)).toBe("512"); | ||
| expect(formatTokens(999)).toBe("999"); | ||
| expect(formatTokens(1000)).toBe("1.0k"); | ||
| expect(formatTokens(84_200)).toBe("84.2k"); | ||
| expect(formatTokens(999_999)).toBe("1000.0k"); | ||
| expect(formatTokens(1_000_000)).toBe("1.0M"); | ||
| expect(formatTokens(12_400_000)).toBe("12.4M"); | ||
| }); | ||
| }); | ||
|
|
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Promote rounded values at the million boundary.
Line 37 locks in 1000.0k for 999_999 tokens. Since these values are displayed in aggregate KPI tiles, this should likely promote to 1.0M after rounding rather than show an awkward 1000.0k; adjust formatTokens and this expectation accordingly.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@web/src/lib/format.test.ts` around lines 31 - 42, Update formatTokens so
values that round to 1000.0k, such as 999_999, promote to the million format and
display as 1.0M. Revise the corresponding formatTokens test expectation while
preserving existing formatting for values below that rounded boundary.
khaledosman
left a comment
There was a problem hiding this comment.
Follow-up by Claude Code (driven by @khaled). Re-reviewed fix(dashboard): address overview review feedback against the earlier review; all points resolved:
- Stale windows:
useWindowsnow keys offlocalDayKey()and advances onvisibilitychange/focus, held stable within a day so query keys don't churn. Sound. - All-clear-during-load/error:
ready/failedprops gate the strip,NeutralStripuses--otari-*tokens, and the all-clear budget phrase reflects real state viacappedCount. Tiles now gate on data presence rather thanisLoading, so a failed query reads as "—" instead of a misleading real zero (nice extra). format.test.tsadded, covering thedeltaFractiondivide-by-zero / undefined guards andformatTokensboundaries.- Emerald documented as a sanctioned healthy/success status color in
design-tokens.mdandSKILL.md.
Nothing outstanding. LGTM.
Description
Adds an at-a-glance Overview as the authenticated index route. It answers "is everything OK, and what needs my attention" before an operator drills into a specific page. Part of #299.
endso it does not stay highlighted on every route.Design notes:
OverviewIndex), so a fresh gateway with no provider configured redirects to Providers without ever firing the overview's query fan-out.max_budget * user_count), excluding unlimited and user-less budgets, matching the Budgets page.formatUsd,formatTokens,formatPct,deltaFraction) andDeltaHintmoved intolib/format.tsandcomponents/ui.tsx;UsagePagenow consumes them instead of local copies.Trend sparklines on the tiles and adopting a charting library are out of scope, tracked in #353 (also retires the hand-rolled
UsageChart).PR Type
Relevant issues
Closes #302
Checklist
web/src/pages/OverviewPage.test.tsx,web/src/lib/overview.test.ts).npm --prefix web run typecheck,npm --prefix web test(168 passing), andnpm --prefix web run build. No Python was touched.AI Usage
AI Model/Tool used: Claude Code (Opus 4.8), driven by @njbrake. The plan was reviewed via an autoplan pass (CEO, design, eng) before implementation; the budget math, unstable-query, and accessibility fixes came from that review.
Any additional AI details you'd like to share: All decisions and direction are @njbrake's; the code and prose were generated by Claude.
Summary
Benefits
Operators can now assess gateway health and usage at a glance, while first-time users are directed to provider setup. Shared formatting and expanded tests improve consistency and reliability.