# Music & VJ URL Structure Unified URL schema for `music.html` and `vj.html`. ## URL Anatomy ``` https://example.com/vj.html?show=reggae&npub=npub1abc#/playlist/ep-1744382400 \______________________/\________/ \_______________/ \________________________/ origin pathname query string hash fragment ``` ## Query String Parameters Query string parameters represent **identity and session context**. They persist across hash navigation changes. | Parameter | Format | Pages | Required | Description | |-----------|--------|-------|----------|-------------| | `npub` | `npub1...` | both | no | Target user public key in npub format (preferred) | | `pubkey` | 64-char hex | both | no | Target user public key in hex format (fallback) | | `auth` | `required` \| `optional` \| `none` | both | no | Authentication mode override | | `show` | slug string | both | no | Active show slug (e.g. `saturday-reggae`) | | `episode` | identifier string | both | no | Active episode playlist identifier | | `a` | `30311:{pubkey}:{slug}` | vj.html | no | Stream coordinate for direct stream targeting | | `naddr` | `naddr1...` | vj.html | no | Nostr address encoding of stream event | ### Parameter Precedence - `npub` takes priority over `pubkey` when both are present - `pubkey` is deleted from URL when `npub` is set - If `npub` or `pubkey` points to a different user than the logged-in user, the page enters **read-only mode** ## Hash Fragment Routes Hash routes represent **in-page navigation state**. Changing the hash does not reload the page. | Route | Description | |-------|-------------| | `#/` | Home — empty search view | | `#/search/{query}` | Search results for the given query | | `#/album/{albumId}` | Album detail drill-down | | `#/artist/{artistId}` | Artist detail drill-down | | `#/track/{trackId}` | Play a specific track by ID | | `#/playlist/{identifier}` | Open own playlist/episode by identifier | | `#/playlist/{pubkey}/{identifier}` | Open external playlist/episode by pubkey and identifier | ### Route Parsing Routes are parsed by splitting the hash on `/`: ``` #/playlist/abc123/ep-42 → { page: 'playlist', parts: ['abc123', 'ep-42'] } #/search/bob marley → { page: 'search', parts: ['bob marley'] } #/track/98765 → { page: 'track', parts: ['98765'] } ``` ## URL Examples ### VJ working on own show ``` vj.html?show=saturday-reggae&episode=ep-1744382400 ``` ### Sharing an episode for playback on music.html ``` music.html?npub=npub1abc123...#/playlist/npub1abc123.../ep-1744382400 ``` ### Sharing a VJ episode for viewing ``` vj.html?npub=npub1abc123...&show=saturday-reggae&episode=ep-1744382400 ``` ### Direct track link (works on either page) ``` music.html#/track/12345678 vj.html#/track/12345678 ``` ### Search link ``` music.html#/search/bob%20marley ``` ### Album link ``` music.html#/album/album-id-here ``` ## URL Update Behavior | User Action | URL Change | Method | |-------------|-----------|--------| | Select show in dropdown | `?show={slug}` added/updated | `replaceState` | | Select/create episode | `?episode={id}` added/updated | `replaceState` | | Search for music | `#/search/{query}` | hash assignment | | Click album/artist | `#/album/{id}` or `#/artist/{id}` | hash assignment | | Play track from link | `#/track/{id}` | hash assignment | | Select playlist | `#/playlist/{id}` | hash assignment | | Login / auth change | `?npub={npub}` added | `replaceState` | | Load external user | `?npub={npub}` or `?pubkey={hex}` | page navigation | ### replaceState vs hash assignment - **`replaceState`** — Used for context changes (show, episode, auth). Does not create a new history entry. The user does not get a "back" step for every dropdown change. - **Hash assignment** — Used for navigation changes (search, album, track, playlist). Creates a new history entry. Back/Forward buttons navigate between views.