Skip to main content

Collaboration Server (server/)

Realtime collaboration server for Songbird. Manages project rooms, syncs file changes between connected clients, performs structured merges on .bird and JSON state files, and provides real-time presence features including Figma-style multiplayer cursors and optimistic mixer sync.
For the full deep-dive into collaboration architecture, see docs/collaboration.md.

Quick Start

# Install dependencies
npm install

# Start server (default port 8765)
npm start

# Development mode (auto-restart on changes)
npm run dev

# Custom port
PORT=9000 npm start

# Run merge engine tests
node test-merge.js

Files

FilePurpose
server.jsWebSocket server — room management (create/join via invite codes), push/pull sync, presence broadcasting, cursor relaying, merge orchestration
merge/bird-merge.jsStructured .bird file parser, serializer, and three-way merge at track-per-section granularity
merge/json-merge.jsRecursive deep-merge for daw.mixer.json (mixer) and daw.plugins.json (plugins). Handles arrays element-by-element
gitea/daw.club — React frontend for Gitea-based git hosting (see gitea/README.md)
mock-ws-bridge.mjsMock WebSocket bridge for standalone React UI development
test-merge.jsMerge engine tests — 7 tests covering parse, round-trip, auto-merge, and conflict resolution
package.jsonDependencies: ws (WebSocket), nanoid (invite codes)

Merge Strategy

  • .bird files: Parsed into structured tree (sig → tracks → arr → sections → tracks). Merged at track-per-section granularity. Two users editing different tracks in the same section auto-merge cleanly.
  • .mixer.json: Recursive deep-merge at the per-track-property level. Two users adjusting different mixer controls auto-merge.
  • .plugins.json: Same deep-merge strategy applied to plugin state.
  • Conflicts: All conflicts resolved via last-write-wins (the incoming push takes precedence).

Real-Time Features

Figma-Style Multiplayer Cursors

Each connected client broadcasts cursor position (track, beat) at throttled intervals. Other clients render colored cursor indicators with user names on the arrangement view. Cursor updates are relayed through the WebSocket server with no persistence.

Optimistic Mixer Sync

Mixer parameter changes (volume, pan, mute, solo) are broadcast optimistically to all connected clients. The sender’s change is applied locally immediately, and other clients receive the update via WebSocket. Conflicts are resolved via last-write-wins. The collabMixerSync.ts service on the React side handles debouncing and deduplication.

Built-In Tunnel

The Rust backend can start a built-in tunnel (via the collab.* sync-engine channel and songbird-collab) for zero-config remote collaboration — no port forwarding or ngrok required. The tunnel URL is shared via the collaboration panel’s invite flow.

Deployment

The server is a single Node.js process with no external dependencies (no database, no Redis). Works on any machine with Node.js 18+.
# Production with pm2
pm2 start server.js --name songbird-collab

# Or with systemd
# [Unit]
# Description=Songbird Collab Server
# [Service]
# ExecStart=/usr/bin/node /opt/songbird-collab/server.js
# Environment=PORT=8765
# [Install]
# WantedBy=multi-user.target
For the Gitea-based git hosting backend, see deploy/ for Fly.io and GCP deployment configurations.