← Blog · 24 September 2026 · Lire en français

Adding audio to a Jekyll site

Jekyll builds your pages at build time and serves them as flat files, often on GitHub Pages where plugins are locked down. Here are the two clean routes to add an audio version of your posts, the exact Liquid snippet for the player, and the trap to avoid.

Jekyll has a simple, solid logic: it reads your Markdown files, applies your Liquid templates at build time, and produces a folder of HTML pages served as plain files. No database, no application server running on each visit. That is what makes a Jekyll site fast and durable, and it is also what raises a real question the moment you want to add an audio version of your posts: where do you generate the audio, and where do you wire it in, when nothing runs on the server at the instant a visitor clicks play?

This guide covers Jekyll specifically. For the wider picture of static generators (Next.js, Hugo, Astro), the article adding audio to a static site sets the common frame; here we go into the details particular to Jekyll.

The constraint that decides everything: GitHub Pages

Many Jekyll sites are hosted on GitHub Pages, and GitHub Pages builds your site only with a closed list of approved plugins. You cannot add a custom plugin there that would call a text-to-speech API during the build. That single constraint rules out the "generate the audio inside the Jekyll build itself" approach for most sites, and it points toward two routes that do not depend on the hosted build.

If you build your site yourself (a local build, or a continuous-integration job that publishes the result), the constraint lifts and the third route, the build route, becomes possible again. Just know which of the two cases is yours before you choose.

Route 1: the RSS feed, no code to write

Jekyll produces a full RSS feed as soon as the jekyll-feed plugin is active, and that plugin is on the list GitHub Pages allows. So, with no code, you have a feed that announces each new post. All you do is hand it to WeDispatch: the service watches the feed, detects published posts, generates the matching audio once, and gives you back the player to insert. No change to your build chain, no key exposed. How the feed works as a trigger is detailed on the RSS feed page. This is the recommended route for a Jekyll site on GitHub Pages, precisely because it does not touch what GitHub locks down.

Route 2: the API call at publish time

If you want to decide the exact moment the audio is produced, an explicit API call in your publish script (or in your continuous-integration workflow, before deployment) generates the audio and returns the file URL. You store that URL in the post's front matter, a variable such as audio_url, and your template uses it. The API and CMS page describes this route. It takes a little upfront work and a place to run the script outside GitHub Pages, but it leaves you in full control.

The Liquid snippet for the player

Whichever route you take, the player goes into your post template. Create a file _includes/audio-player.html holding the player code you are given, then call it in your _layouts/post.html, just after the title:

{% if page.audio_url %}{% include audio-player.html src=page.audio_url %}{% endif %}

The if page.audio_url test is the important part: a post with no audio shows no player, and the day the URL is filled in, the player appears with no other change. That is the behaviour to aim for, and it takes two minutes to check on a draft post.

The trap to avoid: generating in the browser

The temptation, on a serverless site, is to call a synthesis API at the moment the visitor clicks play. Do not. You would expose your keys in the public HTML, you would pay for a generation on every listen instead of once, and you would add latency to every playback. The sound model is the same as for your images: produce once at publish time, serve a file afterwards, cached by the CDN. The audio becomes just another asset, and it fits the flat-file philosophy that led you to Jekyll in the first place. That same logic, with no database, is exactly how we approach French text to speech: the work happens once, upstream, not on every visit.

Try it on your own posts

WeDispatch's free tier lets you narrate your content today, with your real text: try it now. The plans are detailed on the pricing page.

Give your articles a voice with WeDispatch

This blog is itself voiced by WeDispatch. Curious how it sounds on your content?

Book a demo

Read next