Document Apple Music and Last.fm sign-in setup

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MzFywujuH9TiuXbr9vjoX8
This commit is contained in:
2026-10-04 07:12:19 -04:00
co-authored by Claude Opus 5.5
parent 507cffbe57
commit 91a78a8ad4
+4 -2
View File
@@ -42,6 +42,8 @@ Optional keys in `apps/api/.env`:
|---|---| |---|---|
| `SPOTIFY_CLIENT_ID/SECRET` | Spotify connections + exact Spotify links via ISRC. Add redirect URI `http://127.0.0.1:4000/connections/spotify/callback` in the Spotify dashboard (Spotify rejects `localhost`). | | `SPOTIFY_CLIENT_ID/SECRET` | Spotify connections + exact Spotify links via ISRC. Add redirect URI `http://127.0.0.1:4000/connections/spotify/callback` in the Spotify dashboard (Spotify rejects `localhost`). |
| `LASTFM_API_KEY` | Last.fm connections (covers YouTube Music, Tidal, Deezer, SoundCloud… via scrobbling) | | `LASTFM_API_KEY` | Last.fm connections (covers YouTube Music, Tidal, Deezer, SoundCloud… via scrobbling) |
| `LASTFM_SHARED_SECRET` | One-tap "Sign in with Last.fm" (instead of typing a username). Also powers "Spotify via Last.fm", the route that works for every Spotify user while direct Spotify sign-in is capped. |
| `APPLE_TEAM_ID`, `APPLE_MUSICKIT_KEY_ID`, `APPLE_MUSICKIT_PRIVATE_KEY` | Apple Music. Create a key with MusicKit enabled under Apple Developer → Keys; paste the `.p8` contents with newlines as `\n`. |
| `ODESLI_API_KEY` | Direct YouTube Music + TIDAL links via song.link. Without it, those fall back to search links. | | `ODESLI_API_KEY` | Direct YouTube Music + TIDAL links via song.link. Without it, those fall back to search links. |
| `PLEX_CLIENT_ID` | Identifies the app in Plex's sign-in flow. Pick a unique value before launch and never change it. | | `PLEX_CLIENT_ID` | Identifies the app in Plex's sign-in flow. Pick a unique value before launch and never change it. |
| `ALLOW_PRIVATE_SERVER_URLS` | `true` lets users connect LAN Jellyfin/Plex servers. Fine for local dev and self-hosting; **must be `false` in a hosted deployment**. | | `ALLOW_PRIVATE_SERVER_URLS` | `true` lets users connect LAN Jellyfin/Plex servers. Fine for local dev and self-hosting; **must be `false` in a hosted deployment**. |
@@ -109,12 +111,12 @@ Links are https universal links, so on phones they open the native app. Missing
| Service | Status | Notes | | Service | Status | Notes |
|---|---|---| |---|---|---|
| Spotify | ✅ | **Development mode caps an app at 25 allow-listed users.** Since May 2025, extended quota is only granted to registered businesses with an established user base, so plan for this before launch. Last.fm is the fallback for Spotify users beyond the cap. | | Spotify | ✅ | **Development mode now caps an app at 5 allow-listed users** (Feb 2026). Accounts beyond that are sent back with a "limited during beta" message offering Spotify via Last.fm. Since May 2025, extended quota is only granted to registered businesses with an established user base, so plan for this before launch. Last.fm is the fallback for Spotify users beyond the cap. |
| Last.fm | ✅ | Covers almost any service via scrobbling | | Last.fm | ✅ | Covers almost any service via scrobbling |
| ListenBrainz | ✅ | | | ListenBrainz | ✅ | |
| Plex | ✅ | Plex sign-in (PIN flow), server discovery via plex.tv, polls `/status/sessions` on each server (remote → relay → LAN). Optional Plex Pass webhook for instant updates. | | Plex | ✅ | Plex sign-in (PIN flow), server discovery via plex.tv, polls `/status/sessions` on each server (remote → relay → LAN). Optional Plex Pass webhook for instant updates. |
| Jellyfin | ✅ | Server URL + login; only the issued access token is stored and it's revoked on disconnect. Optional Webhook-plugin URL for instant updates. | | Jellyfin | ✅ | Server URL + login; only the issued access token is stored and it's revoked on disconnect. Optional Webhook-plugin URL for instant updates. |
| Apple Music | ⏳ | No server-side now-playing API. MusicKit gives recently-played only; the iOS app can read the device player while open. | | Apple Music | ✅ (iOS) | One system prompt in the iPhone app. The server follows recently played (no timestamps, so a new top song is shown as playing for its length; connecting starts from a baseline). While the app is open it mirrors the Music app live. Native code: `apps/mobile/modules/apple-music`. |
| YouTube Music | via Last.fm | No official history API | | YouTube Music | via Last.fm | No official history API |
| Android (any music app) | ✅ | One toggle in the app. `modules/now-playing-reader` listens to system media sessions (via notification access, never reading notification contents), filters to known music apps, and reports changes plus a 4-minute heartbeat through WorkManager with a per-phone revocable token. Testing with apps outside the allowlist: `EXPO_PUBLIC_EXTRA_MEDIA_APPS=com.android.chrome` (dev only). | | Android (any music app) | ✅ | One toggle in the app. `modules/now-playing-reader` listens to system media sessions (via notification access, never reading notification contents), filters to known music apps, and reports changes plus a 4-minute heartbeat through WorkManager with a per-phone revocable token. Testing with apps outside the allowlist: `EXPO_PUBLIC_EXTRA_MEDIA_APPS=com.android.chrome` (dev only). |