7.8 KiB
Music Player Page — Nostr-Based Music Search & Play
Goal
Integrate the working greyscale PoC music search/playback into the client template system as music.html, matching the project's monochrome aesthetic (CSS variables, monospace fonts, grayscale images, .btn class, etc.).
Architecture
flowchart TB
subgraph www - music.html
HTML[music.html - template-based page]
STYLE[page-specific style block]
INLINE[inline module script - glue code]
end
subgraph www/js - reusable modules
API[js/greyscale-api.mjs - search + streaming API]
PLAYER[js/greyscale-player.mjs - audio + dash.js playback]
NDK[js/init-ndk.mjs - auth + worker]
end
subgraph External
CDN[dash.js CDN]
TIDAL[Tidal API instances]
UPTIME[Uptime workers - instance list]
end
subgraph Shared
CSS[css/client.css - global styles + variables]
NOSTR[nostr.bundle.js + nostr-lite.js]
end
HTML --> CSS
HTML --> NOSTR
HTML --> CDN
INLINE --> API
INLINE --> PLAYER
INLINE --> NDK
API -->|fetch| UPTIME
API -->|fetch| TIDAL
PLAYER -->|uses| CDN
Key Design Decisions
1. Copy api.js and player.js as .mjs modules into www/js/
The greyscale PoC files (greyscale/greyscale-app/js/api.js and player.js) are already self-contained ES modules with zero dependencies (except dash.js global for player). We copy them into www/js/ as:
www/js/greyscale-api.mjs— renamed to.mjsto match project conventionwww/js/greyscale-player.mjs— renamed to.mjsto match project convention
No code changes needed to these files — they export GreyscaleAPI and SimplePlayer classes that work as-is.
2. Use the template layout, not the greyscale layout
The greyscale PoC has its own style.css with a different dark theme. We discard that entirely and use:
client.cssglobal styles (CSS variables,.btnclass, monospace fonts)- Page-specific
<style>block inmusic.htmlfor music-specific elements - All colors via CSS variables (
--primary-color,--secondary-color,--accent-color,--muted-color,--border-color) - No hardcoded colors
3. Player bar sits inside #divBody, not as a fixed footer
The template already has a fixed #divFooter for relay status. The music player bar will be positioned at the bottom of #divBody using flexbox, keeping the standard footer intact. The #divBody layout will be overridden to flex-direction: column with the search area scrollable and the player bar pinned at the bottom.
4. Search UI follows project conventions
- Search input uses
var(--font-family),var(--border-color), etc. - Search button uses the
.btnclass fromclient.css - Results list uses
var(--border-color)borders,var(--muted-color)for secondary text - Cover art images get the standard grayscale filter from
client.css(imgrule already applies globally)
Page Layout
┌─────────────────────────────────────────┐
│ ☰ [header] │ ← #divHeader (standard)
├─────────────────────────────────────────┤
│ │
│ [Search input...............] [Search] │ ← search form
│ Status: Ready. │ ← status text
│ │
│ ┌─────────────────────────────────┐ │
│ │ [img] Track Title 3:42 │ │ ← results list (scrollable)
│ │ Artist — Album │ │
│ ├─────────────────────────────────┤ │
│ │ [img] Track Title 4:15 │ │
│ │ Artist — Album │ │
│ └─────────────────────────────────┘ │
│ │
│─────────────────────────────────────────│
│ [img] Title [◀][▶/❚❚][▶▶] │ ← player bar (pinned bottom)
│ Artist 0:00 ═══════○═══ 3:42 │
├─────────────────────────────────────────┤
│ [relay dots] [center] [right] [sats] │ ← #divFooter (standard)
└─────────────────────────────────────────┘
Implementation Steps
Step 1: Copy greyscale modules to www/js/
Copy greyscale/greyscale-app/js/api.js → www/js/greyscale-api.mjs
Copy greyscale/greyscale-app/js/player.js → www/js/greyscale-player.mjs
No modifications needed — these are already clean ES modules.
Step 2: Update music.html — Head section
- Change
<title>from "TEMPLATE" to "Music" - Add dash.js CDN script:
<script src="https://cdn.dashjs.org/latest/dash.all.min.js"></script>
Step 3: Update music.html — Add <style> block
Page-specific styles following the CSS placement rules:
- Override
#divBodytoflex-direction: column; flex-wrap: nowrap; - Style the search form (
.music-search-form) — grid layout with input +.btn - Style the status text (
.music-status) - Style the results list (
.music-results) — bordered list with hover states - Style result items (
.music-result-item) — grid: cover image + meta + duration - Style the player bar (
.music-player-bar) — pinned to bottom of#divBody - Style player controls and progress bar
- All colors use CSS variables only
- Responsive: stack player bar vertically on narrow screens
Step 4: Update music.html — Add HTML content in #divBody
Add inside #divBody:
- Search section — form with input +
.btnbutton + status paragraph - Results section — scrollable
<ul>for track results - Player bar — cover image, track info, prev/play-pause/next buttons, progress slider with time displays
- Hidden audio element —
<audio id="music-audio" preload="metadata"></audio>
Step 5: Update music.html — Add inline module script
Wire everything together in the existing <script type="module"> block:
- Import
GreyscaleAPIfrom./js/greyscale-api.mjs - Import
SimplePlayerfrom./js/greyscale-player.mjs - After NDK init completes, initialize the greyscale API (
api.initInstances()) - Create
SimplePlayerinstance bound to audio element and progress controls - Set up search form submit handler →
api.searchTracks()→ render results - Set up result click handler →
player.setQueue()+player.playCurrent() - Set up play/pause, next, prev button handlers
- Set up
player.onTrackChangedcallback to update player bar metadata
This is essentially the same logic as greyscale/greyscale-app/js/app.js but inlined into the template's module script, alongside the existing NDK/hamburger/sidenav/footer code.
Step 6: Test
- Verify search works
- Verify track playback works (both direct URL and DASH streams)
- Verify player controls (play/pause, next, prev, progress scrubbing)
- Verify light/dark mode theming
- Verify responsive layout on narrow screens
- Verify standard template features still work (hamburger, sidenav, relay status, logout)
Files Changed
| File | Action | Description |
|---|---|---|
www/js/greyscale-api.mjs |
New | Copy of greyscale/greyscale-app/js/api.js |
www/js/greyscale-player.mjs |
New | Copy of greyscale/greyscale-app/js/player.js |
www/music.html |
Modified | Add title, styles, HTML content, dash.js CDN, music glue code |