Rebrand as Playlink with a new sunset theme

- Name: Playlink in the UI, page title, footer, messages and README
  (file names like playlink.db and .playlink-trash are unchanged).
- Theme: plum-black surfaces with a coral-to-pink accent, a soft glow
  behind the page, gradient primary buttons, toggles and progress bars,
  accent focus rings and slim scrollbars.
- New logo (beamed notes on the brand gradient) and a Play/link wordmark.
- Inter variable font, bundled so it works under the strict CSP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
cdnutterandClaude Opus 5.5 committed 2026-09-30 15:49:21 -07:00
1 parent 30fab3a208
commit c98eb2f41d
23 files changed
+164 -77

No files matched your search

+10 -10
View File
@@ -1,6 +1,6 @@
# playlink
# Playlink
Deduplicate music libraries with hardlinks. playlink finds songs that exist in both a **master** library (e.g. your full `Albums`) and a
Deduplicate music libraries with hardlinks. Playlink finds songs that exist in both a **master** library (e.g. your full `Albums`) and a
**slave** library (e.g. a curated `Singles` library) and replaces the slave copy with a hardlink to the master copy. Each song then takes
up disk space only once, while both libraries keep looking exactly the same to Plex, Navidrome, Jellyfin and other media servers.
@@ -13,7 +13,7 @@ Files are matched by their **path relative to each library root**. Any folder la
`Genre/Artist/Title.ext`, flat, …) as long as both libraries use the same one, so that a song sits at the same relative
path on both sides. The fallbacks below catch small differences, and a scan warns when the two layouts don't line up.
| Situation | What playlink does |
| Situation | What Playlink does |
|---|---|
| Same relative path, **byte-identical** | Status `identical`. Link with one click, in bulk, or automatically after each scan. |
| Same path, **different bytes** (re-encode, different tags) | Status `different`. Manual review with a codec/bitrate/bit-depth/duration comparison. |
@@ -51,7 +51,7 @@ Safeguards:
codec-weighted bitrate (Opus and AAC count for more per kbps than MP3). You then have three choices:
- **Upgrade / link to master copy.** The default. When the master copy is better, the match is flagged as an **upgrade** and listed
under the *Upgrades* filter. The master is kept because it belongs to a complete album. If the master is *lower* quality, playlink
under the *Upgrades* filter. The master is kept because it belongs to a complete album. If the master is *lower* quality, Playlink
warns you and asks for explicit confirmation.
- **Use slave copy as master.** The override. The slave's better file replaces the master file, the old master file is quarantined, and both
libraries share the better file.
@@ -76,14 +76,14 @@ Each row has the match status and type, a recommendation, both paths, where link
bit depth and duration for both sides, the quality verdict and any notes. The file opens cleanly in Excel, Numbers and LibreOffice
(UTF-8, and cells a spreadsheet would treat as formulas are escaped).
**Folders without music** (the *Cleanup* tab). Choose the slave or master library and **Find folders**: playlink lists the top-most
**Folders without music** (the *Cleanup* tab). Choose the slave or master library and **Find folders**: Playlink lists the top-most
folders with no music file anywhere inside them (music = the pair's file extensions), such as album folders left empty after linking or
ones holding only a cover or playlist, with what they still contain. Empty folders are pre-selected, folders that still hold files are
not. **Remove** asks for confirmation (and an extra acknowledgement when the folders still hold files), re-checks each folder for music
right before touching it, and moves it into the quarantine instead of deleting it: it can be restored from History until the retention
period purges it. The library root, the quarantine and hidden folders are never listed, and dry run applies.
**Backups** (Settings → Backups), similar to Sonarr. A backup is a zip of playlink's database (settings, library pairs, scan results and
**Backups** (Settings → Backups), similar to Sonarr. A backup is a zip of Playlink's database (settings, library pairs, scan results and
history, not music files) taken safely while the app runs. Choose a folder (default `/config/backups`), a schedule (off, every 1, 3, 7
or 14 days) and a retention period for scheduled backups; **Back up now** makes a manual one (kept until deleted). Backups can be
downloaded, deleted, or restored, also from an uploaded zip. A restore is validated first (damaged backups and ones from a newer version
@@ -92,12 +92,12 @@ policy brings it back automatically. Optionally, **back up before every action i
before scans change files), never one per file; if that backup fails the action does not run, and the newest 10 are kept.
**Build mode** covers the "start fresh" workflow. Point the slave at an empty folder, browse the master library, tick the
folders or songs you want, and playlink hardlinks them in at the same relative path. **Remove** deletes slave files, but only ones that are hardlinks of the
folders or songs you want, and Playlink hardlinks them in at the same relative path. **Remove** deletes slave files, but only ones that are hardlinks of the
master file.
## Safety model
playlink is built so that no user data is ever lost, even if it crashes or loses power mid-operation:
Playlink is built so that no user data is ever lost, even if it crashes or loses power mid-operation:
- **Dry run is on by default.** Every action is recorded in Activity as *planned* until you switch to live mode.
- **Files are re-verified before any change.** Both files must still be plain regular files with the same inode, size and mtime that
@@ -159,7 +159,7 @@ Run a scan, check the Review tab, and turn off dry run once the planned actions
- **Both libraries must be visible through one bind mount.** Docker bind mounts are separate mount points, and `link(2)` fails across
them (`EXDEV`) even when they are on the same disk. Mount a common parent folder, as shown above.
- **Both libraries must be on the same filesystem.** playlink checks this when you save a pair and before every operation.
- **Both libraries must be on the same filesystem.** Playlink checks this when you save a pair and before every operation.
- **Unraid:** hardlinks through `/mnt/user` require *Settings → Global Share Settings → Tunable (support Hard Links)* to be *Yes*
(the default). If the share uses a cache pool, make sure your mover preserves hardlinks. Every link is verified by inode, and a
failed link aborts safely with the original untouched.
@@ -176,7 +176,7 @@ Run a scan, check the Review tab, and turn off dry run once the planned actions
| `PLAYLINK_LOG_LEVEL` | `info` | `debug` for verbose logs. |
**Hide quarantine from Plex** (Settings → Media servers) writes a `.plexignore` into each pair's quarantine folder so Plex does not
pick up quarantined songs; new quarantine folders get it automatically. Turning it off removes the file again, but only if playlink
pick up quarantined songs; new quarantine folders get it automatically. Turning it off removes the file again, but only if Playlink
created it.
Per-pair settings (in the UI) are file extensions, auto-link, approximate matching and its threshold, scan interval, quarantine folder,