master
Six bugs in the single transport and in how a browser registers as a device, then the feature the fourth one was hiding. A watching device keeps its own audio paused, so every control that read `isPlaying` from the store drew a Play button while the desktop played — and sent `play` when it was pressed. The transport now carries one `playing` value: the remote state while presses are being forwarded, the local one otherwise. Two tabs of one browser shared a stored device id, which made them one device that ran every command twice and played two copies of the audio. A device id is now held by whichever stream has it open: registration refuses to hand back a busy id, and each tab keeps its own in `sessionStorage`. A device that was only showing what another one plays still pointed an audio element at the stream, downloading tracks it would never play. It now loads nothing while the audio is elsewhere, and reloads the moment it comes back. Commands were accepted for an owner with no stream to receive them on, so a killed tab answered a press with a success it never got. Ownership outlives a closed stream deliberately; delivery does not. The event stream never called `reply.hijack()`, leaving Fastify waiting on a handler that resolves with nothing. And the Vibe: `setQueue` is an ownership handoff, so a snapshot from another device dropped the advance handler that asks the server for the next track. A session moved to a phone became a fixed list of the hundred tracks that happened to be synced. Vibe control now follows the audio — the snapshot carries the session id, the device losing the audio stops driving, and the one gaining it resumes the durable session and takes over replanning. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
muzick
A high-performance, distributed music orchestration and recommendation platform.
Overview
muzick is designed to manage a local music library while providing an "infinite vibe" listening experience. It bridges the gap between a local filesystem and advanced discovery engines through a tiered recommendation architecture.
Tech Stack
Frontend
- Framework: React
- Routing: TanStack Router
- Data Fetching: TanStack Query (with Look-ahead Buffering)
- State Management: Zustand (for Session/Vibe state)
- Styling: CSS Variables (Customizable Themes)
Backend
- Runtime: Node.js / TypeScript
- Framework: Fastify
- Task Queue: BullMQ (via Redis)
- Search: Typesense
Infrastructure & Data
- Database: PostgreSQL (Source of truth for metadata, relationships, and session state)
- Cache/Queue: Redis
- Audio Analysis: Essentia (via Worker processes)
- External Metadata: MusicBrainz, Discogs, LRCLib, Cover Art Archive
Core Concepts
- The Rolling Vibe: A continuous, evolving stream of music that uses a "Rolling Window" of tracks. It interleaves owned library tracks with high-probability "probation" tracks (external discoveries).
- The Dislike Lifecycle: A multi-stage state machine that protects users from accidental deletions while ensuring the library stays clean.
- Tiered Similarity: Instant metadata-based matches, followed by deep audio-feature similarity.
Getting Started
Prerequisites
- Docker & Docker Compose
Running Locally
Vibe uses the same per-user identity convention as the rest of the API:
x-user-id when supplied, otherwise the local default user. Each user's Vibe
session and listening history are isolated from other users.
docker-compose up -d
Description
Languages
TypeScript
95.5%
PLpgSQL
2.4%
CSS
1.4%
JavaScript
0.4%
Dockerfile
0.2%