History
Every prototype, rewrite, and shipped feature in the path from one AnalyserNode to a real-time sync platform.
Nine months. One developer. A new way to listen together.
Every prototype, every rewrite, every shipped feature — from a single AnalyserNode
to a full real-time sync platform running on WebRTC, Cloudflare, and encrypted remote file transfer.
MUSIXQUARE starts as a solo-device audio visualizer in August 2025. No sync, no network — just
a single AnalyserNode, frequency bands, and a Canvas loop. But the audio-graph
plumbing laid down here — configurable cutoffs, per-band smoothing — survives into the final product.
October brings the first real P2P attempt: two phones, PeerJS over WebRTC, a dual-strategy sync
algorithm with hard-jump and playbackRate nudge. November strips it down to a
countdown-based start — simpler, more reliable. December shifts to channel routing:
ChannelSplitter, per-band GainNodes, a subwoofer LPF. The name,
the wordmark, the signature #3b82f6 blue — all settle into final form in late December.
AnalyserNode pipeline, frequency-band smoothing, and a Canvas visualizer. The audio-graph pattern that ships in v1.3 traces directly back here.playbackRate nudge (0.05s–0.5s). A 1-second heartbeat sends { time, paused, playbackRate, timestamp } — the ancestor of today's SharedClock.setTimeout to the same local deadline. Host MP3 transfers to guest as a Blob. Per-device offset nudge — the direct ancestor of today's Nudge Sync.Between December's channel lab and the first git commit on January 25, everything converges: frequency analysis, P2P sync, and channel routing become one app. That month of intense iteration was only ever saved as the final file. By the time git history starts, MUSIXQUARE already ships Host / Guest + QR invite, a full audio-effect chain (reverb, 5-band EQ, virtual surround), Nudge Sync, and a 7.1-channel role picker.
February unlocks remote connections via Metered TURN and starts the TypeScript rewrite —
12,018 lines of app.js broken into strict-mode ES modules under src/.
March and April pile on: chat with slash commands, beat detection with Phase Sync,
the SharedClock architecture that makes sync genuinely reliable across flaky networks,
and YouTube 2-stage sync with rendezvous handshake.
app.js → strict-mode TypeScript ES modules. 71 P2P protocol messages, EventBus handlers, and state paths get real types. Build fails before runtime fails. i18n key system introduced./debug, /nick), profanity filter, grouped bubbles. High-precision BPM analyzer with Phase Sync. 174 Playwright E2E scenarios covering late-join, chaos, and multi-device cases.AnalyserNode → BiquadFilter → ChannelSplitter → per-channel Gain → Merger → Convolver → destination.
RAM-only slot pool for audio tracks — no disk writes, no OPFS.
Vite + TypeScript ES2022 strict-mode build. Service Worker for offline shell caching.
getDisplayMedia({audio}). A native app would route system audio through screen-capture APIs, at the cost of install friction.getDisplayMedia({audio: true}) is not implemented by mobile browsers, so a mobile device cannot host system audio. Mobile guests can still receive a desktop host's stream through the SFU path. Hosting from a phone stays desktop-only until mobile OS APIs allow it.