Skip to content

feat(dashboard): overview / home page (#302) - #354

Merged
njbrake merged 5 commits into
mainfrom
homepage
Jul 22, 2026
Merged

feat(dashboard): overview / home page (#302)#354
njbrake merged 5 commits into
mainfrom
homepage

Conversation

@njbrake

@njbrake njbrake commented Jul 22, 2026

Copy link
Copy Markdown
Member

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.

  • System-status strip. A calm one-liner when all clear ("All systems normal, N/N providers healthy, budgets within limit"), otherwise only the problems (unreachable providers, budgets over or 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, active keys, active users. Status tiles pair color with a word (Healthy, Elevated, Over budget, Degraded), never hue alone, so they read for colorblind operators.
  • Recent-activity preview linking to the full request log.
  • Sidebar gets a header-less "Overview" lead item; its NavLink uses end so it does not stay highlighted on every route.

Design notes:

  • Pure frontend. Composes existing hooks (usage summary, provider health, usage logs, budgets, keys, users). No backend change, no new endpoint, no migration.
  • First-run gating stays outside the page (OverviewIndex), so a fresh gateway with no provider configured redirects to Providers without ever firing the overview's query fan-out.
  • Budget health reuses the per-user cap math (max_budget * user_count), excluding unlimited and user-less budgets, matching the Budgets page.
  • Date windows are frozen once (stable query keys, no refetch loop); "Today" is local midnight so the operator's wall-clock day is what the server aggregates.
  • Shared formatters (formatUsd, formatTokens, formatPct, deltaFraction) and DeltaHint moved into lib/format.ts and components/ui.tsx; UsagePage now 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

  • New Feature
  • Bug Fix
  • Refactor
  • Documentation
  • Infrastructure / CI

Relevant issues

Closes #302

Checklist

  • I understand the code I am submitting.
  • I have added or updated tests that cover my change (21 new frontend tests: web/src/pages/OverviewPage.test.tsx, web/src/lib/overview.test.ts).
  • I ran the Definition of Done checks locally. This is a frontend-only change, so the relevant checks are the web ones: npm --prefix web run typecheck, npm --prefix web test (168 passing), and npm --prefix web run build. No Python was touched.
  • Documentation was updated where necessary (no user-facing docs changes needed).
  • If the API contract changed, I regenerated the OpenAPI spec. Not applicable: no API surface changed.

AI Usage

  • No AI was used.
  • AI was used for drafting/refactoring.
  • This is fully AI-generated.

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.

  • I am an AI Agent filling out this form (check box if true)

Summary

  • Added an authenticated Overview dashboard as the home page, with KPIs for spending, requests, errors, budgets, providers, API keys, and users.
  • Added provider, budget, and error-rate status messaging with links to relevant dashboard sections.
  • Added a recent-activity preview linking to the full request log.
  • Updated sidebar navigation to make Overview the leading route and improved active-link handling.
  • Added first-run routing to Providers when no provider is configured.
  • Added shared formatting utilities for currency, tokens, percentages, and period deltas, reused by Usage and Overview.
  • Added comprehensive unit and page tests, refreshed date ranges on tab refocus, and improved error/loading-state handling.
  • Updated generated dashboard assets and frontend status-color guidance.

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.

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>
@github-actions github-actions Bot added the missing-template PR is missing required template sections label Jul 22, 2026
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Changes

The 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

Layer / File(s) Summary
Overview metrics and shared UI
web/src/lib/overview.ts, web/src/lib/format.ts, web/src/components/ui.tsx, web/src/pages/UsagePage.tsx, web/src/lib/*.test.ts, .github/skills/frontend-standards/*
Health calculations, shared formatters, status-aware stat cards, delta hints, usage-page integration, and related tests/documentation are added.
Overview page and validation
web/src/pages/OverviewPage.tsx, web/src/pages/OverviewPage.test.tsx
The overview fetches summary data, renders status strips and tiles, shows recent activity, handles loading/errors, and validates routing and UI states.
Index route and sidebar navigation
web/src/App.tsx, web/src/components/AppShell.tsx, web/e2e/dashboard.spec.ts
The authenticated index renders OverviewIndex, a home navigation item uses exact matching, and dashboard e2e navigation queries are scoped to the sidebar.
Dashboard build artifacts
src/gateway/static/dashboard/index.html, src/gateway/static/dashboard/assets/*
Hashed JavaScript and CSS bundles are added, and index.html references the regenerated assets.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested reviewers: khaledosman

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title is relevant, but it uses feat(dashboard): instead of the required feat: Conventional Commit prefix. Change it to a required prefix like feat: overview/home page (#302) and keep it concise.
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description follows the template and includes the required sections, summary, issue link, checklist, and AI usage details.
Linked Issues check ✅ Passed The PR implements #302’s authenticated overview page, KPIs, provider health, recent activity, and index-route behavior.
Out of Scope Changes check ✅ Passed The extra changes are supporting implementation, tests, docs, and build assets that align with the overview/home-page scope.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch homepage
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch homepage

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai
coderabbitai Bot requested a review from khaledosman July 22, 2026 01:11
njbrake and others added 2 commits July 22, 2026 01:14
… 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
@njbrake
njbrake temporarily deployed to integration-tests July 22, 2026 01:15 — with GitHub Actions Inactive
@github-actions github-actions Bot removed the missing-template PR is missing required template sections label Jul 22, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/gateway/static/dashboard/assets/index-CMrAhRSl.css (1)

1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Lint 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 validate web/src instead; 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

📥 Commits

Reviewing files that changed from the base of the PR and between 632b68a and a625c9d.

📒 Files selected for processing (14)
  • src/gateway/static/dashboard/assets/index-C6QL6228.js
  • src/gateway/static/dashboard/assets/index-CFHe63sp.js
  • src/gateway/static/dashboard/assets/index-CMrAhRSl.css
  • src/gateway/static/dashboard/assets/index-DeR1bneA.css
  • src/gateway/static/dashboard/index.html
  • web/src/App.tsx
  • web/src/components/AppShell.tsx
  • web/src/components/ui.tsx
  • web/src/lib/format.ts
  • web/src/lib/overview.test.ts
  • web/src/lib/overview.ts
  • web/src/pages/OverviewPage.test.tsx
  • web/src/pages/OverviewPage.tsx
  • web/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>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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) and OverviewPage (status strip, KPI tiles, recent activity preview) with unit tests.
  • Consolidates shared formatting and delta helpers into web/src/lib/format.ts, and extends StatCard to 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.

Comment thread web/src/pages/OverviewPage.tsx Outdated
Comment thread web/src/pages/OverviewPage.tsx Outdated
Comment thread web/src/pages/OverviewPage.tsx
Comment thread web/src/pages/OverviewPage.tsx

@khaledosman khaledosman left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.ts only 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.
  • formatUsd now hardcodes en-US where UsagePage's old usdCompact used browser locale (Intl.NumberFormat(undefined, ...)). Behavior change for non-US locales, but consistent with the rest of format.ts. Flagging so it is an intentional call.

Verdict: approve-with-nits.

Comment thread web/src/pages/OverviewPage.tsx
Comment thread web/src/pages/OverviewPage.tsx
Comment thread web/src/pages/OverviewPage.tsx
Comment thread web/src/lib/format.ts
- 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>
@njbrake
njbrake temporarily deployed to integration-tests July 22, 2026 09:53 — with GitHub Actions Inactive
@coderabbitai
coderabbitai Bot requested a review from khaledosman July 22, 2026 09:53
@njbrake
njbrake merged commit 150b2b1 into main Jul 22, 2026
10 checks passed
@njbrake
njbrake deleted the homepage branch July 22, 2026 09:56

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between a625c9d and 01bce4b.

📒 Files selected for processing (8)
  • .github/skills/frontend-standards/SKILL.md
  • .github/skills/frontend-standards/design-tokens.md
  • src/gateway/static/dashboard/assets/index-BnmiwDLj.js
  • src/gateway/static/dashboard/index.html
  • web/e2e/dashboard.spec.ts
  • web/src/lib/format.test.ts
  • web/src/pages/OverviewPage.test.tsx
  • web/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

Comment on lines +31 to +42
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");
});
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 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 khaledosman left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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: useWindows now keys off localDayKey() and advances on visibilitychange/focus, held stable within a day so query keys don't churn. Sound.
  • All-clear-during-load/error: ready/failed props gate the strip, NeutralStrip uses --otari-* tokens, and the all-clear budget phrase reflects real state via cappedCount. Tiles now gate on data presence rather than isLoading, so a failed query reads as "—" instead of a misleading real zero (nice extra).
  • format.test.ts added, covering the deltaFraction divide-by-zero / undefined guards and formatTokens boundaries.
  • Emerald documented as a sanctioned healthy/success status color in design-tokens.md and SKILL.md.

Nothing outstanding. LGTM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dashboard: overview / home page

3 participants