Skip to content

Personal discovery stage 2: the map (MAD-820, MAD-821) - #66

Merged
madeofpendletonwool merged 2 commits into
mainfrom
mad-814-discovery-stage-2
Oct 13, 2026
Merged

madeofpendletonwool merged 2 commits into
mainfrom
mad-814-discovery-stage-2

Conversation

@madeofpendletonwool

Copy link
Copy Markdown
Owner

Stage 2 of Phase 12 (MAD-814): a music-map.com style map around an artist or a set.

MAD-820: the map API

  • GET /me/discover/map?artist=<name>[&mbid=] or ?setId=, with depth (1|2) and limit (10–100, default 60).
  • Around an artist (depth 2 by default): its nearest neighbors, then their own nearest.
  • Around a set (depth 1 by default): the seeds, plus their neighbors ranked by how many seeds they're near.
  • Each node has owned (library KnowsArtist), seed, center, blocked, seeds (overlap), hop, score, fans, picture, top tags, and known. Edges are the graph's merged similarity. Each artist keeps only its 3 strongest edges, so a map doesn't turn into a hairball (warm live maps went from ~340–980 edges to ~140).
  • Blocked artists are left out, unless the map is of them.
  • The map reads musicgraph's cache. It fetches at most 3 uncached artists (the center or the first seeds) and waits at most 5s for them. A fetch still going after that finishes in the background and gets cached. Everyone else is warmed, and the response says partial: true.
  • GET /me/discover/songs?artist= returns an artist's top songs you don't have (same filter as the feed), with Deezer IDs resolved for previews. The map's artist sheet uses it.
  • Refactor: the feed's lookup closure is now a shared looker type, and resolve works without a feed.
  • ADR 0017 has a new "The map" section.

Measured against live sources (ListenBrainz, Deezer, MusicBrainz):

  • A warm map of a 3-seed set or an artist answers in about 40ms.
  • A cold artist answers within the 5s cap as partial, and is fully mapped on the next load.

MAD-821: the Map view

  • A Feed | Map tab on each set, plus a "Map an artist" search on Discover. The route is /discover/map?set=…&path=[…].
  • Layout is d3-force, computed all at once off screen and drawn in SVG. Distance follows similarity and size follows Deezer fans. A new layout starts from the previous positions and tweens there with direct DOM writes, so re-centering glides. The tween is skipped when reduced motion is on.
  • How nodes look: owned artists are dimmed, new ones are full color, and seeds and the center are ringed. In set mode, artists near 2+ seeds get a soft halo. Unknown artists (still being looked up) are drawn dashed. Nothing is beat-reactive.
  • Tapping an artist opens a sheet with:
    • their top unowned songs, each with a preview and a YouTube link
    • Re-center here
    • Add to / Other set (reuses AddToSetSheet)
    • Not for me, with an undo
  • Each re-center is a URL step, so browser Back and the breadcrumbs both retrace it.
  • A partial map refetches every 6s, up to 4 times.

Tests

  • go test ./... and golangci-lint are clean. New tests cover set and artist maps: overlap ranking, owned and blocked handling, the bounds and depth, warming without fetching neighbors, and artist songs. The HTTP test covers both endpoints.
  • pnpm test, typecheck and lint are clean. New tests cover the layout (center pinned, alike artists closer, warm start), crumbs, and a MapGraph render and select test.
  • I haven't driven the UI in a browser yet. The server endpoints were checked against a live instance, but the map view itself still needs a look on a phone.

🤖 Generated with Claude Code

madeofpendletonwool and others added 2 commits October 13, 2026 10:31
GET /me/discover/map draws a graph around any artist, or around a set's
seeds: neighbors near the most seeds first, and two steps out around an
artist. Each artist says whether you have anything of theirs, whether
they're a seed or the center, how many seeds they're near, and their
fans, picture and tags. Each draws its three strongest likenesses, and
artists you blocked are left out.

It reads the music graph's cache and waits at most 5 seconds on the few
artists it fetches. A slow fetch finishes in the background, the rest
are warmed, and the map says it's partial so a reload shows more. Warm,
it takes tens of milliseconds.

GET /me/discover/songs lists an artist's songs you don't have, with
previews, for the map's artist sheet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Map tab beside a set's feed, and a map of any artist from Discover's
search. It's laid out with d3-force, where alike artists sit close and
well-known ones are bigger. Artists you have are dimmed and new ones are
in full color. Seeds and the center are ringed, and artists near several
seeds get a soft halo. Tap one to hear their songs (preview and
YouTube), add them to a set, say they're not for you, or re-center on
them. Each re-center is a step in the URL, so Back and the breadcrumbs
retrace them. A new layout glides from the last one, and it stays calm,
with nothing beat-reactive.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@madeofpendletonwool
madeofpendletonwool merged commit b55ba47 into main Oct 13, 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