- auth.ts: auto-allow localhost:3000-3010 + LAN_HOST for trustedOrigins - setup.sh: new `dev` command (update + kill old processes + auto LAN IP + launch) - next.config.ts: allowedDevOrigins for LAN HMR
12 KiB
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 + PgBouncer (connection pooling) |
| Cache/PubSub | Redis 7 (rate limiting, lobby pub/sub, chat real-time, caching) |
| 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, redis, rate-limit, lobby-pubsub, chat-pubsub
│ ├── 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, redis, pgbouncer, 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
-
Guest join (with lobby): Guest → POST
/api/rooms/[id]/join→ LobbyEntry(PENDING) → SSE via Redis pub/sub → Host approves → LiveKit token → connect -
Real-time chat: POST message → DB + Redis PUBLISH → SSE
/api/rooms/[id]/chat/stream→ instant delivery to all participants -
Real-time transcription: Audio tracks → AI Agent (Deepgram STT) → DataChannel → Live captions
-
Post-lecture (
room_finishedwebhook): 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_KEYmiddleware: protects local dev from network access- LiveKit webhook: signature verification via
WebhookReceiver
Performance Architecture
Clients → Traefik (LB) → Next.js (x2 replicas) → PgBouncer (pool 25, max 500) → PostgreSQL
→ Redis (pub/sub, cache, rate limit)
→ LiveKit (video/audio SFU)
- Redis pub/sub replaces DB polling for lobby SSE and chat — instant delivery (<10ms)
- PgBouncer multiplexes 500 client connections into 25 real PostgreSQL connections
- Chat SSE via Redis pub/sub + optimistic UI on client — messages appear before server confirms
- Rate limiting via Redis INCR+EXPIRE — works across multiple app replicas
- Chat cache in Redis (10s TTL) — reduces DB reads during active rooms
- Prisma select — only fetch needed columns, not full rows
Commands
# Dev
npm run dev # Next.js dev server (localhost:3000)
docker compose up -d postgres minio redis pgbouncer # DB + Storage + Redis + PgBouncer
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
# Setup script (universal installer/doctor)
./setup.sh # Interactive menu
./setup.sh dev # Update + launch dev server (auto LAN, kill old processes)
./setup.sh install # Full first-time setup (auto-generates passwords)
./setup.sh update # git pull + npm install + prisma + rebuild
./setup.sh doctor # Diagnose & auto-fix common issues
./setup.sh status # Health check all services
./setup.sh restart # Restart all containers
./setup.sh logs [service] # Tail service logs (default: app)
./setup.sh admin # Promote user to ADMIN role
./setup.sh reset # Full teardown (with confirmation)
Environment Variables
See .env.example for all variables. Key ones:
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/liveserver
LIVEKIT_URL=wss://...
LIVEKIT_API_KEY=...
LIVEKIT_API_SECRET=...
BETTER_AUTH_SECRET=...
# Auth — trusted origins for non-localhost access (comma-separated)
BETTER_AUTH_TRUSTED_ORIGINS=http://192.168.1.78:3000,http://localhost:3000
# LAN IP for auto trustedOrigins in dev (auto-detected by ./setup.sh dev)
# LAN_HOST=192.168.1.78
# 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.tsin project root (required by Prisma 7)datasourceUrlpassed via PrismaClient constructor, not in schema- Schema has no
urlin datasource block — onlyprovider - Use
-- --webpackflag fornext buildon Windows (Turbopack WASM issue)
Auth Notes
better-authhandles registration/login via/api/auth/[...all]catch-all route- Client:
auth-client.tsusescreateAuthClient()withoutbaseURL— auto-detects current origin (works from any IP/domain) - Server:
auth.tsusesBETTER_AUTH_URLforbaseURLandBETTER_AUTH_TRUSTED_ORIGINS(comma-separated) for CSRF origin validation. WithoutBETTER_AUTH_TRUSTED_ORIGINS, auto-allowslocalhost/127.0.0.1on ports 3000–3010 +LAN_HOSTif set - First admin: register normally, then promote via
./setup.sh adminor manually in DB - No
"type"field inpackage.json— removed to fix Turbopack ESM/CJS conflict in dev mode. Next.js handles ESM in.ts/.tsxautomatically
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.
Post-Change Checklist (ОБЯЗАТЕЛЬНО)
После каждого изменения кода или конфигурации Claude обязан выполнить:
- Обновить
CLAUDE.md— если изменились архитектура, endpoints, модели, команды, стек или conventions - Проверить
setup.sh— все новые сервисы/зависимости должны быть в скрипте (readiness checks, .env переменные, docker compose команды) - Проверить
README.md— инструкции, API таблицы, структура проекта должны отражать текущее состояние - Проверить
PROMPT.md— спецификация должна соответствовать реализации - Проверить
.env.example— все новые переменные окружения должны быть задокументированы
Не пропускать этот чеклист. Если изменение не затрагивает файл — просто подтвердить что файл актуален.
Known Issues & Fixes
| Issue | Cause | Fix |
|---|---|---|
| White screen in dev (ESM/CJS conflict) | "type": "module" or "type": "commonjs" in package.json |
Remove the "type" field entirely — Next.js doesn't need it |
| Auth silently fails from LAN | auth-client.ts had hardcoded baseURL → requests went to localhost from browser |
Removed baseURL, added trustedOrigins config |
setup.sh doctor crashes on .env check |
Comments in .env.example parsed as variable names by set -euo pipefail |
Fixed parsing logic |
setup.sh update runs git pull after stash declined |
Missing else branch after stash prompt |
Fixed control flow |
| Auth form resets on non-localhost (no error shown) | trustedOrigins fallback only had localhost:3000, CSRF rejected other origins silently |
auth.ts auto-allows ports 3000–3010 + LAN_HOST; setup.sh dev auto-detects LAN IP |
Conventions
- Communication language: Russian
- Guests don't register, but
user_idreserved for future LMS sessionId(UUID) is the cross-cutting key linking LobbyEntry, ParticipantHistory, ChatMessage, SharedFile for guestsRoom.codeis the user-facing invite code (not the DB id)- Files store
fileKey(S3 object key), not full URLs LectureArtifactis 1:1 with Room- All cascade deletes: removing Room removes all related data
- MinIO stays as S3 storage — GitHub repo archived (Feb 2026) but Docker image still maintained, no viable lightweight alternative