* feat(ui): full frontend redesign to the Sentry-style design system
Replace the legacy UI with the dark, mono-accent design language from
design/23-sentry.html across every non-canvas surface.
- PlatformShell: fixed 252px sidebar with grouped nav (Platform /
Operate / Workspace), brand mark, user card, and a topbar with
search (Cmd+K palette), env badge, upgrade, notifications, and
theme toggle; mobile collapses to a top bar with horizontal nav
- New shared component kit in shared/components/sentry.tsx:
SPageHead, SStat, SCard, STable, SSection, SPill, Ticks, Seg,
GhostBtn/QuietBtn/IconBtn, status tone helpers
- New DashboardPage at / — stats row, per-node CPU chart with
1h/24h/7d ranges, resource usage tick strips, anomaly box,
node summary table, recent deployments and project cards;
real API data with demo-mode fixtures
- Landing page moved to /landing and rebuilt: live host telemetry
window, install strip, feature grid, template catalog, docs
- Every page (Projects, Templates, Builds, Databases, HA,
Operations, Activity, Security, Usage, Docs, People, Settings,
Audit Logs, Webhooks, Admin, NodeDetail, ServiceDetail, auth,
setup, not-found) migrated to the new kit and tokens
- Nav active state resolves by longest matching href
- Canvas internals intentionally untouched — separate pass
Verified: tsc --noEmit, eslint, vite build, Playwright walkthrough
of every route at desktop and mobile widths (demo + live session).
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(ui): deep audit pass — palette navigation, crash fix, honest badges
- CommandPalette: full route navigation, project deep-links fetched on
open, Create group only where onAddService is wired, dead Connect
items removed, decorative kbd hints dropped; workspace passes its own
view targets
- NodeDetailPage crash: container status arrives as a Docker state
object, not a string — flattened in listAgentContainers and guarded
at render for persisted-cache payloads
- env badge reflects import.meta.env.MODE instead of hardcoded
'production'
- Relative times capped: >1y or future timestamps render 'n/a'/'—'
(zero-time heartbeats no longer show 739898d ago)
- Post-auth and setup redirects land on / (dashboard is the index)
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(ui): use SPageHead actions prop, satisfy tsc -b literal types
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
---------
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Found during a browser-driven audit of the whole app:
- connectivity banner showed permanently: pingServer() resolved
undefined, which React Query treats as an error; returns boolean now
- Vite dev proxy now forwards /health so the probe actually measures
the backend, and the API target is env-overridable (VITE_API_PROXY)
- auth-session removed from the persisted query cache — stale sessions
no longer rehydrate into a false signed-in flash
- workspace Observability tab no longer shows fabricated random metrics
("87K Active User", fake performance/speed-test cards); the dashboard
now aggregates real per-service metrics (CPU, memory, network, instances)
- service detail tabs write ?section= so tab state is shareable/deep-linked
- Security page auto-selects the first project instead of rendering blank
- People page user-creation form no longer overflows its card
(minmax(0,1fr) grid tracks; same fix on env-var rows)
- page padding is responsive (px-4 sm:px-8) so mobile keeps content width;
Projects header wraps instead of clipping the "+ new project" button
- template deploy modal shows a loading state while the session resolves
instead of flashing the sign-in prompt
- audit log table strips the CIDR suffix from displayed IPs
- docs list excerpts no longer repeat the document title
- activity filter placeholder "Search search…" → "Search events…"
- workspace view tabs get more room: ⌘K button now waits for lg:
Generated with [Devin](https://devin.ai)
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
GET /api/v1/operations aggregates active deployments, per-service
deploy-queue depth via Queue.Snapshot(), 24h deployment failures,
cron runs and backups scoped to the caller's projects (admins see all).
Frontend /operations page (Operate nav) shows in-flight count, queued
depth, failures and backup stats with live refetch while deploys are
active. CLI `containr operations` + MCP containr_operations_get.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>