/docs.
What it is
A single-page-feel Next.js App Router application underfrontend/ — 119 files, all client-rendered behind an auth gate. It holds no state of its own: it authenticates against POST /users/login, stores the bearer token in browser localStorage (frontend/src/lib/auth-storage.ts), and every screen is a view onto an API call.
Because it is a browser client, it can do one thing the API alone cannot: place a live microphone call to a websocket agent through the runtime. See Browser test calls.
Status
The API knows about the dashboard in exactly one place:
FRONTEND_URL (default http://localhost:3000) is used to build password-reset links in apps/api/app/services/user_service.py. Nothing else in the core stack depends on it.
frontend/README.md is unmodified create-next-app boilerplate. Ignore it — the behaviour described on these pages comes from the source files.The stack
All versions are from
frontend/package.json. There is no state-management library, no data-fetching library, and no component framework: fetches go through a single apiFetch helper and state is plain React hooks.
What it talks to
Two services, over two protocols. Next.js serves the pages and proxies both REST (/api/v1/* → API_PROXY_TARGET) and browser test-call WebSockets (/agent/... → RUNTIME_PROXY_TARGET). frontend/src/lib/api/http.ts calls same-origin /api/v1, and frontend/src/lib/pipecat/createBrowserClient.ts opens a same-origin WebSocket that Next forwards to the runtime.
API surfaces it consumes
Every request is built infrontend/src/lib/api-client.ts or frontend/src/lib/api/*.ts. Paths below are relative to the API base, which defaults to http://localhost:8000/api/v1.
Recordings and transcripts come back as blobs rather than JSON, because
<audio src> cannot send an Authorization header — apiFetchBlob fetches them with the bearer token and the UI builds an object URL.
frontend/src/lib/api-types.ts holds the TypeScript shapes for all of the above; it is the frontend’s copy of the API contract, not a generated client.
When to use it instead of the API
Treat the dashboard as a convenience layer for exploration and one-off setup. Production operations belong on the API.