4.3 KiB
Web UI architecture
This document explains the redesigned built-in browser UI served by the gateway.
Source file:
src/gateway/web-ui.ts
Overview
The web UI is still served from GET /, but now uses a reusable app shell:
- shared header + sidebar layout
- responsive navigation (desktop sidebar + mobile sheet)
- shadcn-style design tokens and component primitives
- light/dark theme toggle with persisted preference
- chat + conversations + API guide views
The gateway API contract is unchanged. Chat requests still use /v1/chat/stream.
App shell and routes
The page is a small client-side multi-view app with three route panels:
#/chat(default)#/conversations#/api
Routing is hash-based and keeps the shell consistent across views:
- Sidebar: primary navigation/actions
- Top header: current page title, status badge, theme toggle, mobile menu trigger
- Main content: route panel content
Shared shell behavior
- Desktop (
>960px): sidebar is always visible - Mobile (
<=960px): sidebar is replaced with a sheet/drawer opened from header - Escape key and backdrop click close the mobile sheet
UI primitives and design tokens
The redesigned UI follows shadcn-style structure and naming:
- card surfaces
- buttons (
default,secondary,outline,ghost) - inputs and textarea
- badge/status pill
- separator
- sheet/drawer-style mobile nav
Design tokens are centralized as CSS variables on :root and overridden for dark mode via [data-theme="dark"].
Key token families:
--background,--foreground--card,--card-foreground--primary,--secondary,--accent--muted,--muted-foreground--border,--input,--ring- sidebar-specific tokens
Theme system (light/dark)
Behavior
- Initial theme defaults to system preference (
prefers-color-scheme) if no saved preference exists. - User can toggle theme from the header button.
- Selected theme is persisted in
localStorageunder:pi_gateway_theme
- Theme applies by setting:
document.documentElement.dataset.themedocument.documentElement.style.colorScheme
Persistence and system changes
- If user has explicitly chosen a theme, that preference wins.
- If no explicit preference exists, system theme changes are applied live.
Chat view
The Chat panel contains:
- Session settings card
- Conversation ID input (
#conversationId) - optional bearer token input (
#token) - new session and refresh conversations actions
- Conversation ID input (
- Messages card
- streaming message log (
#messages) - clear visible messages action
- streaming message log (
- Composer card
- prompt textarea (
#message) - send action (
#send) - keyboard shortcut hint
- prompt textarea (
Streaming behavior
- Sends
POST /v1/chat/stream - Parses SSE incrementally
- Handles key events:
assistant_text_deltaassistant_thinking_deltatool_startdoneerror
- Saves
conversationIdfromdoneinto:- input field
- localStorage key
pi_gateway_conversation_id
Conversations view
The Conversations panel reads GET /v1/conversations and renders:
- conversation id
- created/updated timestamps
- loaded/streaming indicators
Per-conversation actions:
- Use in chat: sets
#conversationId, persists it, routes back to chat - Delete: calls
DELETE /v1/conversations/:id
API guide view
A lightweight route that summarizes core gateway endpoints used by adapters and the web UI:
/v1/chat/stream/v1/chat/v1/conversations/v1/adapters/chat/stream
Accessibility notes
The redesigned UI includes:
- keyboard-focus-visible styles using
--ring - semantic regions (
nav,header,main,section) aria-currenton active nav item- mobile sheet dialog semantics (
role="dialog",aria-modal="true") - message log with
role="log"+aria-live="polite" - keyboard send shortcut (
Cmd/Ctrl + Enter)
Availability and auth
The route is controlled by GATEWAY_ENABLE_WEB_UI:
true(default):GET /serves UIfalse:GET /returns404with{ "error": "Web UI disabled" }
If GATEWAY_AUTH_TOKEN is set, auth is still global, so GET / also requires bearer auth.
Storage keys used by the UI
pi_gateway_conversation_idpi_gateway_theme
Related docs
docs/gateway.mddocs/channels.md