Drops every YouTube-backed route, proxy and type (external
albums/tracks, thumbnail proxy, youtube.ts) and simplifies
player/track/mix types to the local-only catalog now that the
backend contract dropped Source/ExternalId. Genre tiles on Explore
and "Populares esta semana" on Home stay as deliberate client-only
placeholders per product decision, just without the YouTube backing.
Also finishes the design-system unification pass: Home's three
hand-rolled track rows (Continuar escuchando, Playlist destacada,
Populares esta semana) now reuse the shared TrackTitleCell component
instead of duplicating cover+title+artist markup, and the orphaned
Rail.svelte (no importers) is removed.
The browser used to pull every cover straight from Google, so a search grid
plus infinite scroll fired dozens of cross-origin image requests and started
coming back as 429. Covers now go through /api/youtube/thumbnail, which
resizes the upstream URL, caches the bytes in memory, collapses duplicate
in-flight fetches, caps the concurrency against Google and backs off when it
answers 429. Responses are immutable for a month and revalidate with an ETag,
and serving them same-origin also lets the accent extractor read the pixels.
Updates the compose build context, the Dockerfile header, the package
name and the docs. The compose service and container keep the name
frontend/musify-frontend, since nginx routes to http://frontend:3000.
The source files also carry the first prettier pass, so the rename and
the reformat land together for them.