543031e48cebb82c468b85db39bf14a5612e1d47
next() did `queue.slice(idx + 1)`, so the current track was always queue[0]. prev()'s `idx > 0` guard could therefore never pass after an auto-advance — Previous did nothing, ever — and repeat: 'all' jumped to queue[0], which is the track that just finished, looping the last track of an album instead of restarting it. Replaced with a currentIndex cursor; the queue is no longer trimmed behind the playhead. The old slice did serve a purpose — bounding Vibe-prefetch growth — so that is preserved as a MAX_HISTORY = 50 cap that drops the oldest entries and re-bases the index, rather than dropped outright. setQueue/playTrack/setCurrentTrack recompute the cursor, next()/prev() fall back to findIndex if it drifts, and shuffle now picks by index so the cursor stays valid. Consumer audit: NowPlayingPanel and Vibe.tsx already derived position via findIndex and needed no change. TrackRow.handlePlay did `setQueue(queue.slice(index))`, which re-broke prev at the point of click even with the store fixed; it now passes the intact queue. This commit also includes a pre-existing uncommitted fix from the working tree (not authored by Claude): the end-of-queue auto-resume loop, which stops playback at the end of the queue instead of restarting. It is correct and independent of the cursor bug, and is preserved verbatim here. REVIEW-2026-07-30.md finding 7. 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
docker-compose up -d
Description
Languages
TypeScript
95.5%
PLpgSQL
2.4%
CSS
1.4%
JavaScript
0.4%
Dockerfile
0.2%