Screen.Recording.2026-08-21.at.9.32.05.PM-1.mov #
A 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.
Backend: Go (net/http
, pure standard library server)Database: SQLite viamodernc.org/sqlite
(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 JavaScriptFeatures: 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
go build -o groovebox .
./groovebox -port 8080
./groovebox -sync-discogs
Access the UI locally at http://localhost:8080
.
GET /api/stats
-
Total tracks, canonical albums, and playlists count.
GET /api/playlists?sort=[date_desc|date_asc|name_asc|name_desc] -
List playlists with track counts, creation dates, and 4 cover art URLs.
POST /api/playlists -
Create new internal playlist (
{name, description}
).GET /api/playlists/:id
-
Get tracks inside a specific playlist.
PUT /api/playlists/:id -
Update playlist title and description.
DELETE /api/playlists/:id -
Delete playlist and its track associations.
POST /api/playlists/:id/tracks -
Add track (
{track_id}
) to playlist.DELETE /api/playlists/:id/tracks?position=X
- Remove track at position
X
from playlist.GET /api/tracks
-
Browse all songs in the library.
POST /api/tracks -
Add a new song to library (
{title, artist, album_title, duration_ms, spotify_id, cover_image_url}
).GET /api/autocomplete
-
Local database track/artist autocomplete.
GET /api/autocomplete/online -
Live global iTunes API autocomplete for auto-filling metadata & cover art.
GET /api/artists -
Browse all artists (aggregating albums & tracks) with cover art avatars.
GET /api/artists/:name -
Get dedicated artist detail view with albums grid & tracks.
GET /api/albums?filter=[collection|wantlist]&q=:query -
Browse canonical master albums. Optional filter by
collection
(in_collection=1, owned in Discogs; sorted by most-recently-added-to-collection first) orwantlist
(in_wantlist=1). Optionalq
searches title/artist.GET /api/albums/counts
- Get
{all, collection, wantlist}
album counts for UI badge display.GET /api/albums/:id
-
Get dedicated album detail view (Discogs pressings table with thumbnails & tracklist).
GET /api/search?q=:query -
Instant FTS5 full-text search across songs, artists, and releases.
POST /api/sync/discogs -
Trigger async Discogs collection & wantlist sync.
POST /api/albums/dedupe -
Trigger async lossless master album deduplication (
DedupeAlbums
), merging duplicate albums matched by Discogs master ID, normalized title, or track overlap.GET /api/sync/status
- Thread-safe live progress streaming (stage:
idle
/collection
/wantlist
/deduping
/etc,current_page,total_pages,items_fetched,last_synced_at,last_deduped_at).
To access your music archive securely from your phone or laptop anywhere in the world without exposing ports to the public internet, deploy groovebox
to your Home Server via Tailscale.
Cross-compile a CGO-free static binary from your Mac:
GOOS=linux GOARCH=amd64 go build -o groovebox-linux .
GOOS=linux GOARCH=arm64 go build -o groovebox-arm64 .
Copy the executable, database, and public web assets to your home server:
scp groovebox-linux user@homeserver:/opt/groovebox/groovebox
scp music.db user@homeserver:/opt/groovebox/music.db
scp -r public user@homeserver:/opt/groovebox/public
On your home server, create /etc/systemd/system/groovebox.service
:
[Unit]
Description=Groovebox Archival System
After=network.target
[Service]
Type=simple
User=daniel
WorkingDirectory=/opt/groovebox
ExecStart=/opt/groovebox/groovebox -port 8080 -db /opt/groovebox/music.db
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable --now groovebox
- Ensure Tailscale is running on your home server:
tailscale status
- Note your home server's Tailscale hostname or IP (e.g.
homeserver.tail1234.ts.net
or100.x.y.z
). - Open
http://homeserver.tail1234.ts.net:8080
orhttp://100.x.y.z:8080
from any device on your Tailnet (iPhone, Mac, iPad).
(Optional) Serve over HTTPS with standard port 443 using Tailscale Serve:
sudo tailscale serve --bg 8080
Now access securely at https://homeserver.tail1234.ts.net
on any device!
To visually inspect UI changes or capture layout screenshots end-to-end:
npx -y playwright screenshot http://localhost:8080 screenshot.png
: 1-to-1 canonical master release entities (albums
discogs_master_id
, title, artist, release year, cover image,has_vinyl
/in_collection
/in_wantlist
flags).: Specific Discogs physical pressings & digital entries (release_versions
album_id
,discogs_release_id
, label, cat#, format, source).: Individual songs linked to canonical albums (title, artist, duration, Spotify ID, ISRC).tracks
: Internal playlists.playlists
: Ordered track mappings.playlist_tracks
: FTS5 virtual table for fast searching.search_fts