diff --git a/webui/static/docs.js b/webui/static/docs.js
index 77c19b7d..6b80bfb2 100644
--- a/webui/static/docs.js
+++ b/webui/static/docs.js
@@ -45,7 +45,7 @@ const DOCS_SECTIONS = [
content: () => `
Overview
-
SoulSync is a self-hosted music download, sync, and library management platform. It connects to Spotify, Apple Music/iTunes, Deezer, Tidal, Qobuz, YouTube, and Beatport for metadata, and downloads from Soulseek, YouTube, Tidal, Qobuz, HiFi, and Deezer. Your library is served through Plex, Jellyfin, or Navidrome.
+
SoulSync is a self-hosted music download, sync, and library management platform. It connects to Spotify, Apple Music/iTunes, Deezer, Discogs, Tidal, Qobuz, YouTube, and Beatport for metadata, and downloads from Soulseek, YouTube, Tidal, Qobuz, HiFi, and Deezer. Your library is served through Plex, Jellyfin/Emby, or Navidrome.
${docsImg('gs-overview.jpg', 'SoulSync dashboard overview')}
🎵 Download Music
Search and download tracks in FLAC, MP3, and more from 6 sources (Soulseek, YouTube, Tidal, Qobuz, HiFi, Deezer), with automatic metadata tagging and file organization.
@@ -81,9 +81,10 @@ const DOCS_SECTIONS = [
| Tidal | Download source + playlist import + enrichment | OAuth — Client ID + Secret |
| Qobuz | Download source + enrichment | Username + Password (app ID auto-fetched) |
| HiFi | Download source — free lossless via community API | None |
-
| Deezer | Download source + metadata fallback | ARL cookie token |
+
| Deezer | Download source + metadata fallback + user playlists | ARL cookie token |
+
| Discogs | Enrichment — genres, styles, labels, catalog numbers, community ratings | Personal Access Token (free) |
| Plex | Media server — library scanning, metadata sync, audio streaming | URL + Token |
-
| Jellyfin | Media server — library scanning, audio streaming | URL + API Key |
+
| Jellyfin / Emby | Media server — library scanning, playlist sync, audio streaming | URL + API Key |
| Navidrome | Media server — auto-detects changes, audio streaming | URL + Username + Password |
| Last.fm | Enrichment — listener stats, tags, bios, similar artists | API Key |
| Genius | Enrichment — lyrics, descriptions, alternate names | Access Token |
@@ -459,6 +460,8 @@ const DOCS_SECTIONS = [
icon: '/static/dashboard.jpg',
children: [
{ id: 'dash-overview', title: 'Overview & Stats' },
+ { id: 'dash-history', title: 'Download History' },
+ { id: 'dash-global-search', title: 'Global Search' },
{ id: 'dash-workers', title: 'Enrichment Workers' },
{ id: 'dash-tools', title: 'Tool Cards' },
{ id: 'dash-retag', title: 'Retag Tool' },
@@ -473,6 +476,28 @@ const DOCS_SECTIONS = [
Stats update in real-time via WebSocket — no page refresh needed.
${docsImg('dash-overview.jpg', 'Dashboard overview')}
+
+
Download History
+
Click Download History in the Recent Activity section to view a persistent log of every downloaded and imported track. Each entry is a collapsible card — click to expand and reveal source provenance details.
+
+ - Expected vs Downloaded — Shows what you asked for and what the source actually provided. Mismatches are highlighted in red.
+ - Source file — The original filename from the peer (Soulseek) or internal ID (streaming sources)
+ - AcoustID badge — Color-coded verification result: Verified (green), Failed (red), Skipped (orange), Off (gray)
+ - Source badges — Download source (Soulseek/Tidal/Qobuz/YouTube/HiFi/Deezer) and quality (FLAC/MP3/etc.)
+ - Tabs — Switch between Downloads and Server Imports. Source breakdown bar shows counts per download source.
+
+
+
+
Global Search
+
The search bar at the top of every page is the Global Search. Type any artist, album, or track name to search across all configured metadata sources. Results appear in a dropdown organized by category.
+
+ - Library artists — Artists already in your library (shown first with a "Library" badge)
+ - Artists — External artist results from Spotify/iTunes/Deezer
+ - Albums & Singles — Click to open the download modal directly
+ - Tracks — Click to open the download modal, or use the play button to stream
+ - Downloads started from Global Search create download bubbles on the Dashboard and Search page, same as Enhanced Search
+
+
Enrichment Workers
The header bar contains enrichment worker icons for each metadata service. Hover over any icon to see its current status, what item it's processing, and progress counts (e.g., "142/500 matched").
@@ -544,8 +569,31 @@ const DOCS_SECTIONS = [
Duplicate Cleaner — Identifies duplicate tracks by comparing title, artist, album, and duration. Lets you review duplicates and choose which version to keep (typically the higher-quality one). Frees disk space by removing redundant files.
Database Updater — Refreshes your library database by scanning your media server. Incremental mode only adds new content; Full Refresh rebuilds the entire database. Deep Scan performs a full comparison without losing any enrichment data from services.
Metadata Updater — Triggers all enrichment workers simultaneously with reset flags, forcing them to re-check every item in your library against all connected services (MusicBrainz, Spotify, iTunes, Last.fm, Deezer, AudioDB, Genius, Tidal, Qobuz). Useful after connecting a new service or when metadata seems incomplete.
-
Repair Worker — Background service that scans recently downloaded folders and repairs track metadata. It reads album IDs from file tags, fetches official tracklists from Spotify or MusicBrainz, and fixes incorrect or missing track numbers. Runs automatically after batch downloads complete and can be paused/resumed from the dashboard.
+
Repair Worker — Background service with 16 automated repair jobs. Open Library Maintenance from the dashboard to view all jobs, enable/disable them, and trigger manual runs. Each job runs on a configurable schedule and creates findings that can be reviewed and fixed individually or in bulk.
+
Repair Jobs:
+
+ | Job | What It Does |
+
+ | Track Number Repair | Fixes missing or incorrect track numbers by comparing against official tracklists |
+ | Orphan File Detector | Finds audio files in your transfer folder not tracked in the database. Can move to staging or delete. |
+ | Dead File Cleaner | Removes database entries pointing to files that no longer exist on disk |
+ | Duplicate Detector | Identifies duplicate tracks by fingerprint or metadata match |
+ | AcoustID Scanner | Batch audio fingerprint verification across your library |
+ | Missing Cover Art | Detects albums and tracks without embedded artwork and fetches it |
+ | Metadata Gap Filler | Completes missing metadata fields (genre, year, etc.) from connected services |
+ | Album Completeness | Verifies you have all tracks for each album and flags incomplete ones |
+ | Fake Lossless Detector | Identifies FLAC files that don't actually contain high-frequency audio content |
+ | Library Reorganize | Restructures library folders to match your configured path templates |
+ | MBID Mismatch Detector | Verifies MusicBrainz IDs are still accurate and flags mismatches |
+ | Single Album Dedup | Removes redundant single-track albums when the track exists on a full album |
+ | Album Tag Consistency | Standardizes album tags across all tracks in the same album |
+ | Live Commentary Cleaner | Detects and flags non-music content (commentary, interviews) in your library |
+ | Cache Evictor | Cleans expired metadata cache entries to free database space |
+ | Lossy Converter | Converts lossy files to alternative formats based on your preferences |
+
+
+
⚠️Mass orphan safety: If the orphan detector flags more than 50% of files as orphans, it triggers a "Witness Me" confirmation dialog requiring you to type the phrase before any deletions proceed. This prevents accidental mass deletion from path mismatches.
Activity Feed
@@ -565,13 +613,15 @@ const DOCS_SECTIONS = [
{ id: 'sync-youtube', title: 'YouTube Playlists' },
{ id: 'sync-tidal', title: 'Tidal Playlists' },
{ id: 'sync-deezer', title: 'Deezer Playlists' },
+ { id: 'sync-deezer-link', title: 'Deezer Link' },
{ id: 'sync-listenbrainz', title: 'ListenBrainz' },
{ id: 'sync-beatport', title: 'Beatport' },
{ id: 'sync-import-file', title: 'Import from File' },
{ id: 'sync-mirrored', title: 'Mirrored Playlists' },
{ id: 'sync-history', title: 'Sync History' },
{ id: 'sync-m3u', title: 'M3U Export' },
- { id: 'sync-discovery', title: 'Discovery Pipeline' }
+ { id: 'sync-discovery', title: 'Discovery Pipeline' },
+ { id: 'sync-explorer', title: 'Playlist Explorer' }
],
content: () => `
@@ -640,12 +690,26 @@ const DOCS_SECTIONS = [
Deezer Playlists
-
Import Deezer playlists by URL. Paste a Deezer playlist URL, click Load Playlist, and SoulSync parses the tracks for discovery and download. Tracks go through the same discovery pipeline as YouTube and Tidal playlists.
+
If you have a Deezer ARL token configured (Settings > Downloads), the Deezer tab shows all your personal playlists — identical to how Spotify playlists work. Click Refresh to load your playlists, then click any playlist to view tracks and download.
+
+ - Requires ARL token (a browser cookie from deezer.com — configure in Settings > Downloads)
+ - Click Sync / Download to open the playlist details modal with full track listing
+ - Click Download Missing Tracks to analyze your library and download what's missing
+ - Click Sync Playlist to sync tracks to your media server
+ - Tracks include full album metadata with release dates, cover art, and proper organization
+ - No discovery step needed — tracks go directly to download (like Spotify)
+ - Track data is cached after first load for instant subsequent access
+
+
💡The ARL token is the same one used for Deezer downloads. If you already have Deezer configured as a download source, your playlists will appear automatically.
+
+
+
Deezer Link
+
Import any public Deezer playlist by URL without needing an ARL token. Paste a Deezer playlist URL, click Load Playlist, and SoulSync parses the tracks for discovery and download.
- - Paste any
deezer.com/playlist/... URL
- - Track matching uses the same fuzzy discovery pipeline
- - Previously loaded URLs appear in the history bar
- - Loaded playlists are mirrored for persistent state
+ - Paste any
deezer.com/playlist/... URL or raw playlist ID
+ - Track matching uses the same fuzzy discovery pipeline as YouTube and Tidal
+ - Previously loaded URLs appear in the history bar for quick re-access
+ - Loaded playlists are automatically mirrored for persistent state
@@ -695,6 +759,10 @@ const DOCS_SECTIONS = [
💡Chain automations for hands-free operation: Refresh Playlist → Playlist Changed → Discover → Discovery Complete → Sync
+
+
Playlist Explorer
+
A visual tree-based browser for exploring playlists across all sources. Navigate through your server playlists, Spotify playlists, and mirrored playlists in a unified interface. Click any playlist to expand and view its tracks, then download or sync directly.
+
`
},
{
@@ -804,7 +872,9 @@ const DOCS_SECTIONS = [
{ id: 'disc-playlists', title: 'Discovery Playlists' },
{ id: 'disc-build', title: 'Build Custom Playlist' },
{ id: 'disc-seasonal', title: 'Seasonal & Curated' },
- { id: 'disc-timemachine', title: 'Time Machine' }
+ { id: 'disc-timemachine', title: 'Time Machine' },
+ { id: 'disc-artist-map', title: 'Artist Map' },
+ { id: 'disc-stats', title: 'Listening Stats' }
],
content: () => `
@@ -860,6 +930,27 @@ const DOCS_SECTIONS = [
Browse discovery pool content by decade — tabs from the 1950s through the 2020s. Each decade pulls top tracks from pool artists active in that era.
${docsImg('disc-time-machine.jpg', 'Time Machine decade browser')}
+
+
Artist Map
+
Three interactive canvas-based visualization modes for exploring artist relationships. Accessed from the Discover page.
+
+ - Watchlist Constellation — Your watched artists as large nodes with similar artists orbiting around them. Reveals connections you might not have noticed.
+ - Genre Map — Browse all artists by genre with a sidebar picker. Ring-packed clusters, no artist cap. Great for exploring genres you don't normally listen to.
+ - Artist Explorer — Deep-dive any artist. Ring 1 shows direct similar artists, Ring 2 shows the extended network. Exploring an unknown artist fetches similar artists in real-time and caches them.
+
+
Controls: Mouse wheel to zoom, click to explore, hover for tooltips with genre tags. Keyboard shortcuts: ? for help, F to fit view, S to search.
+
+
+
Listening Stats
+
The Stats page shows analytics about your music library and listening activity. Requires ListenBrainz or Last.fm scrobbling to be enabled for listening data.
+
+ - Library overview — Total artists, albums, tracks, total file size, format distribution
+ - Top artists, albums, and tracks — Ranked by play count or library presence
+ - Genre distribution — Visual breakdown of genres across your library
+ - Recent additions — Latest tracks and albums added to your library
+ - Listening timeline — Activity over time when scrobbling is configured
+
+
`
},
{
@@ -1079,13 +1170,16 @@ const DOCS_SECTIONS = [
{ id: 'lib-matching', title: 'Service Matching' },
{ id: 'lib-tags', title: 'Write Tags to File' },
{ id: 'lib-bulk', title: 'Bulk Operations' },
- { id: 'lib-missing', title: 'Download Missing Tracks' }
+ { id: 'lib-missing', title: 'Download Missing Tracks' },
+ { id: 'lib-smart-delete', title: 'Smart Delete' },
+ { id: 'lib-redownload', title: 'Track Redownload' },
+ { id: 'lib-issues', title: 'Library Issues' }
],
content: () => `
Standard View
The Library page shows all artists in your collection as cards with images, album/track counts, and service badges (Spotify, MusicBrainz, Deezer, AudioDB, iTunes, Last.fm, Genius, Tidal, Qobuz) indicating which services have matched this artist.
-
Use the search bar, alphabet navigation (A–Z, #), and watchlist filter (All/Watched/Unwatched) to browse. Click any artist card to view their discography.
+
Use the search bar, alphabet navigation (A–Z, #), watchlist filter (All/Watched/Unwatched), and metadata source filter to browse. The source filter lets you find artists unmatched to a specific service (e.g. "No Discogs" shows artists missing a Discogs match) or matched to one (e.g. "Has Spotify"). Click any artist card to view their discography.
The artist detail page shows albums, EPs, and singles as cards with completion percentages. Filter by category, content type (live/compilations/featured), or status (owned/missing). At the top, View on buttons link to the artist on each matched external service.
${docsImg('lib-standard.jpg', 'Library artist grid')}
@@ -1104,7 +1198,7 @@ const DOCS_SECTIONS = [
Service Matching
-
In the Enhanced view, each artist, album, and track shows match status chips for all 9 services. Click any chip to manually search and link the correct external ID. Run per-service enrichment from the dropdown to pull in metadata from a specific source.
+
In the Enhanced view, each artist, album, and track shows match status chips for all 10 services (Spotify, MusicBrainz, Deezer, Discogs, AudioDB, iTunes, Last.fm, Genius, Tidal, Qobuz). Click any chip to manually search and link the correct external ID. Run per-service enrichment from the Enrich dropdown to pull in metadata from a specific source.
Matched services show as clickable badges linking to the entity on that service's website.
+
+
Smart Delete
+
Right-click or use the delete action on any track to open the Smart Delete dialog. Three options are available:
+
+ - Remove from Library — Removes the track from SoulSync's database only. The audio file on disk is not touched. Use this if you want to clean up the database without losing files.
+ - Delete File Too — Removes the database entry AND deletes the audio file from disk. Irreversible.
+ - Delete & Blacklist — Removes and deletes the file, then adds it to the download blacklist so it won't be re-downloaded by the wishlist or automation system.
+
+
+
+
Track Redownload
+
Redownload a specific track from your library with a different source or quality. A 3-step wizard guides you through:
+
+ - Choose metadata source — Confirm the correct track identity (Spotify, iTunes, or Deezer match)
+ - Choose download source — Search across all configured download sources (Soulseek, Tidal, Qobuz, YouTube, HiFi, Deezer) and pick a specific result
+ - Download & replace — The new file replaces the existing one with updated metadata and tags
+
+
+
+
Library Issues
+
The Issues page tracks problems detected in your library by the repair worker. Issues are categorized by type and severity:
+
+ - Orphan files — Audio files in your transfer folder not tracked in the database
+ - Dead references — Database entries pointing to files that no longer exist on disk
+ - Duplicate tracks — Multiple copies of the same track detected by fingerprint or metadata
+ - Missing cover art — Albums or tracks without embedded artwork
+ - Metadata gaps — Tracks with incomplete metadata (missing genre, year, etc.)
+ - Fake lossless — Files labeled as FLAC but with audio that doesn't actually contain high-frequency content
+
+
Each issue can be fixed individually or in bulk. Orphan files can be moved to staging (safe, reversible) or deleted. Mass deletions (50+ files) require typing "witness me" to confirm.
+
`
},
{
@@ -1257,7 +1382,8 @@ const DOCS_SECTIONS = [
{ id: 'set-download', title: 'Download Settings' },
{ id: 'set-processing', title: 'Processing & Organization' },
{ id: 'set-quality', title: 'Quality Profiles' },
- { id: 'set-other', title: 'Other Settings' }
+ { id: 'set-other', title: 'Other Settings' },
+ { id: 'set-db-maintenance', title: 'Database Maintenance' }
],
content: () => `
@@ -1271,9 +1397,10 @@ const DOCS_SECTIONS = [
Genius — Access token from genius.com/api-clients
Qobuz — Username + Password (app ID is auto-fetched)
HiFi — No credentials needed, uses community-run API instances. Test Connection to verify.
- Deezer — ARL cookie token from your browser (log into deezer.com → DevTools → Cookies → copy arl)
- AcoustID — API key from acoustid.org (enables fingerprint verification)
- ListenBrainz — Base URL + token for listening history and playlist import
+ Deezer — ARL cookie token from your browser (log into deezer.com → DevTools → Cookies → copy arl). Used for downloads AND user playlist access.
+ Discogs — Personal Access Token from discogs.com/settings/developers (free, no app registration needed). Provides genres, styles, labels, catalog numbers, and community ratings.
+ AcoustID — API key from acoustid.org (enables fingerprint verification of downloaded files)
+ ListenBrainz — Base URL + token for listening history, scrobbling, and playlist import
@@ -1335,6 +1462,15 @@ const DOCS_SECTIONS = [
WebSocket — Real-time status updates are delivered via WebSocket. All downloads, enrichment progress, scan status, and system events push to the UI without polling.
+
+
Database Maintenance
+
In Settings > Advanced, the Database Maintenance section shows your database size, free (reclaimable) pages, and auto-vacuum mode. Two operations are available:
+
+ - Compact Database (VACUUM) — Rewrites the entire database file to reclaim unused space from deleted records. Locks the database during operation and may take over a minute on large databases. Shows elapsed time and space saved when complete.
+ - Enable Incremental Vacuum — Switches SQLite to incremental auto-vacuum mode, which reclaims freed pages automatically in small batches. Requires a one-time full VACUUM to activate. After enabled, the button grays out. This is the recommended approach for large databases.
+
+
⚠️VACUUM requires temporary disk space equal to the database size. For a 5 GB database, ensure at least 5 GB free space before running.
+
`
},
{