The Web UI is the analytical interface for ratelord. While the TUI handles real-time operations, the Web UI focuses on historical analysis, scenario simulation, and broad-scale monitoring.
Core Mission: Answer "Why did this happen?" and "What if we change X?" using deep temporal context.
Key Distinctions:
- Time Horizon: Historical (days/weeks) vs. TUI's Real-time (minutes).
- Interaction: Deep drill-down and simulation vs. TUI's observation.
- Write Access: Read-only (except local simulation configs).
We enforce a strict, modern stack to ensure maintainability and performance.
- Language: TypeScript
- Framework: React 18+
- Build Tool: Vite
- Styling: Tailwind CSS (Utility-first)
- Routing: React Router v6
- State/Fetching: TanStack Query (React Query)
- Visualization: Recharts (for time-series), React Flow (for node graphs - optional but recommended for Identity Explorer)
- Icons: Lucide React
The Web UI is a Single Page Application (SPA) designed to be embedded directly into the ratelord-d binary.
- Source:
web/directory in the repo root. - Build:
npm run buildgenerates static assets (HTML, CSS, JS) intoweb/dist. - Embedding:
- Go server uses
//go:embedto bundleweb/distinto the binary. - A generic HTTP handler serves
index.htmlfor all non-API routes (SPA fallback) to support client-side routing.
- Go server uses
web/
├── src/
│ ├── components/ # Shared atomic components (Button, Card, Badge)
│ ├── features/ # Feature-specific modules (dashboard, simulation)
│ │ ├── components/ # Feature-scoped components
│ │ ├── hooks/ # Feature-scoped data hooks
│ │ └── types.ts # Feature-scoped types
│ ├── hooks/ # Global hooks (useTheme, useEventStream)
│ ├── layouts/ # Page layouts (AppShell)
│ ├── lib/ # Utilities (api client, formatters)
│ ├── pages/ # Route entry points
│ ├── App.tsx # Root component + Providers
│ └── main.tsx # Entry point
├── index.html
├── tailwind.config.js
├── tsconfig.json
└── vite.config.ts
The URL is the source of truth for navigation state to enable deep-linking.
| Route | View | Description |
|---|---|---|
/ |
Dashboard | High-level metrics, health summary, and recent alerts. |
/history |
History | Event log explorer with time-range filtering. |
/identities |
Explorer | Hierarchical view of Agents, Scopes, and Pools. |
/cluster |
Cluster | Federation topology and node status. |
/simulate |
Scenario Lab | "What-if" analysis sandbox. |
/settings |
Settings | Local UI preferences (theme, refresh rate). |
Query Parameters:
- All views involving time must respect
?from=<ts>&to=<ts>params. - Views involving filters must respect
?agent=<id>&scope=<id>.
- SidebarNavigation: Collapsible main nav.
- GlobalHeader: Breadcrumbs, connection status indicator (Daemon: Online/Offline), theme toggle.
- MainContent: Router outlet.
- MetricGrid: Grid of
MetricCardcomponents (Current Usage, Burn Rate, Violations). - BurnRateChart: Recharts
AreaChartshowing usage vs limits over time. - RecentAlertsFeed: Condensed list of recent
denyorthrottleevents.
- TimeRangePicker: Specialized control for selecting absolute or relative windows (Last 1h, Last 7d).
- EventTimeline: Visual scrubber/minimap of event density.
- EventList: Virtualized list of raw events.
- EventDetailPanel: Slide-over or modal showing full JSON payload of a selected event.
- SimulationConfig: Form to set baseline time range and modifiers (multiplier, limit changes).
- SimulationRunner: "Run" button + progress indicator.
- ComparisonView: Split view showing
ActualvsSimulatedoutcomes.
- Purpose: Visualize the hierarchical relationship between Agents, Scopes, and Pools.
- Data Transformation: The API (
GET /v1/identities) returns a flat list of identities. The UI must reconstruct the hierarchy client-side:- Roots: Identities with no parent are root nodes (typically Agents).
- Children: Identities where
parent_idmatches a root become children (Scopes). - Leaves: Deepest level nodes are typically Pools.
- Visualizer:
- TreeTable: Primary view. A collapsible table where rows can be expanded to show children.
- Columns:
- ID: The identity identifier (e.g.,
agent:foo). - Kind: Icon/Badge indicating Agent, Scope, or Pool.
- Current Usage: Sparkline or progress bar (if usage data is linked).
- Last Active: Relative timestamp (e.g., "2m ago").
- ID: The identity identifier (e.g.,
- Interaction: Clicking a row navigates to
/historyfiltered by that identity ID.
- Purpose: Visualize the federation topology and node health.
- Data Source:
GET /v1/cluster/nodes. - Visualizer:
- Node Table: List of all nodes (Leader, Followers).
- Columns:
- Node ID: Unique identifier.
- Role: Leader / Follower.
- Status: Active / Offline (based on heartbeat).
- Last Seen: Timestamp.
- Network Graph (Future): Visual graph of leader-follower connections.
- Pattern: We treat the Daemon as the source of truth.
- Caching: Aggressive caching for historical data (immutable).
- Live Data:
- Polling: Default mechanism (e.g., every 5s) for dashboard metrics.
- Invalidation:
refetchOnWindowFocusenabled to ensure freshness.
- Minimal client-only state:
- Theme (Dark/Light)
- Sidebar collapsed/expanded
- Active simulation configuration (draft)
The UI consumes the REST API defined in API_SPEC.md.
- Client: Typed
fetchwrapper (oraxios) handling base URL configuration. - Error Handling: Global toast notifications for API failures.
- Types: TypeScript interfaces generated from or manually synced with Go structs in
DATA_MODEL.md.
- Dark Mode First: The UI should default to dark mode to match the CLI experience.
- Information Density: Use "sparklines" and compact tables. Avoid excessive whitespace.
- Feedback: Every action (especially simulation runs) must provide immediate visual feedback (loading skeletons, spinners).
- Zero Configuration: The UI must work out-of-the-box when the daemon starts.
- Auth: If the daemon enforces auth, the UI client must intercept 401s and redirect to a login prompt or generic "Unauthorized" state.
- Sanitization: All user input (filters, simulation params) must be sanitized before sending to API, though the API is the ultimate gatekeeper.