7795cf84a3f53e060bdfe9504bc76167a95d5e7d
- Sidebar (channel list + nickname) becomes an off-canvas drawer below 860px, opened via a new fixed top bar (hamburger + live status) and closed by tapping the backdrop or picking a channel. - Mic/deafen/share get an always-visible bottom control bar so they're reachable mid-call without opening the drawer; updateMicButton/ updateDeafenButton and their click wiring now target both the sidebar and mirror buttons via shared NodeLists instead of single elements. - Per-user volume popup (previously hover-only) now also toggles on tap, and repositions below the row instead of to the side, which would overflow a narrow drawer. - Screen-share tiles stack full-width, touch targets are enlarged, and the spatial map panel shrinks to leave room for the stage. Also includes the working tree's prior swap of the spatial view from Konva to Cytoscape.js (drag, scroll-to-zoom, fit-to-view, distance edges) — not authored in this change, carried along since it was already uncommitted. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
gibbz voice — POC
Discord-clone proof of concept: peer-to-peer WebRTC voice chat + screen sharing with position-based spatial audio and pluggable STUN/TURN.
Run (Node 18+, only dep is ws):
npm install
PORT=8081 npm start
# open http://localhost:8081, click a voice channel, allow mic
What works
- Mesh WebRTC voice (perfect negotiation; lowest peer id initiates)
- Screen share with audio (mic is spatialized, screen audio plays direct)
- Spatial audio: drag your avatar on the plane; remote mics run through a
PannerNode(HRTF, inverse distance). Positions sync over signaling. - Custom STUN/TURN: gear icon → JSON override in
localStorage, applied on next join. Server default comes from env (below). - Mute (M), deafen (D), per-peer volume, speaking indicators.
ICE configuration (server side)
| Env var | Meaning |
|---|---|
STUN_URLS |
comma-separated stun: urls (Google defaults) |
TURN_URLS |
comma-separated turn:/turns: urls |
TURN_USERNAME / TURN_CREDENTIAL |
static TURN creds |
ICE_SERVERS_JSON |
full {"iceServers":[...]} override, wins over the above |
PORT / HOST |
listen address (default 8081 / 0.0.0.0) |
Example with coturn:
TURN_URLS='turn:turn.example.com:3478?transport=udp,turns:turn.example.com:5349' \
TURN_USERNAME=mats TURN_CREDENTIAL=secret npm start
POC shortcuts (productionize later)
- No auth, no reconnection, rooms are in-memory, signaling is unencrypted ws behind the preview ingress (use wss/TLS in front for real deploys).
- No media server: N² mesh — fine for small rooms, needs SFU (mediasoup/livekit) beyond ~6–8 participants.
- Text channels are decorative. No persistence, no rate limiting.
- Screen-share negotiation storms on join/leave are expected at small scale.
Languages
JavaScript
75.1%
CSS
16.2%
HTML
7.5%
Makefile
0.9%
Dockerfile
0.3%