Files
chad/server/CLAUDE.md
2026-04-12 22:35:47 +06:00

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 (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 <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.