Random 1:1 video calling — meet someone new, face to face.
Cougny pairs two people at a time for a live, peer-to-peer video chat. Media flows directly between browsers over WebRTC; our servers only handle matchmaking, signaling, and safety.
This is a pnpm + Turborepo monorepo. Apps are deliberately separate deployables so each can scale (and later be rewritten) independently.
apps/
web/ Next.js (App Router, TypeScript, Tailwind, next-intl) — user client
api/ Fastify HTTP API — anonymous sessions, TURN credentials, reports
signaling/ WebSocket signaling + FIFO matchmaking (ws)
packages/
protocol/ Zod-typed signaling + REST contracts (shared source of truth)
db/ Prisma schema + client (PostgreSQL)
config-typescript/ Shared tsconfig presets
config-eslint/ Shared ESLint flat config
infra/ docker-compose: PostgreSQL, Redis, coturn (self-hosted TURN/STUN)
POST /v1/sessions) and
stores the returned token.GET /v1/ice-servers) — STUN plus short-lived
TURN credentials minted by the API from coturn’s shared secret.For 1:1 random calling, running our own signaling server and self-hosting coturn (rather than paying a per-minute TURN/video vendor) is both the big-app pattern and dramatically cheaper at scale. The matchmaker and signaling hub are small, pure, and unit-tested, and the TURN credential scheme is the standard coturn REST-API HMAC pattern. The scale path — a Redis-backed queue and an SFU for group calls — slots in behind the same interfaces.
Prerequisites: Node 24 (.nvmrc), pnpm 10, Docker.
pnpm install
# Copy each app/package's env template to a local .env
for d in apps/api apps/signaling apps/web packages/db; do cp "$d/.env.example" "$d/.env"; done
# Start Postgres, Redis, and coturn
pnpm infra:up
# Generate the Prisma client and apply the schema
pnpm db:generate
pnpm db:migrate
# Run every app in watch mode (web :3000, api :4000, signaling :4001)
pnpm dev
Open http://localhost:3000.
| Command | What it does |
|---|---|
pnpm dev |
Run all apps in watch mode |
pnpm build |
Build everything (topologically) |
pnpm lint |
Lint all packages |
pnpm typecheck |
Type-check all packages |
pnpm test |
Run unit tests |
pnpm knip |
Find unused files/deps/exports |
pnpm infra:up/down |
Start / stop local infrastructure |
pnpm db:studio |
Open Prisma Studio |
@cougny/protocol. The web client and the signaling
server parse the same Zod schemas — change the wire format in one place.apps/web/messages/*.json and is rendered via next-intl.CLAUDE.md / AGENTS.md for contributor
guidance.