···45454646## recent work
47474848+### April 2026
4949+5050+#### AT-URI top-level route resolution (PRs #1206, #1208, Apr 1)
5151+5252+**why**: every atproto app should support AT-URIs as top-level routes ([streamplace/streamplace#1012](https://github.com/streamplace/streamplace/issues/1012)). this lets anyone paste `https://plyr.fm/at://did:plc:xxx/fm.plyr.track/rkey` and land on the right page.
5353+5454+**what shipped**:
5555+- new SvelteKit catch-all route at `/at/[...uri]` that parses AT-URIs via `AtUri` from `@atproto/api`, resolves them against existing backend `/tracks/by-uri` and `/lists/playlists/by-uri` endpoints, and 301 redirects to the canonical page (`/track/{id}`, `/playlist/{id}`)
5656+- handles browser normalization of `://` in URL paths
5757+- follow-up (#1208): replaced 7 instances of manual `.split("/")` AT-URI parsing across backend and frontend with proper library utilities (`parse_at_uri()` wrapper in Python, `AtUri` class in TypeScript)
5858+5959+---
6060+6161+#### track detail page: title width + metadata disclosure (PR #1205, Apr 1)
6262+6363+**why**: long track titles like "better hate (jessica pratt cover)" wrapped onto two lines because `.track-info-wrapper` was capped at `max-width: 600px`. the inline description also added visual weight without user opt-in.
6464+6565+**what shipped**:
6666+- widened `.track-info-wrapper` from `max-width: 600px` to `min(900px, 90%)` — long titles stay on one line on desktop, 90% prevents edge-touching on narrower viewports
6767+- replaced the inline collapsible description (gradient mask + "show more/less" toggle) with a circled `(i)` icon in the stats row that slides open a metadata panel on click. only renders when `track.description` exists
6868+6969+---
7070+7171+#### WebSocket hardening (PRs #1203-1204, Apr 1)
7272+7373+**what shipped**:
7474+- **security** (#1203): origin validation rejects WebSocket upgrades from non-allowlisted origins, `session_id` omitted from client-facing messages
7575+- **reliability** (#1204): idle timeout disconnects inactive connections, per-IP rate limiting and connection limits prevent abuse
7676+7777+---
7878+7979+#### Jetstream identity sync + image URL fix (PRs #1200-1202, Mar 31)
8080+8181+**what shipped**:
8282+- **handle sync** (#1200): Jetstream identity events now trigger handle updates — when an artist changes their handle on Bluesky, plyr.fm picks it up automatically instead of waiting for their next sign-in
8383+- **image URL fix** (#1202): R2 storage keys use the original file extension, but the image URL construction wasn't preserving it. images uploaded as `.jpeg` were served with `.jpg` URLs (or vice versa), returning 404s from R2
8484+- **docs homepage** (#1201): pinned track 778 on docs homepage, deduplicated tracks-by-artist in the showcase
8585+8686+---
8787+4888### March 2026
49895090#### graceful OAuth error handling (PR #1198, Mar 29)
···226266227267---
228268229229-#### collapsible track descriptions (PRs #1144-1146, Mar 18)
269269+#### collapsible track descriptions (PRs #1144-1146, Mar 18; superseded by #1205)
230270231231-long track descriptions were pushing the track page layout down with no way to collapse them. added a collapsible wrapper that truncates descriptions taller than ~5 lines (128px) with a fade-out gradient. the "show more" toggle started as a bare left-aligned text link, then was restyled as a centered pill button with chevron indicators (▾/▴) to match the existing `.pill-btn` pattern used in Queue and tag badges.
271271+long track descriptions were pushing the track page layout down with no way to collapse them. added a collapsible wrapper that truncates descriptions taller than ~5 lines (128px) with a fade-out gradient. the "show more" toggle started as a bare left-aligned text link, then was restyled as a centered pill button with chevron indicators (▾/▴) to match the existing `.pill-btn` pattern used in Queue and tag badges. **replaced in #1205** with the metadata disclosure icon approach.
232272233273---
234274···331371332372### current focus
333373334334-FLAC uploads graduated (#1189), OAuth error handling improved (#1198), activity page ambient theme race condition fixed (#1197). next: add a staging environment for the moderation service (#1165).
374374+AT-URI resolution route shipped (#1206), standardized AT-URI parsing across codebase (#1208), WebSocket hardening (#1203-1204), Jetstream identity sync (#1200). next: add a staging environment for the moderation service (#1165).
335375336376### known issues
337377- iOS PWA audio may hang on first play after backgrounding
···467507468508---
469509470470-this is a living document. last updated 2026-03-29 (FLAC GA, OAuth error handling, activity page fixes, lossless badge redesign).
510510+this is a living document. last updated 2026-04-01 (AT-URI resolution, track detail redesign, WebSocket hardening, Jetstream identity sync).
471511