# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Chad is a real-time voice/video chat server (think Discord-like) built with Fastify, Socket.IO, and mediasoup for WebRTC media handling. It uses SQLite via Prisma ORM and Lucia for session-based authentication. The client is a Tauri desktop app (separate repo). ## Commands - **Start server:** `yarn start` (runs `ts-node --transpile-only server.ts`) - **Deploy DB (migrate + seed + generate):** `yarn db:deploy` - **Generate Prisma client after schema changes:** `npx prisma generate` - **Create a migration:** `npx prisma migrate dev --name ` - **Lint:** `npx eslint .` - **Package manager:** Yarn 4 (corepack). Do not use npm. ## Architecture ### Entry Point & Plugin System `server.ts` creates a Fastify instance and uses `@fastify/autoload` to auto-register everything in `plugins/` and `routes/` (prefixed under `/chad`). Plugins use `fastify-plugin` (`fp`) with named dependencies to control load order. ### Plugin Load Order (dependency chain) 1. `plugins/auth.ts` — Adds `req.user` / `req.session` via Lucia cookie validation on every request (preHandler hook) 2. `plugins/mediasoup-worker.ts` — Creates a mediasoup Worker, decorates `fastify.mediasoupWorker` 3. `plugins/mediasoup-router.ts` — Creates a mediasoup Router (depends on worker), decorates `fastify.mediasoupRouter`. Configures supported audio/video codecs (Opus, VP8, VP9, H.264, AV1) 4. `plugins/socket.ts` — Creates Socket.IO server at `/chad/ws` (depends on worker + router), decorates `fastify.io`. Registers socket handlers on `fastify.ready()` ### Socket Handlers (`socket/`) - `socket/webrtc.ts` — Main WebRTC signaling: join/leave, transport creation, producer/consumer lifecycle, audio level observation, active speaker detection - `socket/channel.ts` — Channel-based socket logic (in development on `channels` branch) Both handlers authenticate by looking up `socket.handshake.auth.userId` against the DB. ### REST Routes (`routes/`) All routes are prefixed with `/chad` via autoload config. - `routes/auth.ts` — `/register`, `/login`, `/logout`, `/me` - `routes/user.ts` — `/preferences` (GET/PATCH), `/profile` (PATCH). Profile changes broadcast to connected socket peers via `clientChanged` event. ### Type System (`types/socket.ts`) Fully typed Socket.IO events: `ClientToServerEvents`, `ServerToClientEvents`, `SocketData`. The `SomeSocket` union type covers both live `Socket` and `RemoteSocket` (from `fetchSockets()`). ### Database - SQLite with Prisma 7 + `@prisma/adapter-better-sqlite3` - Schema at `prisma/schema.prisma`, generated client at `prisma/generated/client/` - Models: `User`, `Session` (Lucia), `UserPreferences`, `Channel` - Seed creates a persistent "Default" channel - Config in `prisma.config.ts` using `dotenv` for `DATABASE_URL` ### Key Patterns - Request validation uses Zod schemas defined inline in route handlers - DTOs in `dto/` define Prisma select objects with `satisfies Prisma.*Select` for type-safe projections - `utils/socket-to-client.ts` maps socket data to the `ChadClient` interface sent to clients - ESLint uses `@antfu/eslint-config` (flat config) with `no-console` and `n/prefer-global/process` disabled ### Environment Variables - `PORT` — Server port (default: 4000, Docker: 80) - `DATABASE_URL` — SQLite path (e.g., `file:../data/database.db`) - `ANNOUNCED_ADDRESS` — Public IP for WebRTC ICE candidates (default: `127.0.0.1`) - `CORS_ORIGIN` — Socket.IO CORS origin (default: `*`) ### Docker `Dockerfile` requires python3 and build-essential for mediasoup native compilation. Runs `yarn db:deploy && yarn start`.