Full MVP implementation: - Next.js 16 + React 19 + TypeScript + Tailwind CSS v4 - LiveKit integration (rooms, tokens, webhooks, moderation) - better-auth (email/password, sessions, roles) - Prisma 7 + PostgreSQL (9 models, 3 enums) - 15 API routes (auth, rooms, lobby, chat, files, moderation, hand-raise) - 7 pages (landing, auth, dashboard, join, video room) - SSE-based waiting room with host approval flow - Security: PIN rate limiting, session fingerprint bans, chat/files auth - Python AI Agent (Deepgram STT + OpenAI summarization) - Docker Compose (local + production with Traefik + Let's Encrypt) - Interactive setup script (setup.sh) - Dev protection middleware (DEV_ACCESS_KEY, ALLOWED_IPS) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
168 lines
6.8 KiB
Markdown
168 lines
6.8 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
**LiveServer-M1** — образовательная видеоконференц-платформа на базе LiveKit.
|
|
|
|
Ключевые фичи:
|
|
- AI-ассистент: авто-подключение к комнатам, real-time транскрипция (Deepgram), суммаризация лекций (OpenAI GPT)
|
|
- Защита от Zoom-bombing: lobby/waiting room, PIN-коды, kick/ban по session fingerprint, panic button
|
|
- Пост-лекционная панель: чат, файлы, транскрипт, AI-саммари, экспорт в PDF/Google Drive
|
|
|
|
Полная спецификация: **`PROMPT.md`**
|
|
|
|
## Tech Stack
|
|
|
|
| Слой | Технологии |
|
|
|------|-----------|
|
|
| Frontend | Next.js 16 (App Router), React 19, TypeScript, Tailwind CSS v4 |
|
|
| Video | LiveKit Cloud → self-hosted, `@livekit/components-react` |
|
|
| Backend | Next.js Route Handlers, `livekit-server-sdk` |
|
|
| Auth | `better-auth` + Prisma adapter |
|
|
| AI Agent | Python, `livekit-agents`, `livekit-plugins-deepgram` (STT), `livekit-plugins-openai` (LLM) |
|
|
| DB | PostgreSQL + Prisma 7 ORM |
|
|
| Storage | MinIO (S3-compatible) |
|
|
| Proxy | Traefik v3 + Let's Encrypt (prod only) |
|
|
|
|
## Architecture
|
|
|
|
```
|
|
├── src/
|
|
│ ├── app/
|
|
│ │ ├── api/ # 15 API route handlers
|
|
│ │ │ ├── auth/[...all]/ # better-auth catch-all
|
|
│ │ │ ├── rooms/ # CRUD, by-code lookup
|
|
│ │ │ ├── rooms/[roomId]/ # join, lobby, lobby/stream (SSE), chat, files, moderate, hand-raise, start, end
|
|
│ │ │ └── livekit/ # token generation, webhook receiver
|
|
│ │ ├── (dashboard)/ # Host/Admin pages
|
|
│ │ ├── join/[code]/ # Guest entry
|
|
│ │ ├── room/[code]/ # Video room (LiveKit)
|
|
│ │ ├── login/ & register/ # Auth pages
|
|
│ │ └── page.tsx # Landing
|
|
│ ├── components/
|
|
│ │ ├── room/ # ChatPanel, ModerationPanel
|
|
│ │ └── lobby/ # WaitingRoom, LobbyManager
|
|
│ ├── lib/ # prisma, auth, auth-helpers, livekit
|
|
│ ├── middleware.ts # Dev protection (DEV_ACCESS_KEY, ALLOWED_IPS)
|
|
│ └── types/
|
|
├── ai-agent/ # Python LiveKit Agent
|
|
├── prisma/schema.prisma # 9 models, 3 enums
|
|
├── docker-compose.yml # Base: postgres, minio, ai-agent, app
|
|
├── docker-compose.override.yml # Local dev: direct ports, no SSL
|
|
├── docker-compose.prod.yml # Traefik + Let's Encrypt
|
|
└── Dockerfile # Multi-stage Next.js standalone build
|
|
```
|
|
|
|
### Key Data Flows
|
|
|
|
1. **Guest join (with lobby):**
|
|
Guest → POST `/api/rooms/[id]/join` → LobbyEntry(PENDING) → SSE `/api/rooms/[id]/lobby/stream` → Host approves → LiveKit token → connect
|
|
|
|
2. **Real-time transcription:**
|
|
Audio tracks → AI Agent (Deepgram STT) → DataChannel → Live captions
|
|
|
|
3. **Post-lecture (`room_finished` webhook):**
|
|
Transcript → OpenAI GPT → LectureArtifact → `/lectures/[id]`
|
|
|
|
### User Roles
|
|
|
|
- **ADMIN** — global panel, all rooms monitoring
|
|
- **HOST** — room creation, moderation, security
|
|
- **GUEST** — join by link, no registration required
|
|
|
|
### Security Layers
|
|
|
|
- `sessionFingerprint` (required) for bans — IP is secondary only
|
|
- PIN hashed with bcrypt, rate-limited (5 attempts/min per IP)
|
|
- Chat/files auth: verified via ParticipantHistory
|
|
- SSE lobby: verified against existing LobbyEntry
|
|
- Token generation: only room owner can get LiveKit token
|
|
- `DEV_ACCESS_KEY` middleware: protects local dev from network access
|
|
- LiveKit webhook: signature verification via `WebhookReceiver`
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
# Dev
|
|
npm run dev # Next.js dev server (localhost:3000)
|
|
docker compose up -d postgres minio # DB + Storage only
|
|
npm run lint # TypeScript type-check (tsc --noEmit)
|
|
|
|
# Database
|
|
npx prisma migrate dev # Create + apply migration
|
|
npx prisma db push # Quick schema sync (no migration)
|
|
npx prisma studio # DB GUI
|
|
npx prisma generate # Regenerate Prisma Client
|
|
|
|
# Build
|
|
npm run build -- --webpack # Production build (Webpack, not Turbopack — WASM limitation on Windows)
|
|
|
|
# Docker (full stack)
|
|
docker compose up -d --build # Local
|
|
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build # Prod (with Traefik)
|
|
|
|
# AI Agent
|
|
cd ai-agent && python main.py start
|
|
```
|
|
|
|
## Environment Variables
|
|
|
|
See `.env.example` for all variables. Key ones:
|
|
|
|
```env
|
|
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/liveserver
|
|
LIVEKIT_URL=wss://...
|
|
LIVEKIT_API_KEY=...
|
|
LIVEKIT_API_SECRET=...
|
|
BETTER_AUTH_SECRET=...
|
|
|
|
# Local dev protection (when DOMAIN is not set)
|
|
DEV_ACCESS_KEY=mySecretKey123
|
|
# ALLOWED_IPS=192.168.1.10,192.168.1.11
|
|
|
|
# Production
|
|
# DOMAIN=live.example.com
|
|
# ACME_EMAIL=admin@example.com
|
|
```
|
|
|
|
## Deployment Modes
|
|
|
|
| Mode | Command | Description |
|
|
|------|---------|-------------|
|
|
| **Local dev** | `docker compose up -d` | Direct ports (3000, 5432, 9000). `docker-compose.override.yml` auto-applied |
|
|
| **Production** | `docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d` | Traefik reverse proxy, auto SSL via Let's Encrypt |
|
|
|
|
## Prisma 7 Notes
|
|
|
|
- `prisma.config.ts` in project root (required by Prisma 7)
|
|
- `datasourceUrl` passed via PrismaClient constructor, not in schema
|
|
- Schema has no `url` in datasource block — only `provider`
|
|
- Use `-- --webpack` flag for `next build` on Windows (Turbopack WASM issue)
|
|
|
|
## Agent Orchestration
|
|
|
|
| Task | Agent |
|
|
|------|-------|
|
|
| API routes, backend logic | `backend-architect` |
|
|
| React components, LiveKit UI | `frontend-developer` |
|
|
| DB schema, indexes, queries | `database-optimizer` |
|
|
| Python AI Agent, Deepgram/OpenAI | `ai-engineer` |
|
|
| System architecture | `software-architect` |
|
|
| UI design, components | `ui-designer` |
|
|
| UX flows, accessibility | `ux-architect` |
|
|
| Code review before commit | `code-reviewer` |
|
|
|
|
**Rule:** for tasks spanning 2+ layers — use `agents-orchestrator`.
|
|
|
|
## Conventions
|
|
|
|
- Communication language: Russian
|
|
- Guests don't register, but `user_id` reserved for future LMS
|
|
- `sessionId` (UUID) is the cross-cutting key linking LobbyEntry, ParticipantHistory, ChatMessage, SharedFile for guests
|
|
- `Room.code` is the user-facing invite code (not the DB id)
|
|
- Files store `fileKey` (S3 object key), not full URLs
|
|
- `LectureArtifact` is 1:1 with Room
|
|
- All cascade deletes: removing Room removes all related data
|