All checks were successful
Build and Push Docker Image / build (pull_request) Successful in 1m18s
183 lines
4.3 KiB
Markdown
183 lines
4.3 KiB
Markdown
# 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 `localStorage` under:
|
|
- `pi_gateway_theme`
|
|
- Theme applies by setting:
|
|
- `document.documentElement.dataset.theme`
|
|
- `document.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:
|
|
|
|
1. **Session settings card**
|
|
- Conversation ID input (`#conversationId`)
|
|
- optional bearer token input (`#token`)
|
|
- new session and refresh conversations actions
|
|
2. **Messages card**
|
|
- streaming message log (`#messages`)
|
|
- clear visible messages action
|
|
3. **Composer card**
|
|
- prompt textarea (`#message`)
|
|
- send action (`#send`)
|
|
- keyboard shortcut hint
|
|
|
|
### Streaming behavior
|
|
|
|
- Sends `POST /v1/chat/stream`
|
|
- Parses SSE incrementally
|
|
- Handles key events:
|
|
- `assistant_text_delta`
|
|
- `assistant_thinking_delta`
|
|
- `tool_start`
|
|
- `done`
|
|
- `error`
|
|
- Saves `conversationId` from `done` into:
|
|
- 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-current` on 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 UI
|
|
- `false`: `GET /` returns `404` with `{ "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_id`
|
|
- `pi_gateway_theme`
|
|
|
|
---
|
|
|
|
## Related docs
|
|
|
|
- `docs/gateway.md`
|
|
- `docs/channels.md`
|