Add titles-only list export and Custom lists

Export
- GET /l/<list>/export?format=csv|txt downloads a list's titles in rank
  order, one per line, with no header or other fields (CSV gets a UTF-8
  BOM for Excel)
- Export menu in the list editor and, for the owner, on the public list
  page; hidden lists stay owner-only

Custom lists
- New "Custom" category for anything not built in (sports teams,
  drinks…): owner-named, slug from the title, entries added by hand or
  from an unfiltered Wikipedia search
- Per-list artwork shape (square or tall), stored in a new lists.art
  column (migration 2)
- Art can be uploaded while adding an entry, not only after

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
cdnutterandClaude Opus 5.5 committed 2026-09-24 17:18:24 -07:00
1 parent e9a75a968a
commit 58a29b7339
23 files changed
+314 -37

No files matched your search

+13 -1
View File
@@ -1,14 +1,16 @@
# TopDeck
A self-hosted page for **your** ranked favorites: movies, TV shows, albums, songs, video games and theater. One owner, as many lists as you like, each with its own size (Top 5, Top 100, … up to 65,535), with proper posters and cover art pulled from the best free metadata sources.
A self-hosted page for **your** ranked favorites: movies, TV shows, albums, songs, video games, theater, and anything else you care to rank in a custom list. One owner, as many lists as you like, each with its own size (Top 5, Top 100, … up to 65,535), with proper posters and cover art pulled from the best free metadata sources.
Visitors just see your lists. There's no sign-up, no feed and no login button. You manage everything from `/login`.
- **Ranked lists per category**: Movies, TV Shows, Albums, Songs, Video Games and Theater. Each list sets its own size, title, description and layout (artwork grid or ranked list).
- **Search-to-add** from TMDB, TheTVDB, IGDB, Deezer/MusicBrainz and Wikipedia, with add-manually as a fallback for anything they miss.
- **Custom lists** for anything else, like sports teams, drinks or restaurants. You name the list and add entries by hand (with your own photo or logo), or pull a name and picture from Wikipedia.
- **Theater by production**: record *which* staging you mean (Broadway, West End, North American Tour, a revival…) plus venue and cast, and use that production's own poster.
- **Drag to rank**, or use the arrow buttons or type a new number. Paginated editing keeps huge lists usable.
- **Art is cached on your server**, so pages never hotlink and keep working if a source changes. You can also paste an image URL or upload your own.
- **Export** any list as a titles-only `.csv` or `.txt`.
- **Personal notes** on any entry, shown in a detail view (toggleable).
- **12 theme presets** plus a custom CSS box. Every color is a CSS variable.
- **Single binary + SQLite**, no external database. Around 15 MB, and it runs anywhere Docker does.
@@ -44,6 +46,7 @@ Or from source (Go 1.26+): `go run ./cmd/topdeck` stores data in `./data`.
| Video Games | [IGDB](https://www.igdb.com) | Yes (free, via Twitch) | Register an app at [dev.twitch.tv/console](https://dev.twitch.tv/console/apps) and use its Client ID + Secret ([guide](https://api-docs.igdb.com/#account-creation)). |
| Albums & Songs | [Deezer](https://developers.deezer.com/api) (default) or [MusicBrainz](https://musicbrainz.org) + [Cover Art Archive](https://coverartarchive.org) | No | Nothing to set up. |
| Theater | [Wikipedia](https://en.wikipedia.org) | No | Nothing to set up. |
| Custom | Manual entry, or [Wikipedia](https://en.wikipedia.org) | No | Nothing to set up. |
**Why these for music and theater?** Neither needs a key.
- **Music:** Deezer's public catalogue API has no key, generous limits (about 50 requests per 5 seconds) and 1000×1000 covers for both tracks and albums. MusicBrainz is the fully open alternative, but it's limited to one request per second and art coverage is patchier. Spotify, Apple Music and Last.fm all need keys or OAuth and have stricter terms.
@@ -95,6 +98,15 @@ See [`web/static/css/themes.css`](web/static/css/themes.css) for every variable.
A list can hold 1 to 65,535 entries. The editor recommends **100 or fewer** and warns past 1,000. Long lists work (public pages and the editor paginate at 100), but they're hard for visitors to take in.
## Exporting a list
Every list can be downloaded as its titles only, in rank order, one per line. There are no ranks, header row or other fields.
- **Export → Titles as CSV** (`/l/<list>/export?format=csv`): a single column. It starts with a UTF-8 BOM so Excel shows accented titles correctly.
- **Export → Titles as text** (`/l/<list>/export?format=txt`): plain lines.
The Export menu appears in the list editor and, when you're signed in, on the list's public page. The links follow the list's visibility: anyone can download a public list, and only you can download a hidden one.
## Backups
Everything lives in the data volume: `topdeck.db` (SQLite) and `images/`. Copy the volume, or while running: