Skip to content

Commit c1329e8

Browse files
Add persistent player support for all show types (Mixcloud, YouTube)
- Rewrote player.js to load Mixcloud/YouTube into bottom bar via Widget APIs - All play buttons now use KloomPlayer.load() regardless of show type - Player state persists across page navigation for all types - Added CSP rules for widget.mixcloud.com and www.youtube.com APIs - Added embed wrapper styles to player.css - Updated CLAUDE.md with new player behavior documentation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent f3d10d9 commit c1329e8

27 files changed

Lines changed: 415 additions & 245 deletions

CLAUDE.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,13 @@ No CI pipeline — GitHub Pages serves master at root directly. `.nojekyll` is p
3838

3939
### Show types & player behaviour
4040

41-
Shows in `shows.json` have a `type` field:
41+
Shows in `shows.json` have a `type` field. **All types play through the persistent bottom-bar player** and survive page navigation via `localStorage`:
4242

43-
- **`local_audio`** — file hosted in the repo (`src` field). Plays through the persistent bottom-bar player (`KloomPlayer.load()`). Survives page navigation via `localStorage`; on restore a pulsing "TAP TO RESUME" hint appears because browsers block autoplay without a gesture.
44-
- **`embed`** — Mixcloud iframe. Audio lives inside the iframe and cannot be routed through our `<Audio>` element. On the index, clicking play navigates to the show page (which renders the embed at full width). No cross-page persistence.
45-
- **`youtube`** — YouTube iframe. Same constraints as embed.
43+
- **`local_audio`** — file hosted in the repo (`src` field). Uses HTML5 `<audio>` element.
44+
- **`embed`** — Mixcloud iframe. Uses the [Mixcloud Widget API](https://www.mixcloud.com/developers/widget/) loaded dynamically.
45+
- **`youtube`** — YouTube iframe. Uses the [YouTube IFrame API](https://developers.google.com/youtube/iframe_api_reference) loaded dynamically.
46+
47+
On page restore, a pulsing "TAP TO RESUME" hint appears because browsers block autoplay without a gesture. The player saves position every 3s and restores it on reload.
4648

4749
### SSH Teletext Radio (`kloom_ssh.py`)
4850

@@ -118,6 +120,6 @@ The cheat system is defined in the `<script>` block in `index_list_glitch.html`
118120
## Security notes
119121

120122
- CSP (Content-Security-Policy) is set on all pages via `<meta>` tag.
121-
- `'unsafe-inline'` is required in `script-src` due to `onclick` handlers — this is an accepted trade-off.
123+
- `script-src` allows `'unsafe-inline'` (for `onclick` handlers) plus `widget.mixcloud.com` and `www.youtube.com` (for the persistent player APIs).
122124
- All user-facing URLs are validated (only Mixcloud, YouTube, or local paths allowed).
123125
- The SSH server requires no authentication by design (it's a public radio).

about.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
66
<title>KLOOM // ABOUT</title>
77
<meta name="description" content="About Kloom Lo Kadosh — an underground experimental radio archive. Nothing is Holy.">
8-
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; media-src 'self' blob:;">
8+
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' https://widget.mixcloud.com https://www.youtube.com; style-src 'self' 'unsafe-inline'; img-src 'self' https://thumbnailer.mixcloud.com https://i.ytimg.com data:; frame-src https://player-widget.mixcloud.com https://www.youtube.com; media-src 'self' blob:; connect-src 'self' https://api.mixcloud.com;">
99
<link rel="icon" href="assets/favicon.svg">
1010
<link rel="canonical" href="https://willbearfruits.github.io/kloom-radio/about.html">
1111
<link rel="alternate" type="application/rss+xml" title="KLOOM LO KADOSH" href="feed.xml">
@@ -157,7 +157,7 @@ <h1>NOTHING<br>IS HOLY</h1>
157157
</div>
158158

159159
<div class="footer">
160-
KLOOM LO KADOSH RADIO ARCHIVE // GENERATED 2026-02-04 03:10:50
160+
KLOOM LO KADOSH RADIO ARCHIVE // GENERATED 2026-02-04 03:22:35
161161
</div>
162162

163163
<script src="assets/player.js"></script>

assets/player.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@
3737
.kp-resume { color:#00ff00; font-family:monospace; font-size:.75rem; font-weight:bold; text-align:center; padding:2px 0; animation:kp-pulse 1.4s ease-in-out infinite; }
3838
@keyframes kp-pulse { 0%,100%{opacity:1} 50%{opacity:.3} }
3939

40+
/* embed wrapper (Mixcloud/YouTube in persistent player) */
41+
.kp-embed-wrap { display:flex; flex-direction:column; gap:4px; }
42+
.kp-embed-wrap iframe { border:none; background:#111; max-height:60px; }
43+
.kp-embed-progress { margin-top:2px; }
44+
.kp-youtube-wrap iframe { pointer-events:none; }
45+
.kp-youtube-wrap #kp-youtube { background:#111; }
46+
4047
/* embed / youtube "now playing" badge */
4148
.kp-badge {
4249
display:inline-flex; align-items:center; gap:6px;

0 commit comments

Comments
 (0)