Skip to content

Commit f2932fe

Browse files
committed
feat(demo): build deployable demo site with themed layout and player demos
- Replace bare-bones baseof.html with full demo page layout - Sticky header, centered container, system font stack - Light/dark theme toggle with localStorage persistence - Responsive breakpoint at 640px - Rewrite _index.md with 6 demo sections: - Basic player, poster, chapters, persistence (with A/B comparison), theming - Parameter reference table, links section - Enable unsafe raw HTML in Goldmark renderer for demo page layout - Add GitHub Pages deploy workflow (builds exampleSite, deploys on push to main)
1 parent 186d5b4 commit f2932fe

4 files changed

Lines changed: 308 additions & 14 deletions

File tree

.github/workflows/deploy-demo.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Deploy Demo Site
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- "exampleSite/**"
8+
- "layouts/**"
9+
- "assets/**"
10+
- ".github/workflows/deploy-demo.yml"
11+
# Allow manual trigger from Actions tab
12+
workflow_dispatch:
13+
14+
# Allow only one concurrent deployment
15+
concurrency:
16+
group: pages
17+
cancel-in-progress: true
18+
19+
jobs:
20+
deploy:
21+
name: Build & Deploy to GitHub Pages
22+
runs-on: ubuntu-latest
23+
permissions:
24+
contents: read
25+
pages: write
26+
id-token: write
27+
environment:
28+
name: github-pages
29+
url: ${{ steps.deployment.outputs.page_url }}
30+
31+
steps:
32+
- uses: actions/checkout@v4
33+
34+
- uses: actions/setup-go@v5
35+
with:
36+
go-version: "1.23"
37+
38+
- uses: peaceiris/actions-hugo@v3
39+
with:
40+
hugo-version: "0.146.0"
41+
extended: true
42+
43+
- name: Setup Pages
44+
uses: actions/configure-pages@v5
45+
46+
- name: Build demo site
47+
run: hugo --source exampleSite --minify --baseURL "${{ steps.pages.outputs.base_url }}/"
48+
49+
- name: Upload artifact
50+
uses: actions/upload-pages-artifact@v3
51+
with:
52+
path: exampleSite/public
53+
54+
- name: Deploy to GitHub Pages
55+
id: deployment
56+
uses: actions/deploy-pages@v4

exampleSite/content/_index.md

Lines changed: 150 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,156 @@
11
---
2-
title: "Podcast Demo Site"
2+
title: "Podcast Player Demo"
33
---
44

5-
# Hugo Podcast Shortcode Demo
5+
<section class="hero">
6+
<h1>Hugo Podcast Shortcode</h1>
7+
<p>A reusable <strong>&lt;podcast-player&gt;</strong> Web Component for Hugo — persistent audio playback with chapter navigation, poster support, and full accessibility. Drop it into any post with a single shortcode.</p>
8+
</section>
69

