# Room

A small Google Meet–style web app: create a meeting, share `/meet/abc-defg-hij`, and talk with camera, microphone, chat, screen share, and a waiting room.

Media uses a **mesh**. Each browser opens a WebRTC peer connection to every other person. That stays simple up to about four people. The server only relays signaling. `server/src/signaling/mediaRouter.ts` is the seam for a later SFU (mediasoup or LiveKit) when you need more than that.

## Architecture

```
Browser (React)                         API (Express)
  lobby: getUserMedia preview            JWT access + refresh cookie
  call: RTCPeerConnection per peer       MongoDB: users, meetings,
        |                                 participants, chat
        |  Socket.IO                      |
        +------ join-room ---------------> room access + waiting room
        +------ offer / answer / ice ----> relay to the target socket
        +------ chat, mute, remove ------> persist or enforce, then broadcast

STUN: stun.l.google.com (dev)
TURN: coturn via TURN_URL when you deploy (needed when peers cannot connect directly)
```

```
client/src
  app/                 router
  features/auth        login, signup, guest session
  features/home        new meeting and join-by-code
  features/meeting     lobby, mesh session, call room
  shared/api.ts
server/src
  routes + services    auth and meetings
  models               User, Meeting, Participant, ChatMessage
  signaling            in-memory rooms + mesh relay
```

## WebRTC in one pass

- **Offer / answer.** The people already in the room create an SDP offer when someone joins. The new person answers. That swaps the media description (codecs, tracks).
- **ICE.** Each side gathers network candidates (local addresses, STUN reflexive addresses, TURN relay addresses) and trickles them through `ice-candidate`.
- **STUN** helps a peer learn its public address. **TURN** relays media when a firewall blocks a direct path. Development uses Google’s public STUN only.
- **Mesh** means every pair has its own connection. An **SFU** would receive one upload per person and fan it out, which is the path for 10+ people.

Signaling events: `join-room`, `user-joined`, `offer`, `answer`, `ice-candidate`, `user-left`, `toggle-audio`, `toggle-video`, `screen-share-start`, `screen-share-stop`, `chat-message`, `host-mute`, `host-remove`, plus `host-admit` / `host-deny` for the waiting room.

If a socket drops, Socket.IO reconnects and the client joins the room again, closing the old peer connections first (the socket id has changed). A failed peer connection calls `restartIce()`.

## Schemas

- **User** — `name`, `email` (unique), `passwordHash`, `avatar`, `googleId`, `refreshTokenHash`, `createdAt`
- **Meeting** — `meetingCode` (unique), `hostId` or `hostGuestId`, `title`, `scheduledAt`, `status`, `settings` (`waitingRoom`, `allowChat`, `allowScreenShare`), `createdAt`
- **Participant** — `meetingId`, `userId` or `guestId` / `guestName`, `displayName`, `role`, `status`, `joinedAt`, `leftAt`
- **ChatMessage** — `meetingId`, `senderId`, `senderName`, `message`, `timestamp` (indexed with the meeting)

## Run it

MongoDB has to be listening on `127.0.0.1:27017`. From the repo root:

```bash
docker compose up -d mongo
```

Then in two terminals:

```bash
cd server
cp .env.example .env
npm install
npm run dev
```

```bash
cd client
npm install --legacy-peer-deps
npm run dev
```

Open http://localhost:5173. The Vite dev server proxies `/api` and `/socket.io` to port 4000.

`RATE_LIMIT_MAX` and `AUTH_RATE_LIMIT_MAX` cap requests per `RATE_LIMIT_WINDOW_MS` and `AUTH_RATE_LIMIT_WINDOW_MS`. Set a max to `0` to turn that limiter off. Restart the API after changing them so the in-memory counters reset.

Google login stays off until `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`, and `GOOGLE_REDIRECT_URI` are set on the server and `VITE_GOOGLE_AUTH=true` is set for the client.

Production media needs HTTPS. Docker runs MongoDB and the API. Put Nginx in front with [docs/setup-docker.md](docs/setup-docker.md), or Apache with [docs/setup-apache.md](docs/setup-apache.md). Put coturn credentials in `TURN_URL`, `TURN_USERNAME`, and `TURN_CREDENTIAL`.

```bash
cd server && npm run typecheck
cd client && npm run build
```
