Important
Note
The first start rearranges your locations, once. Every distinct location in a collection becomes a shelf (see below). Spellings that only differ by case or spaces are merged on the way: Living room, living room and LIVING ROOM end up as one shelf, and the items that used the odd spellings are moved onto it. A location made only of spaces is cleared. Nothing else about your items changes, and a second start does nothing more.
Hi, everyone! Sorry for the wait... I've been really busy lately. But to make it up to you, here's the biggest release since 3.0. Thirteen pull requests from five people, three new ways to look at a collection, lists, a second games database, board games, and a long list of the small things you asked for.
Thank you @Siebe-Uy, @Sbax, @ArtwoXYZ, @RobertClarke64 and @teaboyteaboy :D
🗄 Your Collection, on a Shelf
The collection page now has three views, switched from the toolbar and remembered per browser:
- Grid, the one you know.
- Table, for the ones who asked for a spreadsheet: one line per item, no images to load, stripes and a clear hover. The info and location fold under the title on phones.
- Shelf, the new one: your items drawn standing on their spine, title written along it, at the real height of their format (a vinyl is taller than a CD, a DVD sits in between).
Shelves come from your locations: each one becomes a shelf in a piece of furniture you can then arrange. Editors can build furniture (cubes or rows, how many columns, how many shelves), rename and reorder shelves, drag spines from one shelf to another, and file items away from a shelf picker on the item page or in bulk from the selection bar. Items with no location wait in an "unsorted" area under the furniture. On a phone the furniture folds into one band per shelf, and share links show it read-only.
And to land where you actually work, Settings now let you pick the collection, the page and the view DVinyl opens on at startup. An admin can set it for another member from the instance panel. Asked by @chibashr and @LordChabelo.
📋 Lists and Playlists
Gather items into lists ("Backlog", "Finished in 2026", "To lend to Marc") and tracks into playlists. Lists belong to the collection, like its shelves: every member reads them, editors arrange them.
- Add from the item page, from a track's modal, or from the selection bar for many items at once.
- Move lines up and down to set the order. If someone else changed the list in the meantime, the move is refused instead of dropping a line.
- Playlists are a table of tracks you can filter by text, rating and BPM range, and sort by column.
- Lists travel with backups, and a track keeps its identity through a Discogs refresh.
Share links don't show lists yet: baby steps, as @driph put it when asking for lists. Playlists were a request from @raorm88.
ℹ️ An Info Page for Each Collection
Each collection can have a page of its own, written in Markdown, with images and a lightbox: what the collection is, how it's sorted, where to find things, a few links. You choose whether visitors with a share link can see it, which makes it a nice landing page for a QR code on a shelf. Links are restricted to http(s), mailto and pages of your own instance.
Asked by @jws5406.
🎮 Games: ScreenScraper, Completion Times and Board Games
ScreenScraper is the second source for video games, next to IGDB. It knows MS-DOS, arcade and the 8 and 16-bit consoles far better than IGDB does. Pick it on the add page, choose the system you're looking in (seconds instead of a minute for a search across all systems), and the system you picked is remembered.
- The official Docker image already carries DVinyl's developer credentials, so there is nothing to set up. Adding your own free screenscraper.fr account in
.env(SCREENSCRAPER_USER/SCREENSCRAPER_PASSWORD) raises your daily quota. Building from source needs a developer pair of your own, see the API keys doc. - CSV imports use each row's platform to search the right system, and the import screen says beforehand that ScreenScraper lookups take their time.
- ScreenScraper puts its credentials in every image address it returns. DVinyl never sends one of those to your browser: covers are copied into your instance and thumbnails are relayed by the server.
Asked by @Jaklyl.
IGDB completion times show on each game's page: hastily, normally, completely, when IGDB has timed the game. Built by @Siebe-Uy.
Board games arrive as a new module, with BoardGameGeek search: designer, year, player count, playing time, minimum age, BGG rating and cover. BGG approves API tokens by hand, which can take up to a week, so apply early and put yours in BGG_API_KEY. Built by @Siebe-Uy for @aarondixon.
🔎 Finding Things Faster
- Live search. The collection and wishlist filter as you type, without reloading the page, and the matching text is highlighted in the cards, the table and the global search. Asked by @chibashr, built by @Siebe-Uy.
- Scan to find. A barcode button in the filter bar scans a code and opens the item directly when it is the only match. Asked by @nagarrido.
- Series. The search now looks into book series, and books gain a series, then volume sort that puts volume 10 after volume 9, not after volume 1. Asked by @reneald.
📚 Books: the Right Edition
- Pick the edition on the confirm page: publisher, ISBN, pages, language, format and year follow the one you choose, and so does the cover. Searching by ISBN preselects that exact edition, and a metadata refresh keeps it. Asked by @tilldeeke, built by @Siebe-Uy.
- An ISBN in an import is taken at its word. A row that carries a code is looked up by that code alone. When the code isn't found, the row comes in with the file's own data rather than borrowing some other book's details. Asked by @reneald.
⚡ Adding and Tidying Up
- Scan mode. Turn it on in the quick-add settings, and scanning an ISBN that matches exactly one book adds it without the confirm step and takes you back to the add page, ready for the next one. Built by @RobertClarke64.
- A better add flow on phones. The keyboard no longer pops over the page, the camera opens full screen, a "Scan a barcode" shortcut sits next to every +, the Collection button is also at the top of the confirm page, and "Back to search" really goes back to your results. Reported by @oversizedcanoe, built by @Siebe-Uy.
- Range selection and bulk delete. Shift-click selects everything between two items, and the selection bar can delete them all at once (it tells you what it skipped and why). The bar folds down to a small tab when it's in the way. Built by @Sbax.
- Emptying a field on the edit form now clears it. It used to be ignored. Blanking the external id also detaches the item from its source. Built by @Sbax.
🔌 Several Sources per Module
Behind ScreenScraper there is a bigger change: a module can now have several external sources. The add page offers a choice when more than one is configured, the admin page lists each source with what it can do and the variables it's still missing, and you can reorder them. Every item remembers the source it came from, the CSV import lets you pick the source that fills in the file, and items added before this are credited to the source that can describe them. Plugin authors: the contract is documented in plugin development.
💾 Safer Backups and Restores
- Backups carry the new things: lists, furniture and info pages, with the info page images in the ZIP.
- Restoring a collection backup into another collection works cleanly: seasons stay attached to their show, list lines follow their items.
- The instance import refuses a collection backup. Picking the wrong file there used to wipe every user and every other collection. It is now refused before anything is touched, with a message saying where the file goes instead. Thanks @oversizedcanoe for the report that led here.
- A restore checks the file before deleting anything. An item the file can't bring back stops a collection restore with nothing changed, instead of leaving an empty collection. A list it can't restore is left out rather than failing the whole import.
- Good to know: a collection restore replaces the collection's lists with the file's. Restoring a backup made before 3.2.0 therefore leaves the collection with no lists.
🛠 Fixes
-
Switching collections on one device no longer moves your other devices. The active collection is now kept per session, so a phone on collection B leaves your computer on collection A, and its links keep working. Reported by @reneald
-
"Back to collection" no longer loops between a show and its seasons, or between two formats of a film. It returns to the exact page of the listing you came from. Reported and fixed by @teaboyteaboy
-
A pre-filled confirm form no longer posts a custom field twice, which made the save fail. Reported and fixed by @teaboyteaboy
-
Items of a custom collection saved without a picture show its default image again, instead of the generic DVinyl logo. Reported by @jws5406, fixed by @ArtwoXYZ
-
Sign in with your username or your email. And creating a member with an email that's already taken now says it failed, instead of showing a green success banner. Reported by @oversizedcanoe
-
A custom field that collides with a field the module now ships itself is caught. Its values are kept apart, never merged into the native field, and admins get a warning. By @ArtwoXYZ
-
Security hardening: a failed-login lockout is now counted per account, so switching between username and email doesn't multiply the attempts. Sessions are only stored once you sign in. Scan mode's self-submitting page needs a one-time token.
bcryptmoved to 6 and the audited dependencies were patched (npm audit: 0). -
The admin pages are split into tabs that stick to the top, remember the one you were on and scroll sideways on phones. Long settings forms get a floating save bar when they have unsaved changes. The mobile layout is a bit wider, with tighter gutters.
Same as always: nearly every line above started as one of your issues or discussions, and a lot of them arrived with the code attached. Thank you @Siebe-Uy for five pull requests this cycle (!), @Sbax for three, @ArtwoXYZ, @RobertClarke64 and @teaboyteaboy, and @reneald, @chibashr, @jws5406, @nagarrido, @tilldeeke, @Jaklyl, @aarondixon, @driph, @raorm88, @LordChabelo and @oversizedcanoe for asking for all of it. Love u all <3