Changeset 4c9f29a in Klonkt for src/views/shell.ejs


Ignore:
Timestamp:
06/15/2026 03:23:14 AM (3 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
3e86f1c
Parents:
650b601
git-author:
roboburr <roboburr@…> (06/15/2026 03:22:47 AM)
git-committer:
roboburr <roboburr@…> (06/15/2026 03:23:14 AM)
Message:

feat: on-brand media embeds via the real player APIs

Replaces bare platform iframes with on-brand cards, powered by the
official JS APIs so play/pause/progress are in our own hands:

  • YouTube (IFrame Player API) + SoundCloud (Widget API): fully custom controls, native chrome hidden.
  • Spotify (iFrame API): our frame around it + controls (their player UI remains; restyling not possible without Premium+OAuth).
  • Shared PlaybackRegistry: mutual exclusion -- only 1 thing plays at a time (incl. the site audio player). Replaces the focus/blur heuristic with real play events (blur stays as fallback for iframe-only embeds).
  • Progressive enhancement: if an ad-blocker blocks the platform API, falls back seamlessly to the bare platform iframe (autoplay). The resting-state card is our brand for everyone.

AudioEmbedService now renders a placeholder div (data-embed-*) for YT/SC/
Spotify instead of an iframe; embed-player.js builds the card client-side.
CSP scriptSrc extended with the player API hosts.

Adversarial review (workflow) -> 6 bugs fixed: HTMX swap leak (poll timers/
adapters -> MutationObserver teardown + adapter.destroy()), javascript: URL XSS
(scheme guard in detectProvider + safeHref client-side), Spotify ended
misdetection (no more reset-to-0), ytId/server regex on exact 11, blur scope
limited to .folio-embed.

Co-Authored-By: Claude <noreply@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/views/shell.ejs

    r650b601 r4c9f29a  
    169169     a singleton — see the script tag near </body>. -->
    170170<link rel="stylesheet" href="/assets/css/audio.css?v=5">
     171<!-- Eigen custom media-embeds (YouTube/SoundCloud/Spotify) in huisstijl. -->
     172<link rel="stylesheet" href="/assets/css/embed.css?v=1">
    171173
    172174<%- include('partials/shared-styles') %>
     
    309311     ?v=N — cache-buster: bump bij elke audio-player.js wijziging zodat
    310312     Cloudflare (max-age=1y) niet de oude versie blijft serveren. -->
    311 <script src="/assets/js/audio-player.js?v=13"></script>
     313<script src="/assets/js/audio-player.js?v=15"></script>
     314<!-- Eigen custom media-embeds (YouTube/SoundCloud/Spotify) via de echte
     315     player-API's + gedeelde mutual-exclusion registry met de site-speler. -->
     316<script src="/assets/js/embed-player.js?v=3" defer></script>
    312317<% if (site && site.enable_audio_player && audioTracks && audioTracks.length > 0) { %>
    313318  <script>window.PCMS_SITE_TRACKS = <%- JSON.stringify(audioTracks) %>;</script>
Note: See TracChangeset for help on using the changeset viewer.