# 05 — Web App (Next.js) Map
> Surface: `apps/web`
> Stack: Next.js 15 App Router + React 19 + MUI (via `@d3ro/ui`) + Supabase
> Role: cloud console; the reference surface for server-shared data UX
---
## 1. Route tree (`src/app/`)
Root layout: `ThemeProvider → I18nProvider → AuthProvider`.
| Route | Type | Feature |
|---|---|---|
| `/` | server | Redirects: session → `/dashboard`, else `/login` (also `/login` when Supabase unconfigured) |
| `/login` | client | OAuth (Google/GitHub/Apple) + email/password |
| `/accept-invite` | client | Team invite acceptance (`?token=` → `team-accept`); stores pending token if logged out |
| `/download` | client | Download center + release history; desktop installers marked "release pending"; client SHA-256 verify tool |
| `/releases` | server | Re-exports `/download` |
| `/auth/callback` | route handler | OAuth code → session exchange |
| `(app)/record` | server | `` real-time record/STT |
| `(app)/commands` | client | Custom instruction CRUD/reorder/activate/execute |
| `(app)/dashboard` | client | Stats (sessions, time, words, streak), tier, recent history |
| `(app)/actions` | server | NL command → LLM parse → action (``) |
| `(app)/meetings` | server | Meetings list |
| `(app)/meetings/[id]` | server | Meeting detail: audio player, live transcript (Realtime), memos, generated docs |
| `(app)/knowledge` | server | RAG doc list + add + semantic search (search "planned V2-M+1") |
| `(app)/teams` | server | Teams list + create |
| `(app)/teams/[id]` | server | Team detail: members, owner-only invite, team meetings |
| `(app)/chat` | server | Talk AI chat (``) |
| `(app)/dictionary` | client | Pronunciation dictionary CRUD |
| `(app)/history` | client | History list: search, favorites, pagination, copy/delete |
| `(app)/history/[id]` | client | History detail: edit title/original/polished, favorite, delete |
| `(app)/billing` | client | Plans + Payple/Stripe checkout, manage/portal |
`(app)/layout.tsx` is the auth guard + shared ``.
---
## 2. Components (`src/components/`)
| Group | Components |
|---|---|
| `actions/` | `action-runner.tsx` (LLM parse → action: create_meeting/search_knowledge/create_memo/send_team_invite) |
| `record/` | `mic-recorder.tsx` (MediaRecorder + level analyser → `transcribeWebAudio`) |
| `dashboard/` | `meetings-trend-chart.tsx` (recharts) |
| `billing/` | `billing-checkout-options`, `checkout-button` (Stripe), `payple-checkout-button`, `payple-client`, `payple-manage-button`, `portal-button` |
| `meetings/` | `document-editor`, `generate-document-button`, `live-transcript-list` (Realtime), `markdown-preview` (Mermaid), `meeting-audio-player` (signed URL), `memo-form` |
| `chat/` | `chat-panel.tsx` |
| `teams/` | `create-team-form`, `invite-member-form`, `activity-feed` (team notes + realtime) |
| `knowledge/` | `add-knowledge-form` (text or `.txt`/`.md` file, newline-aware chunking, `embed-chunks` on submit), `knowledge-search` (semantic via `search-knowledge`) |
| `layout/` | `sidebar.tsx` (nav, theme selector, logout, i18n) |
| `providers/` | `auth-provider`, `i18n-provider`, `theme-mode-context`, `theme-provider` |
---
## 3. Clients (`src/lib/`)
| File | Purpose |
|---|---|
| `billing-catalog.ts` | Parse/validate billing catalog (schema v1, pro/pro_plus, Payple/Stripe prices) |
| `command-client.ts` | Custom instruction client (types, error codes, execute) |
| `dashboard-client.ts` | Dashboard snapshot loader |
| `dictionary-client.ts` | Dictionary CRUD/pagination/search + `serializeDictionary` / `parseDictionaryFile` / `importDictionaryFile` (JSON/CSV) |
| `history-client.ts` | History list/get/update/delete, revision-safe |
| `supabase-browser.ts` | Re-export `@d3ro/api-client/supabase-browser` |
| `supabase-server.ts` | Next `cookies()` wrapper |
| `web-stt-client.ts` | Web STT via `stt-proxy`, 25 MB limit, `WebSttError` codes |
---
## 4. Tests
Playwright specs in `apps/web/e2e/`: billing, payple-checkout, dashboard-dictionary-commands, history, web-stt-client, smoke.
---
## 5. Web status summary
- Full App Router console: auth (email + OAuth), record/STT, history (list+detail), commands, actions, meetings (list+detail+docs), knowledge (add+search), teams (list+detail+invite), chat, dictionary, billing, download/releases.
- Backed by Supabase tables + Edge Functions (`stt-proxy`, `llm-proxy`, `team-invite`, `team-accept`, `stripe-checkout`, `payple-checkout`, `payple-manage`, `search-knowledge`, `generate-meeting-document`).
- No literal `TODO`/`FIXME` markers; remaining smaller items (see [`11-gap-backlog.md`](./11-gap-backlog.md) `WEB-*`):
- Teams `member_count` is `0` in MVP (separate query needed) — `teams/page.tsx`.
- Action runner team-invite uses a manual redirect safety path instead of a live invite (`action-runner.tsx`).
- `/download` shows "artifact not yet published" for the current desktop release.
- Knowledge file upload, semantic search, dictionary import/export, and the team activity feed are now implemented (`[x]` in the catalog).