3.7 KiB
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(runsts-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 <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)
plugins/auth.ts— Addsreq.user/req.sessionvia Lucia cookie validation on every request (preHandler hook)plugins/mediasoup-worker.ts— Creates a mediasoup Worker, decoratesfastify.mediasoupWorkerplugins/mediasoup-router.ts— Creates a mediasoup Router (depends on worker), decoratesfastify.mediasoupRouter. Configures supported audio/video codecs (Opus, VP8, VP9, H.264, AV1)plugins/socket.ts— Creates Socket.IO server at/chad/ws(depends on worker + router), decoratesfastify.io. Registers socket handlers onfastify.ready()
Socket Handlers (socket/)
socket/webrtc.ts— Main WebRTC signaling: join/leave, transport creation, producer/consumer lifecycle, audio level observation, active speaker detectionsocket/channel.ts— Channel-based socket logic (in development onchannelsbranch)
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,/meroutes/user.ts—/preferences(GET/PATCH),/profile(PATCH). Profile changes broadcast to connected socket peers viaclientChangedevent.
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 atprisma/generated/client/ - Models:
User,Session(Lucia),UserPreferences,Channel - Seed creates a persistent "Default" channel
- Config in
prisma.config.tsusingdotenvforDATABASE_URL
Key Patterns
- Request validation uses Zod schemas defined inline in route handlers
- DTOs in
dto/define Prisma select objects withsatisfies Prisma.*Selectfor type-safe projections utils/socket-to-client.tsmaps socket data to theChadClientinterface sent to clients- ESLint uses
@antfu/eslint-config(flat config) withno-consoleandn/prefer-global/processdisabled
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.