7-
Welcome to the demo site for the [hugo-podcast-shortcode](https://github.com/adurrr/hugo-podcast-shortcode) module.
10+
<section class="demo-section">
11+
<h2>📻 Basic Player</h2>
12+
<p class="desc">Minimal usage — just a <code>src</code> and <code>title</code>.</p>
13+
<div class="demo-player">
14+
<div class="player-wrapper">
15+
{{< podcast-player
16+
src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3"
17+
title="SoundHelix: Ambient Demo"
18+
>}}
19+
</div>
20+
</div>
21+
<div class="demo-code">
22+
<code>\{\{&lt; podcast-player
23+
src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3"
24+
title="SoundHelix: Ambient Demo"
25+
&gt;\}\}</code>
26+
</div>
27+
</section>
828

9-
## Episodes
29+
<section class="demo-section">
30+
<h2>🎵 Player with Poster</h2>
31+
<p class="desc">Show an album-art poster alongside the controls.</p>
32+
<div class="demo-player">
33+
<div class="player-wrapper">
34+
{{< podcast-player
35+
src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3"
36+
title="SoundHelix: Chilled Beats"
37+
poster="https://picsum.photos/seed/player1/400/400"
38+
>}}
39+
</div>
40+
</div>
41+
<div class="demo-code">
42+
<code>\{\{&lt; podcast-player
43+
src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3"
44+
title="SoundHelix: Chilled Beats"
45+
poster="https://picsum.photos/seed/player1/400/400"
46+
&gt;\}\}</code>
47+
</div>
48+
</section>
1049

11-
- [Test Episode](/posts/test-episode/)
50+
<section class="demo-section">
51+
<h2>📖 Player with Chapters</h2>
52+
<p class="desc">Add timestamp-labelled chapters for easy navigation.</p>
53+
<div class="demo-player">
54+
<div class="player-wrapper">
55+
{{< podcast-player
56+
src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-3.mp3"
57+
title="SoundHelix: Long Mix"
58+
poster="https://picsum.photos/seed/player2/400/400"
59+
chapters="00:00:00-Intro,00:00:45-Buildup,00:02:15-Main Theme,00:04:00-Bridge,00:05:30-Climax,00:06:45-Outro"
60+
persistent="true"
61+
>}}
62+
</div>
63+
</div>
64+
<div class="demo-code">
65+
<code>\{\{&lt; podcast-player
66+
src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-3.mp3"
67+
title="SoundHelix: Long Mix"
68+
poster="https://picsum.photos/seed/player2/400/400"
69+
chapters="00:00:00-Intro,00:00:45-Buildup,00:02:15-Main Theme,00:04:00-Bridge,00:05:30-Climax,00:06:45-Outro"
70+
persistent="true"
71+
&gt;\}\}</code>
72+
</div>
73+
</section>
74+
75+
<section class="demo-section">
76+
<h2>💾 Persistence Demo</h2>
77+
<p class="desc">Toggle <code>persistent="true"</code> — the player saves your position, volume, mute, and playback speed to <code>sessionStorage</code>. Navigate between pages and resume where you left off. Try it on these two instances of the same audio:</p>
78+
79+
<div class="demo-player">
80+
<h3 style="font-size:1rem;margin-bottom:0.5rem">🔁 Player A (with persistence)</h3>
81+
<div class="player-wrapper">
82+
{{< podcast-player
83+
src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-4.mp3"
84+
title="SoundHelix: Persistent Player"
85+
persistent="true"
86+
>}}
87+
</div>
88+
</div>
89+
<div class="demo-code" style="margin-bottom:1rem">
90+
<code>\{\{&lt; podcast-player src="…" title="SoundHelix: Persistent Player" persistent="true" &gt;\}\}</code>
91+
</div>
92+
93+
<div class="demo-player">
94+
<h3 style="font-size:1rem;margin-bottom:0.5rem">🔁 Player B (no persistence)</h3>
95+
<div class="player-wrapper">
96+
{{< podcast-player
97+
src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-4.mp3"
98+
title="SoundHelix: Non-Persistent"
99+
persistent="false"
100+
>}}
101+
</div>
102+
</div>
103+
<div class="demo-code">
104+
<code>\{\{&lt; podcast-player src="…" title="SoundHelix: Non-Persistent" &gt;\}\}</code>
105+
</div>
106+
<p class="desc" style="margin-top:0.75rem;font-size:0.85rem">💡 Play some of Player A, then reload the page — your position, volume, mute, and speed are remembered. Player B always starts fresh.</p>
107+
</section>
108+
109+
<section class="demo-section">
110+
<h2>🎨 Theming</h2>
111+
<p class="desc">Click the <strong>🌙 Dark / ☀️ Light</strong> toggle in the header to switch between built-in themes. The player responds to <code>data-theme</code> on <code>&lt;html&gt;</code>. You can also customise every visual aspect with <a href="https://github.com/adurrr/hugo-podcast-shortcode#css-custom-properties" target="_blank" rel="noopener">CSS custom properties</a> — primary colour, background, radius, progress height, and more.</p>
112+
<div class="demo-player">
113+
<div class="player-wrapper">
114+
{{< podcast-player
115+
src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-5.mp3"
116+
title="SoundHelix: Theme Demo"
117+
>}}
118+
</div>
119+
</div>
120+
</section>
121+
122+
<section class="demo-section">
123+
<h2>📋 All Shortcode Parameters</h2>
124+
<p class="desc">These can be passed per-invocation or set globally in <code>hugo.toml</code> under <code>[params.podcastPlayer]</code>:</p>
125+
126+
<table style="width:100%;border-collapse:collapse;font-size:0.9rem">
127+
<thead>
128+
<tr style="border-bottom:2px solid var(--border);text-align:left">
129+
<th style="padding:0.5rem 0.75rem">Param</th>
130+
<th style="padding:0.5rem 0.75rem">Default</th>
131+
<th style="padding:0.5rem 0.75rem">Description</th>
132+
</tr>
133+
</thead>
134+
<tbody>
135+
<tr style="border-bottom:1px solid var(--border)"><td style="padding:0.5rem 0.75rem"><code>src</code></td><td style="padding:0.5rem 0.75rem">—</td><td style="padding:0.5rem 0.75rem">Audio URL or local resource path</td></tr>
136+
<tr style="border-bottom:1px solid var(--border)"><td style="padding:0.5rem 0.75rem"><code>title</code></td><td style="padding:0.5rem 0.75rem">—</td><td style="padding:0.5rem 0.75rem">Episode title (required for a11y)</td></tr>
137+
<tr style="border-bottom:1px solid var(--border)"><td style="padding:0.5rem 0.75rem"><code>type</code></td><td style="padding:0.5rem 0.75rem"><code>local</code></td><td style="padding:0.5rem 0.75rem">Source type: <code>local</code>, <code>azuracast</code>, <code>ivoox</code></td></tr>
138+
<tr style="border-bottom:1px solid var(--border)"><td style="padding:0.5rem 0.75rem"><code>persistent</code></td><td style="padding:0.5rem 0.75rem"><code>false</code></td><td style="padding:0.5rem 0.75rem">Save/resume playback in sessionStorage</td></tr>
139+
<tr style="border-bottom:1px solid var(--border)"><td style="padding:0.5rem 0.75rem"><code>preload</code></td><td style="padding:0.5rem 0.75rem"><code>metadata</code></td><td style="padding:0.5rem 0.75rem">HTML5 <code>&lt;audio&gt;</code> preload hint</td></tr>
140+
<tr style="border-bottom:1px solid var(--border)"><td style="padding:0.5rem 0.75rem"><code>autoplay</code></td><td style="padding:0.5rem 0.75rem"><code>false</code></td><td style="padding:0.5rem 0.75rem">Start playing on page load</td></tr>
141+
<tr style="border-bottom:1px solid var(--border)"><td style="padding:0.5rem 0.75rem"><code>rate</code></td><td style="padding:0.5rem 0.75rem"><code>1</code></td><td style="padding:0.5rem 0.75rem">Playback speed multiplier</td></tr>
142+
<tr style="border-bottom:1px solid var(--border)"><td style="padding:0.5rem 0.75rem"><code>poster</code></td><td style="padding:0.5rem 0.75rem">—</td><td style="padding:0.5rem 0.75rem">Cover image URL</td></tr>
143+
<tr style="border-bottom:1px solid var(--border)"><td style="padding:0.5rem 0.75rem"><code>chapters</code></td><td style="padding:0.5rem 0.75rem">—</td><td style="padding:0.5rem 0.75rem">Comma-separated <code>time-label</code> list</td></tr>
144+
<tr><td style="padding:0.5rem 0.75rem"><code>description</code></td><td style="padding:0.5rem 0.75rem">—</td><td style="padding:0.5rem 0.75rem">Rich text description (supports Markdown)</td></tr>
145+
</tbody>
146+
</table>
147+
</section>
148+
149+
<section class="demo-section">
150+
<h2>🔗 Links</h2>
151+
<ul class="link-list">
152+
<li><a href="https://github.com/adurrr/hugo-podcast-shortcode" target="_blank" rel="noopener">GitHub Repository</a> — source code, issues, contributing</li>
153+
<li><a href="https://github.com/adurrr/hugo-podcast-shortcode#readme" target="_blank" rel="noopener">README</a> — full documentation, install guide, all CSS custom properties and <code>::part()</code> selectors</li>
154+
<li><a href="https://github.com/adurrr/hugo-podcast-shortcode?tab=readme-ov-file#keyboard-shortcuts" target="_blank" rel="noopener">Keyboard Shortcuts</a> — Space, arrows, M, and more</li>
155+
</ul>
156+
</section>

exampleSite/hugo.toml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
1-
baseURL = "https://podcast-demo.example.org/"
2-
title = "Podcast Demo Site"
1+
baseURL = "https://adurrr.github.io/hugo-podcast-shortcode/"
2+
title = "Hugo Podcast Shortcode Demo"
33
languageCode = "en-us"
4+
description = "Live demo for the hugo-podcast-shortcode module — a persistent <podcast-player> Web Component for Hugo"
5+
ignoreLogs = ["warning-goldmark-raw-html"]
6+
7+
# Allow raw HTML in Markdown (used in demo page layout)
8+
[markup]
9+
[markup.goldmark]
10+
[markup.goldmark.renderer]
11+
unsafe = true
412

513
# Import the local module for development
614
[module]
Lines changed: 92 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,109 @@
11
<!DOCTYPE html>
2-
<html lang="{{ .Site.LanguageCode }}">
2+
<html lang="{{ .Site.LanguageCode }}" data-theme="light">
33
<head>
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
66
<title>{{ block "title" . }}{{ .Site.Title }}{{ end }}</title>
7+
<meta name="description" content="{{ .Site.Params.description }}">
8+
{{ with .OutputFormats.Get "rss" -}}
9+
{{ printf `<link rel=%q type=%q href=%q title=%q>` .Rel .MediaType.Type .Permalink $.Site.Title | safeHTML }}
10+
{{ end -}}
11+
<style>
12+
/* ── Reset & base ── */
13+
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
14+
html{font-family:system-ui,-apple-system,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif;font-size:16px;line-height:1.6;scroll-behavior:smooth}
15+
body{background:var(--bg);color:var(--text);min-height:100vh;display:flex;flex-direction:column}
16+
17+
/* ── Theme variables ── */
18+
:root,[data-theme="light"]{--bg:#fafafa;--surface:#ffffff;--text:#1a1a2e;--text-muted:#6b7280;--accent:#4f46e5;--accent-hover:#4338ca;--border:#e5e7eb;--radius:8px;--max-w:960px}
19+
[data-theme="dark"]{--bg:#0f0f1a;--surface:#1a1a2e;--text:#e4e4ed;--text-muted:#9ca3af;--accent:#818cf8;--accent-hover:#6366f1;--border:#2d2d44}
20+
21+
/* ── Layout ── */
22+
.container{max-width:var(--max-w);margin:0 auto;padding:0 1.5rem;width:100%}
23+
header{background:var(--surface);border-bottom:1px solid var(--border);padding:1rem 0;position:sticky;top:0;z-index:100;backdrop-filter:blur(8px)}
24+
header .container{display:flex;align-items:center;gap:1rem;flex-wrap:wrap}
25+
header .site-title{font-size:1.1rem;font-weight:700;color:var(--accent);text-decoration:none;margin-right:auto}
26+
header nav{display:flex;gap:1rem;align-items:center}
27+
header nav a{color:var(--text-muted);text-decoration:none;font-size:0.9rem;transition:color .15s}
28+
header nav a:hover{color:var(--accent)}
29+
main{flex:1;padding:2rem 0}
30+
footer{background:var(--surface);border-top:1px solid var(--border);padding:1.5rem 0;text-align:center;color:var(--text-muted);font-size:0.85rem}
31+
footer a{color:var(--accent)}
32+
33+
/* ── Theme toggle button ── */
34+
#theme-toggle{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);color:var(--text);cursor:pointer;font-size:0.85rem;padding:0.35rem 0.75rem;transition:background .15s,border-color .15s;white-space:nowrap}
35+
#theme-toggle:hover{background:var(--border)}
36+
37+
/* ── Hero ── */
38+
.hero{padding:2rem 0 1rem}
39+
.hero h1{font-size:2rem;font-weight:800;letter-spacing:-0.02em;margin-bottom:0.5rem}
40+
.hero p{color:var(--text-muted);font-size:1.05rem;max-width:640px}
41+
42+
/* ── Demo sections ── */
43+
.demo-section{margin-bottom:3rem}
44+
.demo-section h2{font-size:1.4rem;font-weight:700;margin-bottom:0.25rem}
45+
.demo-section .desc{color:var(--text-muted);font-size:0.92rem;margin-bottom:1rem}
46+
.demo-player{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:1.25rem;margin-bottom:1rem}
47+
.demo-player .player-wrapper{max-width:700px}
48+
.demo-code{background:#1a1a2e;color:#e4e4ed;border-radius:var(--radius);font-size:0.82rem;overflow-x:auto;padding:1rem;margin-top:0.75rem}
49+
.demo-code code{white-space:pre-wrap;word-break:break-all}
50+
.badge{display:inline-block;background:var(--accent);color:#fff;border-radius:999px;font-size:0.7rem;font-weight:600;padding:0.15rem 0.6rem;text-transform:uppercase;letter-spacing:0.03em;margin-right:0.4rem;vertical-align:middle}
51+
52+
/* ── Responsive ── */
53+
@media(max-width:640px){
54+
.hero h1{font-size:1.5rem}
55+
header .container{gap:0.5rem}
56+
header nav{order:3;width:100%;justify-content:flex-start;padding-top:0.35rem;border-top:1px solid var(--border)}
57+
}
58+
59+
/* ── Link list ── */
60+
.link-list{list-style:none;padding:0;margin:1rem 0}
61+
.link-list li{margin-bottom:0.5rem}
62+
.link-list a{color:var(--accent);text-decoration:none;font-weight:500}
63+
.link-list a:hover{text-decoration:underline}
64+
</style>
765
</head>
866
<body>
967
<header>
10-
<nav>
11-
<a href="/">Home</a>
12-
<a href="/posts/test-episode/">Test Episode</a>
13-
</nav>
68+
<div class="container">
69+
<a href="/" class="site-title">{{ .Site.Title }}</a>
70+
<nav>
71+
<a href="/">Home</a>
72+
<a href="https://github.com/adurrr/hugo-podcast-shortcode" target="_blank" rel="noopener">GitHub</a>
73+
</nav>
74+
<button id="theme-toggle" aria-label="Toggle color theme">🌙 Dark</button>
75+
</div>
1476
</header>
1577

1678
<main>
17-
{{ block "main" . }}{{ end }}
79+
<div class="container">
80+
{{ block "main" . }}{{ end }}
81+
</div>
1882
</main>
1983

2084
<footer>
21-
<p>Powered by Hugo Podcast Shortcode</p>
85+
<div class="container">
86+
<p>Powered by <a href="https://github.com/adurrr/hugo-podcast-shortcode" target="_blank" rel="noopener">hugo-podcast-shortcode</a> — built with Hugo</p>
87+
</div>
2288
</footer>
89+
90+
<script>
91+
(function() {
92+
const btn = document.getElementById('theme-toggle');
93+
const html = document.documentElement;
94+
const STORAGE_KEY = 'podcast-demo-theme';
95+
96+
function getPreferred() { return localStorage.getItem(STORAGE_KEY) || 'light'; }
97+
function apply(theme) {
98+
html.setAttribute('data-theme', theme);
99+
localStorage.setItem(STORAGE_KEY, theme);
100+
btn.textContent = theme === 'dark' ? '☀️ Light' : '🌙 Dark';
101+
}
102+
function toggle() { apply(html.getAttribute('data-theme') === 'dark' ? 'light' : 'dark'); }
103+
104+
apply(getPreferred());
105+
btn.addEventListener('click', toggle);
106+
})();
107+
</script>
23108
</body>
24109
</html>

0 commit comments

Comments
 (0)