6.2 KiB
6.2 KiB
VJ Playlist Page Plan
Overview
Add playlist browsing functionality to www/vj-playlist.html (duplicated from template). The page will query Nostr events to discover past livestream shows and display their episode playlists (tracklists).
Data Model (Existing Events from vj-stream.mjs)
graph TD
A[Show - kind 30311] -->|d tag = show slug| B[Episode]
B -->|episode tag = timestamp ID| C[Playlist - kind 30078]
C -->|d tag = show-playlist:slug:episodeId| D[Track Tags]
C -->|viewers tags| E[Viewer Snapshots]
A -->|a tag coordinate| F[30311:pubkey:slug]
C -->|a tag = stream coordinate| F
Kind 30311 — Stream/Show Metadata
dtag: show slug (e.g.my-show)title: show titlestatus: planned / live / endedepisode: episode ID (unix timestamp string)episode_description: episode descriptionimage: show image URLstreaming: HLS playlist URLweb: viewer page URL
Kind 30078 — Playlist Event
dtag:show-playlist:{slug}:{episodeId}showtag: show slugepisodetag: episode IDatag: stream coordinate (30311:{pubkey}:{slug})titletag: e.g.My Show Playliststatustag:liveorendedepisode_descriptiontag: optionaltracktags:[track, trackNumber, artist, title, nostrRef, isoTimestamp]viewerstags:[viewers, isoTimestamp, count, variant:count...]
Architecture
The page keeps all existing template functionality (auth, sidenav, hamburger, relay UI, etc.) and adds playlist browsing in the #divBody area.
Query Strategy
- Discover shows: Subscribe to kind 30311 events authored by the target pubkey to find all shows
- Fetch playlists: Query kind 30078 events authored by the target pubkey, filtering by
#showtag when a show is selected - Parse and display: Extract
tracktags from playlist events and render as tracklists grouped by episode
Auth Mode
- Default to
optionalauth mode (supports?npub=or?pubkey=URL params for viewing other users' playlists) - If no target pubkey in URL, use the logged-in user's pubkey
- Public browsing works without login
UI Layout
┌─────────────────────────────────────────────┐
│ HEADER: VJ PLAYLISTS │
├─────────────────────────────────────────────┤
│ │
│ [Show Selector Dropdown ▼] │
│ │
│ ┌─ Episode Card ─────────────────────────┐ │
│ │ Episode: 2026-04-06 • Status: ended │ │
│ │ Description: Saturday night session │ │
│ │ 12 tracks • 45 viewers peak │ │
│ │ │ │
│ │ # │ Artist │ Title │ Time │ │
│ │ 001│ Artist Name │ Song Title │ 20:15 │ │
│ │ 002│ Artist Name │ Song Title │ 20:19 │ │
│ │ 003│ Artist Name │ Song Title │ 20:23 │ │
│ │ ... │ │
│ └─────────────────────────────────────────┘ │
│ │
│ ┌─ Episode Card ─────────────────────────┐ │
│ │ Episode: 2026-04-05 • Status: ended │ │
│ │ (collapsed - click to expand) │ │
│ └─────────────────────────────────────────┘ │
│ │
├─────────────────────────────────────────────┤
│ FOOTER │
└─────────────────────────────────────────────┘
Implementation Steps
1. HTML Structure (in divBody)
Add to #divBody:
- Show selector dropdown
- Loading indicator
- Container for episode playlist cards
- Empty state message
2. Imports
Add to the existing module script:
queryCacheandndkFetchEventsfrominit-ndk.mjs(for fetching events)subscribeis already imported
3. Show Discovery Logic
- On page load, determine target pubkey (from URL params or logged-in user)
- Query kind 30311 events for that pubkey
- Populate show selector dropdown with discovered shows
- Auto-select if only one show exists
4. Playlist Fetch Logic
- When a show is selected, query kind 30078 events with
authors: [targetPubkey] - Filter client-side by
showtag matching selected show slug - Group by episode (from
dtag patternshow-playlist:{slug}:{episodeId}) - Sort episodes by
created_atdescending (newest first) - For addressable events (kind 30078), only the latest version per
dtag is kept
5. Playlist Rendering
- Render each episode as a collapsible card
- Parse
tracktags into a table: track number, artist, title, timestamp - Parse
viewerstags to show peak viewer count - Show episode metadata: episode ID (formatted as date), status, description
- First/newest episode expanded by default, rest collapsed
6. Styling
- Episode cards styled consistently with existing app design (border, border-radius, secondary-color background)
- Track table with monospace numbering
- Responsive: stack on mobile
- Dark mode compatible via CSS variables
7. URL Parameter Support
?npub=...or?pubkey=...— view another user's playlists?show=...— pre-select a specific show slug- Auth mode defaults to
optionalwhen target pubkey is in URL
Files Modified
| File | Changes |
|---|---|
www/vj-playlist.html |
Add HTML structure, styles, and JS logic for playlist browsing |
No new JS modules needed — all logic fits inline in the page script, using existing init-ndk.mjs exports (subscribe, queryCache, ndkFetchEvents).