A modern WebRTC video chat platform built as a pnpm monorepo with NestJS backend and React frontend. Group video calls via mediasoup SFU, plus a developer platform on top: REST API, TypeScript SDKs, live streaming egress, and recordings.
- Group Video Calls — mediasoup SFU for multi-participant rooms, ephemeral TURN credentials via coturn
- Developer Platform —
/v1REST API (rooms, tokens, egress, recordings) with API-key auth and per-key rate limits - TypeScript SDKs —
@zvonok/clientand@zvonok/reacton npm (sources inpackages/);@zvonok/video-layoutis the app's internal layout engine - Live Streaming Egress — push the composited room program to RTMP endpoints or serve it as HLS; server-side recording with Range-supported downloads
- Webhooks — signed
room.*andegress.*events with delivery retries - Whiteboard — shared collaborative canvas in rooms
- Prebuilt Widget — drop-in room UI component on top of the React SDK
- Docs Site — static documentation site served on the VPS
- Secure Authentication — JWT with refresh token rotation and reuse detection
- Production-Ready — Docker Compose + Caddy, shared Traefik gateway on the VPS (multi-site, automatic HTTPS)
| Layer | Tech |
|---|---|
| Backend | NestJS v11, PostgreSQL 16, Prisma ORM, Passport.js (JWT), mediasoup |
| Frontend | React 19, Vite 7, Tailwind CSS v4, React Router v7, Base UI, mediasoup-client |
| Signalling | Socket.io |
| Media | mediasoup SFU, FFmpeg (egress pipelines), coturn (TURN) |
| Deployment | Docker Compose, Caddy + shared Traefik gateway in production (multi-site VPS) |
- Node.js 22+
- pnpm (this project uses pnpm only — no npm/yarn)
- Docker and Docker Compose
pnpm installServer env is ready out of the box at apps/server/.env.development.
Client env is at apps/client/.env.local.
If missing, create from examples:
cp apps/server/.env.example apps/server/.env.development
cp apps/client/.env.example apps/client/.env.localEdit apps/client/.env.local:
VITE_API_BASE_URL="http://localhost:3000"
VITE_SOCKET_URL="http://localhost:3000"pnpm -C apps/server db:devThis starts PostgreSQL (port 5432) and pgAdmin (port 5050) via Docker.
pnpm -C apps/server migrate:devpnpm dev- Server: http://localhost:3000 (Swagger: http://localhost:3000/swagger)
- Client: http://localhost:5173
In dev mode, mediasoup listens on 127.0.0.1 (default without env vars) — video/audio works only on the same machine.
See docs/deployment.md for the full production setup guide.
Quick version:
make setup # create .env from template
$EDITOR .env # edit with real secrets and your domain/IP
make deploy-local # build and start all services on this machineThis starts 5 services: PostgreSQL, migrations, NestJS server, Caddy (with baked-in client assets), and coturn TURN.
Open: https://localhost (self-signed) or https://your-domain.com (Let's Encrypt).
Run make help to see all available targets.
zvonok/
├── apps/
│ ├── server/ # NestJS backend (port 3000)
│ │ ├── prisma/ # Database schema and migrations
│ │ └── src/
│ │ ├── auth/ # Authentication (JWT, Passport)
│ │ ├── user/ # User CRUD
│ │ ├── room/ # Room management
│ │ ├── chat/ # Room chat
│ │ ├── sfu/ # mediasoup SFU (WebSocket gateway)
│ │ ├── egress/ # RTMP/HLS streaming + server-side recordings
│ │ ├── platform/ # Developer platform: /v1 API, API keys, DTOs
│ │ ├── developer/ # Developer accounts, projects, API keys
│ │ ├── webhooks/ # Signed webhook delivery with retries
│ │ └── whiteboard/ # Shared collaborative canvas
│ └── client/ # React frontend (port 5173)
│ └── src/
│ ├── features/ # Feature modules
│ ├── components/ # Shared UI components
│ ├── hooks/ # Shared hooks
│ └── lib/ # API client, SFU manager, utilities
├── packages/
│ ├── client/ # @zvonok/client — headless SFU/room SDK
│ ├── react/ # @zvonok/react — React bindings + host controls
│ └── video-layout/ # @zvonok/video-layout — composited layout engine
├── docs/ # Architecture, quickstart, domain docs, ADRs
├── docker-compose.yml # Production full-stack deployment
├── Makefile # Production Docker orchestration (make help)
├── Caddyfile # Caddy config (dev/standalone; imports Caddyfile.routes)
├── Caddyfile.traefik # Caddy config for prod behind the Traefik gateway
└── .env.production.example # Production env template
| Command | Description |
|---|---|
make help |
Show all available targets |
make setup |
Create .env from template |
make ci |
Run the CI checks locally (lint, typecheck, unit tests) |
make deploy |
Workstation deploy: run make ci checks, build amd64 images, push to GHCR, deploy to the VPS (mirrors deploy.yml, no GitHub Actions) |
make deploy-local |
Build images and start all services on this machine (local stack) |
make down |
Stop all services |
make migrate |
Run database migrations |
make logs |
Follow logs for all services |
make status |
Show local stack status and health |
| Command | Description |
|---|---|
pnpm dev |
Run client + server in development |
pnpm test |
Run tests in all workspaces |
pnpm test:client |
Client unit tests (CI mode) |
pnpm test:server |
Server unit tests |
pnpm clean |
Clean caches |
| Command | Description |
|---|---|
pnpm -C apps/server dev |
Development mode with watch |
pnpm -C apps/server build |
Compile TypeScript |
pnpm -C apps/server lint |
ESLint |
pnpm -C apps/server test |
Unit tests |
pnpm -C apps/server test:e2e |
E2E tests |
pnpm -C apps/server migrate:dev |
Apply Prisma migrations |
pnpm -C apps/server db:dev |
Start dev database (Docker) |
| Command | Description |
|---|---|
pnpm -C apps/client dev |
Vite dev server |
pnpm -C apps/client build |
Production build |
pnpm -C apps/client lint |
ESLint |
pnpm -C apps/client test:run |
Unit tests (CI mode) |
pnpm -C apps/client test:e2e |
Playwright E2E tests |
| Command | Description |
|---|---|
pnpm -C packages/client build |
Build @zvonok/client |
pnpm -C packages/react build |
Build @zvonok/react |
pnpm -C packages/video-layout build |
Build @zvonok/video-layout |
pnpm -C packages/<pkg> test:run |
Run package unit tests (client, react) |
pnpm -C packages/<pkg> lint |
Lint and format-check a package |
pnpm -C packages/<pkg> lint:ts |
Type-check a package |
- Quickstart — integrate the SDK into an external app
- Platform Roadmap — platform direction, stages, checkpoint
- Egress — HLS/RTMP streaming and server-side recordings
- Whiteboard — shared collaborative canvas
- Deployment Guide — Production Docker setup
- ADRs — architecture decision records
- OpenSpec Specs — source of truth: current behavior per domain
MIT