Skip to content

Playlists in Syncphony, and the night's Wrapped (MAD-737, MAD-722) - #63

Merged
madeofpendletonwool merged 2 commits into
mainfrom
mad-737-722-playlists-and-wrapped
Oct 9, 2026
Merged

madeofpendletonwool merged 2 commits into
mainfrom
mad-737-722-playlists-and-wrapped

Conversation

@madeofpendletonwool

Copy link
Copy Markdown
Owner

What

MAD-737, reworked: instead of exporting a night to Navidrome or Spotify, Syncphony now has its own playlists, and a night saves as one.

  • A Library tab lists your playlists and the ones shared with your rooms.
  • Songs keep the link they came from, like queue items do. One playlist can mix everyone's services, so a night saves whole and nothing has to be matched across services.
  • Save tonight's playlist is offered from the crowning, the Wrapped and History → Recaps. It keeps songs in play order with who queued each one. Skipped songs and repeats are left out unless you keep them. It's shared with the room by default.
  • A bookmark on song rows (search, albums, playlists, history, now playing) saves a song to a playlist or a new one.
  • On a playlist page you can add it to your lane, shuffle in 20, rename, reorder, remove songs, share with the room or delete it. Queueing follows the same rules as "add again": you need a link you can use, or the room has to allow borrowing.
  • Exporting to external services is left for a later task, as agreed.

MAD-722: the night's Wrapped.

  • GET /rooms/{id}/recap adds the top adder, most hearted, most skipped, longest no-skip streak, genre and decade mix (from the musicgraph cache only), taste overlaps, the night and its saved playlists.
  • The web app plays it as a story (tap or hold, keyboard on desktop). It ends with Share the card, a 1080×1920 PNG via Web Share or download, and the save or open playlist button.
  • The big screen plays it by itself after the crowning, ending on a QR code for the night's shared playlist.

Design notes are in docs/adr/0016-playlists-and-wrapped.md.

How

  • Server: new internal/playlists and internal/recap packages, migration 00028, and fromPlaylistSongId on queue adds (queue.TrackRef.Snapshot). The borrow check now lives in one place.
  • Web: /library and /library/$playlistId routes, a Sheet component, components/playlists/* and components/wrapped/*.

Testing

  • go test ./..., golangci-lint: pass. New tests: the recap math, the night-song picking rules, and an HTTP test covering create, add, move, remove, share and unshare visibility, save night, queue from a playlist (including cant_borrow), recap and delete. The room access and display ops spec tests cover the new endpoints.
  • pnpm typecheck, pnpm lint and pnpm test (219 tests) pass. New tests for the playlist and wrapped helpers.
  • Ran a local server with the fake provider and a seeded night, and checked in a headless browser: the recaps tab, every story page, the share card PNG, saving the night, the playlist page and its edit mode, the Library, the search bookmark sheet, and the big screen playing the Wrapped after the crowning.

🤖 Generated with Claude Code

madeofpendletonwool and others added 2 commits October 9, 2026 09:19
…722)

Syncphony keeps its own playlists: songs keep the snapshot and link
they came from, so one playlist can mix everyone's services. A night
can be saved as one, shared with the room, and its songs queued again.

GET /rooms/{id}/recap makes a night's Wrapped: top adder, most hearted,
most skipped, longest streak, genre and decade mix, taste overlaps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Library tab keeps Syncphony playlists: save songs from search, the
queue and history with the bookmark, reorder and share them with the
room, and add them to your lane. A night saves as a playlist from its
recap or its crowning.

The night's Wrapped plays as a story from History or the crowning, and
shares as an image card. The big screen plays it by itself after the
crowning, ending on a QR code for the night's playlist.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@madeofpendletonwool
madeofpendletonwool merged commit 92c3d6b into main Oct 9, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant