Tabs get a sliding indicator that persists across library routes, grid rows flip and collapse on removal, the selection bar and filters crossfade, album tracks move between lists with a crossfade, processing badges pulse and the dropzone scales while dragging.
Track lists and the upload queue now render through a declarative DataGrid, the album editor reuses AlbumForm with a split layout and a track picker, and genre labels and types are shared helpers.
Adapt the refactored web player to the new backend API (id path params,
bulk track adds, flat list items, mix kind) and port AddAlbumToPlayList
to the backend conventions.
Add catch-all routes so unknown pages 404 inside the (app) layout and unknown
/api URLs return a JSON 404 instead of redirecting to the login page. Restore
the full root error page.
Guid and long route constraints, id/trackId parameter names, Update*Request without the New prefix,
sentence-case operation summaries, shared security scheme id and a single Limits class.
Following lists are public; followers are visible to the user and to mutual followers.
Adds GET /users/{id}/followers and /following, exposes isFollowing and canViewFollowers
on the profile, and returns isFollowedByViewer from user search so the web player no
longer calls /is-following per user.
Discover used a hardcoded list of genre tiles that searched track titles,
and the upload form kept its own copy of the genre list and compatibility
rules. Both now come from the backend.
Backend:
- GET /genres returns genres with at least one track and their counts.
- GET /genres/available returns every assignable genre with the genres
it cannot be combined with, so the rules live only in
GenreCompatibility.
- GET /tracks accepts ?genre= (case-insensitive, 400 on unknown values).
web-player:
- Discover tiles are built from /genres; each opens /explore?genre=X, a
song list filtered by that tag. Unknown genres fall back to a label
derived from their name.
- The upload form loads /genres/available, disables incompatible genres
as you pick, and the server validates before reserving upload URLs.
- lib/data/trackGenres.ts is removed; its helpers merge into
lib/data/genres.ts.
- Regenerate the typed API client.