d3ro-voice/docs/map/05-web-app.md
Yun Chan c3ddd36c6f
Some checks failed
deploy-site / deploy (push) Failing after 40s
docs: record the 1.1.0 release and add the infrastructure map
Release notes for 1.1.0 were split between an Unreleased section and the
version section, so the published notes would have omitted the update-feed
and desktop changes. Everything shipping in this version now sits under one
`## [1.1.0]` heading.

`docs/map/` becomes the entry point for what infrastructure exists per
platform and how far each feature is developed, with a documented update
protocol so feature work and this map do not drift apart again. The release
guide now states that installer binaries live in the update feed rather than
the repository.
2026-09-16 23:27:52 +09:00

86 lines
5 KiB
Markdown

# 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 | `<MicRecorder/>` 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 (`<ActionRunner/>`) |
| `(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 (`<ChatPanel/>`) |
| `(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 `<Sidebar/>`.
---
## 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).