add a Content pack nav link to blog category
This commit is contained in:
parent
4d86d9b7e8
commit
cd272c5e8d
4 changed files with 74 additions and 3 deletions
70
www/blog/2026-04-22-contentpack-podcast.mdx
Normal file
70
www/blog/2026-04-22-contentpack-podcast.mdx
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
---
|
||||||
|
slug: contentpack-podcast
|
||||||
|
title: Podcast Delivery Without Internet
|
||||||
|
authors: [nxf99]
|
||||||
|
tags: [contentpack]
|
||||||
|
---
|
||||||
|
|
||||||
|
We have released a [small, self-contained sample podcast content pack](https://guardianproject.dev/butter/contentpack-sample-podcast), built on a webpage and RSS feed from [Guardian Project](https://guardianproject.info/podcast). This repository is intended as an example "content pack": a minimal, portable bundle of everything needed to host and distribute a podcast, including episode audio, show notes, a landing page, and a standards-compliant feed.
|
||||||
|
|
||||||
|
## What's inside
|
||||||
|
|
||||||
|
- **`index.html`** : A simple, styled landing page that lists each episode with inline audio playback.
|
||||||
|
- **`podcast.xml`** : An RSS 2.0 feed with iTunes podcast extensions, suitable for submission to podcast directories and use in podcast players.
|
||||||
|
- **`posts/*.md`** : Per-episode show notes in Markdown (YAML frontmatter holds the episode metadata).
|
||||||
|
- **`posts/*.mp3`** : The episode audio files, colocated with their show notes.
|
||||||
|
- **`build.sh`** : Regenerates `index.html` and `podcast.xml` from the contents of `posts/`.
|
||||||
|
|
||||||
|
{/* truncate */}
|
||||||
|
|
||||||
|
## Using it
|
||||||
|
|
||||||
|
Because everything in `index.html` is relative-linked, you can serve this site from a folder on a USB drive plugged into a ButterBox device.
|
||||||
|
|
||||||
|
To subscribe in a podcast client, point it at the hosted URL of `podcast.xml`.
|
||||||
|
|
||||||
|
## Building `index.html` and `podcast.xml`
|
||||||
|
|
||||||
|
Both output files are generated from the markdown posts in `posts/` by `build.sh`. Run the script any time you add, remove, or edit a post:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./build.sh <baseURL>
|
||||||
|
```
|
||||||
|
|
||||||
|
The single required argument is the **absolute URL prefix where the mp3 files will be served**. It is only used for the `<enclosure url="...">` entries in `podcast.xml`, because RSS enclosures must be absolute URLs so podcast clients can download them without knowing where the feed lives. Everything else in the generated files (the RSS `<link>`, the `<audio>` players in `index.html`, and the link to the feed itself) stays relative, so you can still move the whole bundle around and serve it from any path.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
If the files will be served from a USB drive called `usb-butter` plugged into a ButterBox, inside a folder named `engardepodcast`, run:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./build.sh http://butterbox.local/serve_file/media/usb-butter/engardepodcast/
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that `butterbox.local` in the URL must match the configured hostname of your ButterBox. `butterbox.local` is the default, but if you have changed yours to, for example, `someotherbox.local`, use that hostname instead.
|
||||||
|
|
||||||
|
The script will produce `podcast.xml` with enclosures like:
|
||||||
|
|
||||||
|
```
|
||||||
|
http://butterbox.local/serve_file/media/usb-butter/engardepodcast/posts/ProofModeCaravan-English-Feb2024.mp3
|
||||||
|
```
|
||||||
|
|
||||||
|
and an `index.html` whose audio elements still use the relative `posts/<file>.mp3` path.
|
||||||
|
|
||||||
|
### How it works
|
||||||
|
|
||||||
|
For each `posts/*.md` file (sorted newest-first by filename date prefix), the script:
|
||||||
|
|
||||||
|
1. Parses the YAML frontmatter (`title`, `date`, `description`, `file`, `voices`, `keywords`, `duration`/`length`, `explicit`).
|
||||||
|
2. Looks up the referenced mp3 in `posts/` and reads its real byte size with `stat` for the RSS `length` attribute.
|
||||||
|
3. Picks whichever of the `duration`/`length` frontmatter fields actually looks like `HH:MM[:SS]` for `<itunes:duration>` (the two fields are used inconsistently across the sample posts).
|
||||||
|
4. Normalizes the `date` field into an RFC 822 `<pubDate>`.
|
||||||
|
5. Emits one `<item>` block into `podcast.xml` and one `<article class="episode">` block into `index.html`.
|
||||||
|
|
||||||
|
Adding a new episode is just a matter of dropping a new `YYYY-MM-DD-slug.md` file and its `.mp3` into `posts/` and re-running `build.sh`.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
All content in this repository (audio, show notes, webpage, and feed) is released under [Creative Commons Zero (CC0 1.0)](https://creativecommons.org/publicdomain/zero/1.0/). You may copy, modify, distribute, and use the material for any purpose, including commercial, without asking permission.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
nxf99:
|
nxf99:
|
||||||
name: Nathan Freitas
|
name: Nathan
|
||||||
title: Director, Guardian Project
|
title: Director, Guardian Project
|
||||||
url: https://nathan.freitas.net
|
url: https://nathan.freitas.net
|
||||||
image_url: https://avatars.githubusercontent.com/u/30851?v=4
|
image_url: https://avatars.githubusercontent.com/u/30851?v=4
|
||||||
|
|
@ -9,11 +9,11 @@ nxf99:
|
||||||
newsletter: https://nathan.freitas.net
|
newsletter: https://nathan.freitas.net
|
||||||
|
|
||||||
fabby:
|
fabby:
|
||||||
name: Fabiola M.
|
name: Fabby
|
||||||
title: Community Lead
|
title: Community Lead
|
||||||
image_url: https://avatars.githubusercontent.com/u/30851?v=4
|
image_url: https://avatars.githubusercontent.com/u/30851?v=4
|
||||||
|
|
||||||
trob:
|
trob:
|
||||||
name: Tiffany R.
|
name: Tiff
|
||||||
title: Project Coordinator
|
title: Project Coordinator
|
||||||
image_url: https://avatars.githubusercontent.com/u/30851?v=4
|
image_url: https://avatars.githubusercontent.com/u/30851?v=4
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,7 @@ const config: Config = {
|
||||||
},
|
},
|
||||||
{to: '/contact', label: 'Get In Touch', position: 'left'},
|
{to: '/contact', label: 'Get In Touch', position: 'left'},
|
||||||
{to: '/blog', label: 'Blog', position: 'left'},
|
{to: '/blog', label: 'Blog', position: 'left'},
|
||||||
|
{to: '/blog/tags/contentpack', label: 'Content Packs', position: 'left'},
|
||||||
{
|
{
|
||||||
type: 'localeDropdown',
|
type: 'localeDropdown',
|
||||||
position: 'right',
|
position: 'right',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue