Capstone / lesson 15
Ship the call. Then ship the failure.
The capstone is not a prettier demo. It is a one-to-one video application where every state has an owner, every failure has a message, and every resource has a shutdown path. Build it locally, break it on purpose, and verify the result before you call it done.
In scope
- Room code + generated handle
- Camera/mic and test feed
- Offer/answer + trickle ICE
- TURN fallback
- Chat and small file transfer
- Stats, errors, and teardown
Out of scope
- Accounts or profiles
- Names, emails, or payments
- Legal or privacy pages
- Group calls or recording
- A public credential registry
- Any personal-information flow
The anonymous completion record is the only “account” in this project. It is a local IndexedDB record, not an identity product.
01 / The brief
One call. No magic. No missing state.
Build a two-person video room on top of a WebSocket signaling service and a TURN-capable ICE configuration. The app should let a person arrive with a room code, receive an auto-generated handle, see local and remote media, mute, exchange chat and a small file, inspect the live path, and leave cleanly. The server should enforce the room cap and record completion progress without collecting personal data.
The difficult part is not the happy path. It is what happens when permission is denied, the socket dies, a candidate never arrives, the network changes, a file is too large, or one browser refreshes mid-call. That is where the field guide becomes an engineering practice.
Capture
getUserMedia / test feed local tracks
Signal
WebSocket join offer / answer / ICE
Connect
ICE + TURN DTLS / SRTP
Observe
getStats + logs path + quality
Close
stop tracks leave / teardown
02 / Milestones
Six passes, each with evidence.
Do not declare a milestone complete because the UI looks right. Each one has a definition of done you can demonstrate in a browser or read in a log.
Room and anonymous identity
A person can arrive with a room code, receive a generated handle, and leave without an account.
- Room codes are validated, capped, and authorized at the signaling server.
- No name, email, profile, or payment field exists anywhere in the flow.
- A third peer is rejected or placed in a clear waiting state.
- Refresh and tab close remove the participant from the room.
The call path
Media capture, offer/answer, trickle ICE, and a TURN fallback connect two browsers reliably.
- Camera and microphone denial has a specific, recoverable message.
- A synthetic test feed works when no camera exists.
- Offer, answer, and candidates apply in the correct order.
- A TURN-only path connects when credentials are configured.
- The lab's automatic, manual, and loopback modes have taught you what each failure looks like.
Lifecycle and media controls
Mute, source changes, device loss, leaving, and teardown all have an owner and a visible state.
- Mute disables the track payload without tearing down the connection.
- Camera or mic device changes do not leave a ghost old track.
- Leaving stops every local track and closes the peer connection.
- Remote tracks disappear when the peer leaves intentionally.
- Object URLs and data-channel buffers are released.
Resilience
The call survives signaling loss, reconnects cleanly, and can restart ICE after a network change.
- Killing signaling does not immediately kill an established media path.
- Signaling reconnects with backoff and jitter, then rejoins the room.
- ICE restart succeeds after a simulated path interruption.
- Malformed signaling messages are rejected without crashing the client.
- A compact status model explains connecting, connected, reconnecting, and failed.
Observability
RTT, loss, jitter, bitrate, frames, selected pair, and limitation reason are visible without opening devtools.
- getStats is sampled on an interval and reduced to user-facing numbers.
- The selected candidate pair and relay path are visible.
- Quality limitations distinguish CPU from bandwidth or other.
- Errors name the layer and the next action, not just “connection failed”.
- Logs redact SDP, candidates, and peer identifiers where appropriate.
Ship the surface
The app has a documented setup, a test matrix, permission hygiene, and a clean local shutdown.
- The README explains install, signaling, optional ICE, and certificate gating.
- CSP, Permissions-Policy, and secure-context assumptions are documented.
- TURN credentials, when used, are short-lived and minted server-side.
- The final verification list passes on a second device or real network.
- Progress is durable in this browser's IndexedDB; no personal information is collected.
03 / Break it on purpose
The failure drill is the product.
Run every drill with a second tab or device. Write down what the user sees, what the sender's stats say, and which layer failed first. “It reconnected” is not an observation; the state trail is.
A clean tab refresh must not leave a ghost participant. If the room says 2 peers while one browser is closed, the teardown path is incomplete.
| Drill | Expected evidence | Do not accept |
|---|---|---|
| Camera permission denied | Specific recovery message; test feed still works. | A generic “call failed” that points at signaling. |
| TURN temporarily unavailable | Direct path still connects where possible; the status names the relay problem. | Silent black video with a green “connected” badge. |
| Signaling socket killed | Established media continues until the path itself fails; UI explains the split. | Immediate teardown or a frozen UI with no status. |
| Peer closes the tab | Remote media and participant state disappear; room count is correct. | A ghost tile that stays forever. |
| ICE path changes networks | ICE restart offers a new path; the user sees reconnecting then connected. | A full page reload as the only recovery. |
| Malformed data-channel file | Transfer is rejected at the size or schema boundary. | The tab runs out of memory. |
04 / Final verification
Sign the record with evidence.
This is the capstone checklist from lesson 15. Every line should be demonstrable in the running app or visible in a durable record. The certificate is a completion record, not a promise of production readiness.
Two browsers connect through signaling with camera and microphone
A third peer is rejected or placed in a clear waiting state
Newcomer refresh does not leave a ghost participant
Camera denial shows a specific, recoverable message
Test feed works when no camera exists
Mute changes payload, not the peer-connection state
TURN-only path connects when TURN is configured
Killing signaling does not kill an established media path
ICE restart succeeds after a path interruption
Chat and file transfer survive signaling loss
Oversized or malformed files are rejected
Closing the tab stops the camera and removes the peer
RTT, loss, jitter, bitrate, path type, and CPU limitation are visible
The certificate unlocks only after every lesson and lab is complete
No name, email, or personal profile is requested anywhere
05 / Finish the field guide
Complete every lesson and lab, then issue your anonymous record.
The certificate unlocks only when all fifteen lessons and all four labs are present in this browser. It records the scope and date, never a name. If you reset progress, the record is removed with it.