{"slug": "show-hn-groovebox-self-hosted-music-library-integrated-with-discogs-and-tidal", "title": "Show HN: Groovebox – self-hosted music library integrated with Discogs and Tidal", "summary": "A developer released Groovebox, a self-hosted, local-first music archival engine that consolidates physical media from Discogs collections and wantlists with custom playlists into a portable SQLite database, featuring full-text search and a mobile-first web interface. The Go-based tool uses a pure standard library server, SQLite via modernc.org/sqlite, and FTS5 search, and supports Tailscale VPN for remote access. It provides REST APIs for managing playlists, tracks, artists, albums, and syncing with Discogs.", "body_md": "## Screen.Recording.2026-08-21.at.9.32.05.PM-1.mov\n\nA self-hosted, local-first music archival engine that consolidates physical media (Discogs collection & wantlist) and custom playlists into a single portable SQLite database with instant full-text search and a sleek mobile-first web interface.\n\n**Backend:** Go (`net/http`\n\n, pure standard library server)**Database:** SQLite via`modernc.org/sqlite`\n\n(Pure Go, CGO-free, portable single binary)**Search Engine:** SQLite FTS5 (Porter stemmer + unicode61 tokenizer for instant full-text search)**Frontend:** Vanilla HTML5 + CSS3 (Glassmorphism dark mode with Blueprint BP5) + Vanilla JavaScript**Features:** Collapsible sidebar, creation date playlist sorting, 2x2 grid collage playlist covers, Library view switching (All Songs, Artists with avatars, Albums grid, Dedicated Album & Artist pages), clickable track rows navigating to Album pages, SVG cover art fallback error handling, and Discogs + Qobuz store master release search links.**Networking:** Localhost & Tailscale VPN ready\n\n```\n# Build binary\ngo build -o groovebox .\n\n# Run Web Server (defaults to port 8080)\n./groovebox -port 8080\n./groovebox -sync-discogs\n```\n\nAccess the UI locally at `http://localhost:8080`\n\n.\n\n`GET /api/stats`\n\n- Total tracks, canonical albums, and playlists count.`GET /api/playlists?sort=[date_desc|date_asc|name_asc|name_desc]`\n\n- List playlists with track counts, creation dates, and 4 cover art URLs.`POST /api/playlists`\n\n- Create new internal playlist (`{name, description}`\n\n).`GET /api/playlists/:id`\n\n- Get tracks inside a specific playlist.`PUT /api/playlists/:id`\n\n- Update playlist title and description.`DELETE /api/playlists/:id`\n\n- Delete playlist and its track associations.`POST /api/playlists/:id/tracks`\n\n- Add track (`{track_id}`\n\n) to playlist.`DELETE /api/playlists/:id/tracks?position=X`\n\n- Remove track at position`X`\n\nfrom playlist.`GET /api/tracks`\n\n- Browse all songs in the library.`POST /api/tracks`\n\n- Add a new song to library (`{title, artist, album_title, duration_ms, spotify_id, cover_image_url}`\n\n).`GET /api/autocomplete`\n\n- Local database track/artist autocomplete.`GET /api/autocomplete/online`\n\n- Live global iTunes API autocomplete for auto-filling metadata & cover art.`GET /api/artists`\n\n- Browse all artists (aggregating albums & tracks) with cover art avatars.`GET /api/artists/:name`\n\n- Get dedicated artist detail view with albums grid & tracks.`GET /api/albums?filter=[collection|wantlist]&q=:query`\n\n- Browse canonical master albums. Optional filter by`collection`\n\n(in_collection=1, owned in Discogs; sorted by most-recently-added-to-collection first) or`wantlist`\n\n(in_wantlist=1). Optional`q`\n\nsearches title/artist.`GET /api/albums/counts`\n\n- Get`{all, collection, wantlist}`\n\nalbum counts for UI badge display.`GET /api/albums/:id`\n\n- Get dedicated album detail view (Discogs pressings table with thumbnails & tracklist).`GET /api/search?q=:query`\n\n- Instant FTS5 full-text search across songs, artists, and releases.`POST /api/sync/discogs`\n\n- Trigger async Discogs collection & wantlist sync.`POST /api/albums/dedupe`\n\n- Trigger async lossless master album deduplication (`DedupeAlbums`\n\n), merging duplicate albums matched by Discogs master ID, normalized title, or track overlap.`GET /api/sync/status`\n\n- Thread-safe live progress streaming (*stage*:`idle`\n\n/`collection`\n\n/`wantlist`\n\n/`deduping`\n\n/etc,*current_page*,*total_pages*,*items_fetched*,*last_synced_at*,*last_deduped_at*).\n\nTo access your music archive securely from your phone or laptop anywhere in the world without exposing ports to the public internet, deploy `groovebox`\n\nto your Home Server via [Tailscale](https://tailscale.com).\n\nCross-compile a CGO-free static binary from your Mac:\n\n```\n# For Linux x86_64 server\nGOOS=linux GOARCH=amd64 go build -o groovebox-linux .\n\n# For ARM64 server / Raspberry Pi 4/5\nGOOS=linux GOARCH=arm64 go build -o groovebox-arm64 .\n```\n\nCopy the executable, database, and public web assets to your home server:\n\n```\nscp groovebox-linux user@homeserver:/opt/groovebox/groovebox\nscp music.db user@homeserver:/opt/groovebox/music.db\nscp -r public user@homeserver:/opt/groovebox/public\n```\n\nOn your home server, create `/etc/systemd/system/groovebox.service`\n\n:\n\n```\n[Unit]\nDescription=Groovebox Archival System\nAfter=network.target\n\n[Service]\nType=simple\nUser=daniel\nWorkingDirectory=/opt/groovebox\nExecStart=/opt/groovebox/groovebox -port 8080 -db /opt/groovebox/music.db\nRestart=always\nRestartSec=5\n\n[Install]\nWantedBy=multi-user.target\n```\n\nEnable and start the service:\n\n```\nsudo systemctl daemon-reload\nsudo systemctl enable --now groovebox\n```\n\n- Ensure\n**Tailscale** is running on your home server:\n\n```\ntailscale status\n```\n\n- Note your home server's Tailscale hostname or IP (e.g.\n`homeserver.tail1234.ts.net`\n\nor`100.x.y.z`\n\n). - Open\n`http://homeserver.tail1234.ts.net:8080`\n\nor`http://100.x.y.z:8080`\n\nfrom any device on your Tailnet (iPhone, Mac, iPad).\n\n*(Optional)* Serve over HTTPS with standard port 443 using **Tailscale Serve**:\n\n```\nsudo tailscale serve --bg 8080\n```\n\nNow access securely at `https://homeserver.tail1234.ts.net`\n\non any device!\n\nTo visually inspect UI changes or capture layout screenshots end-to-end:\n\n```\nnpx -y playwright screenshot http://localhost:8080 screenshot.png\n```\n\n: 1-to-1 canonical master release entities (`albums`\n\n`discogs_master_id`\n\n, title, artist, release year, cover image,`has_vinyl`\n\n/`in_collection`\n\n/`in_wantlist`\n\nflags).: Specific Discogs physical pressings & digital entries (`release_versions`\n\n`album_id`\n\n,`discogs_release_id`\n\n, label, cat#, format, source).: Individual songs linked to canonical albums (title, artist, duration, Spotify ID, ISRC).`tracks`\n\n: Internal playlists.`playlists`\n\n: Ordered track mappings.`playlist_tracks`\n\n: FTS5 virtual table for fast searching.`search_fts`", "url": "https://wpnews.pro/news/show-hn-groovebox-self-hosted-music-library-integrated-with-discogs-and-tidal", "canonical_source": "https://github.com/danielfalbo/groovebox/", "published_at": "2026-08-21 20:37:44+00:00", "updated_at": "2026-08-21 21:14:25.748314+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools"], "entities": ["Groovebox", "Discogs", "Tidal", "SQLite", "Go", "Tailscale", "iTunes", "Qobuz"], "alternates": {"html": "https://wpnews.pro/news/show-hn-groovebox-self-hosted-music-library-integrated-with-discogs-and-tidal", "markdown": "https://wpnews.pro/news/show-hn-groovebox-self-hosted-music-library-integrated-with-discogs-and-tidal.md", "text": "https://wpnews.pro/news/show-hn-groovebox-self-hosted-music-library-integrated-with-discogs-and-tidal.txt", "jsonld": "https://wpnews.pro/news/show-hn-groovebox-self-hosted-music-library-integrated-with-discogs-and-tidal.jsonld"}}