diff --git a/data/admin-content.json b/data/admin-content.json index cd924ad..1d03f7a 100644 --- a/data/admin-content.json +++ b/data/admin-content.json @@ -31,7 +31,29 @@ "studyGuideUrl": "https://a.co/d/01sG2tOJ", "shareHeading": "Help one more person hear the Word this week.", "shareP": "Scan the QR code or text the show link to a friend who needs encouragement today.", - "customLinks": [], + "customLinks": [ + { + "id": "pocket-casts", + "label": "Pocket Casts", + "url": "https://pca.st/76jisz3d", + "placement": "platforms", + "imageUrl": "/images/listen-on-pocket-casts.svg" + }, + { + "id": "castbox", + "label": "Castbox", + "url": "https://castbox.fm/channel/id7140701?country=us", + "placement": "platforms", + "imageUrl": "/images/listen-on-castbox.svg" + }, + { + "id": "goodpods", + "label": "Goodpods", + "url": "https://goodpods.com/podcasts/verse-by-verse-with-nate-732127", + "placement": "platforms", + "imageUrl": "https://storage.googleapis.com/goodpods-images-bucket/badges/generic-badge-3.svg" + } + ], "customBlocks": [], "archivedSeries": [], "redirects": [ diff --git a/public/images/listen-on-amazon-music.svg b/public/images/listen-on-amazon-music.svg new file mode 100644 index 0000000..7ecc7be --- /dev/null +++ b/public/images/listen-on-amazon-music.svg @@ -0,0 +1,12 @@ + + + + + + + + + + Listen on + Amazon Music + diff --git a/public/images/listen-on-castbox.svg b/public/images/listen-on-castbox.svg new file mode 100644 index 0000000..b2638ef --- /dev/null +++ b/public/images/listen-on-castbox.svg @@ -0,0 +1,11 @@ + + + + + + + + + Listen on + Castbox + diff --git a/public/images/listen-on-pocket-casts.svg b/public/images/listen-on-pocket-casts.svg new file mode 100644 index 0000000..4a69a4c --- /dev/null +++ b/public/images/listen-on-pocket-casts.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + Listen on + Pocket Casts + diff --git a/public/images/listen-on-spotify.svg b/public/images/listen-on-spotify.svg new file mode 100644 index 0000000..275f070 --- /dev/null +++ b/public/images/listen-on-spotify.svg @@ -0,0 +1,9 @@ + + + + + + + Listen on + Spotify + diff --git a/public/images/watch-on-youtube.svg b/public/images/watch-on-youtube.svg new file mode 100644 index 0000000..e3ffa68 --- /dev/null +++ b/public/images/watch-on-youtube.svg @@ -0,0 +1,12 @@ + + + + + + + + + + Watch on + YouTube + diff --git a/src/App.css b/src/App.css index e0d76cc..a6fe655 100644 --- a/src/App.css +++ b/src/App.css @@ -460,6 +460,25 @@ align-items: center; } +.headliner-widget-wrap { + margin-top: 2rem; +} + +.headliner-widget-frame { + display: block; + width: 100%; + min-height: 580px; + border: 0; + border-radius: 12px; +} + +.headliner-widget-empty { + margin: 0; + text-align: center; + color: rgba(255, 255, 255, 0.72); + font-size: 0.95rem; +} + .platform-btn { display: inline-flex; align-items: center; @@ -495,6 +514,19 @@ display: block; } +.platform-btn-image { + background: transparent; + padding: 0; + border-radius: 0; +} + +.platform-badge { + display: block; + width: 150px; + max-width: 100%; + height: auto; +} + /* ── About ── */ .section-about { background: #0d0d0d; diff --git a/src/App.tsx b/src/App.tsx index a178591..0c4d53d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -11,6 +11,69 @@ import './App.css' const SPOTIFY_EMBED_URL = 'https://open.spotify.com/embed/show/0Gq1TzoJOdReSZ1gYQi8Xl?utm_source=generator&theme=0' const CONSENT_KEY = 'vbn_analytics_consent_choice' +const HEADLINER_WIDGET_ID = 'WI_cmou3b4q7000701p0o9qmmcfj' + +function HeadlinerWidget() { + const [iframeSrc, setIframeSrc] = useState('') + const [status, setStatus] = useState<'loading' | 'ready' | 'empty'>('loading') + + useEffect(() => { + const getDiscoUrl = () => { + const canonicalHref = document.querySelector('link[rel="canonical"]')?.getAttribute('href') + const ogUrl = document.querySelector('meta[property="og:url"]')?.getAttribute('content') + const base = canonicalHref || ogUrl + if (!base) return window.location.href + try { + const parsed = new URL(base) + return `${parsed.origin}${window.location.pathname}` + } catch { + return window.location.href + } + } + + const discoUrl = getDiscoUrl() + const discoTitle = document.querySelector('meta[property="og:title"]')?.getAttribute('content') || document.title + const src = `https://disco.headliner.link/d/web/widget.html?widgetId=${encodeURIComponent(HEADLINER_WIDGET_ID)}&url=${encodeURIComponent(discoUrl)}&title=${encodeURIComponent(discoTitle)}` + + const sessionId = `SS_siteforge_${Date.now()}_${Math.random().toString(36).slice(2, 10)}` + const query = new URLSearchParams({ + sessionId, + url: discoUrl, + widgetId: HEADLINER_WIDGET_ID, + }) + + fetch(`https://api.headliner.link/api/v1/widget/widget-request?${query.toString()}`) + .then(r => (r.ok ? r.json() : Promise.reject(new Error('widget request failed')))) + .then((data: { results?: unknown[] }) => { + if (Array.isArray(data.results) && data.results.length > 0) { + setIframeSrc(src) + setStatus('ready') + return + } + setStatus('empty') + }) + .catch(() => { + // If API probing fails, still attempt iframe rendering. + setIframeSrc(src) + setStatus('ready') + }) + }, []) + + return ( + status === 'empty' ? null : ( +
+ {status === 'ready' && iframeSrc && ( +