source: Klonkt/src/routes/embed.js@ 0251bae

main
Last change on this file since 0251bae was 6be57b4, checked in by roboburr <roboburr@…>, 3 months ago

Embeddable player (premium feature #7)

Standalone /embed page (no shell) with a compact audio player for the site
tracks, intended for an <iframe> on external sites. The page runs on the klonkt
origin, so audio requests from the iframe remain same-origin -> the
/audio/stream gate lets them through, even on an external site. Helmet's
X-Frame-Options + frame-ancestors are overridden per route (frame-ancestors *)
so external embedding is allowed.

  • routes/embed.js (premium-gated): GET /embed.
  • views/pages/embed-player.ejs: standalone HTML, inline css/js, play/pause, track click, auto-next, progress bar; themable on site.accent.
  • admin-audio: embedUrl + "Embeddable player" section with copyable iframe code + preview link (premium).

node --check passed.

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

  • Property mode set to 100644
File size: 1.5 KB
RevLine 
[6be57b4]1/**
2 * Embedbare player (premium feature #7).
3 *
4 * GET /embed -> een zelfstandige, compacte audiospeler-pagina (geen shell),
5 * bedoeld om op EXTERNE sites in een <iframe> te zetten.
6 *
7 * De pagina wordt door ons (klonkt-origin) geserveerd, dus de audio-requests vanuit
8 * het iframe blijven same-origin → de /audio/stream-gate laat ze door, ook al staat
9 * het iframe op een vreemde site. We overrulen alleen Helmet's frameguard +
10 * frame-ancestors zodat externe sites mógen inbedden. Hub: /user/:slug/embed.
11 */
12
13import express from 'express';
14import { premiumUnlocked } from '../services/PatreonService.js';
15
16const router = express.Router();
17
18router.get('/embed', (req, res, next) => {
19 if (!premiumUnlocked()) return next();
20 const site = res.locals.site;
21 if (!site) return next();
22
23 // Inbedden op externe sites toestaan (overrule de globale frameguard/CSP).
24 res.removeHeader('X-Frame-Options');
25 res.setHeader(
26 'Content-Security-Policy',
27 "default-src 'self'; media-src 'self' blob: https:; img-src 'self' data: https:; style-src 'unsafe-inline'; script-src 'unsafe-inline' 'self'; frame-ancestors *",
28 );
29
30 const tracks = (res.locals.audioTracks || []).map((t) => ({
31 id: t.id, title: t.title, artist: t.artist, duration: t.duration, url: t.media_url,
32 })).filter((t) => t.url);
33
34 res.render('pages/embed-player', {
35 site,
36 embedTracks: tracks,
37 siteUrlBase: res.locals.siteUrlBase || '',
38 });
39});
40
41export default router;
Note: See TracBrowser for help on using the repository browser.