How to add a narrated demo video to your GitHub README
Record a narrated walkthrough of your project, embed a GIF in the README, and link to the full MP4. No screen recorder, no editing, no re-recording when the UI changes.
How to Add a Narrated Demo Video to Your GitHub README
A project with a demo video gets more stars, more contributors, and more users than one without. The problem: recording a good demo takes longer than writing the feature. You need a screen recorder, audio setup, a take without mistakes, editing, and a host for the file.
Here's how to generate one from a script instead.
Record the demo
Define the walkthrough once. Make two API calls — one for the narrated MP4, one for the README GIF. Both return binary directly.
import fs from 'fs';
const steps = [
{ action: 'navigate', url: 'https://yourproject.com', note: 'Open the project' },
{ action: 'click', selector: '#quick-start', note: 'Click Quick Start' },
{ action: 'fill', selector: '#input', value: 'Hello world', note: 'Enter a value' },
{ action: 'click', selector: '#run', note: 'Run it' },
{ action: 'wait_for', selector: '.output', note: 'See the result' }
];
const sharedOptions = {
steps,
audioGuide: {
enabled: true,
voice: 'nova',
script: "Here's how it works. {{1}} Hit Quick Start. {{2}} Enter any value. {{3}} Run it — {{4}} and the result appears instantly. {{5}}"
},
frame: { enabled: true, style: 'macos' },
background: { enabled: true, type: 'gradient', gradient: 'ocean' },
cursor: { style: 'highlight', persist: true },
pace: 'slow'
};
// Record narrated MP4
const mp4Res = await fetch('https://api.pagebolt.dev/v1/video', {
method: 'POST',
headers: { 'x-api-key': process.env.PAGEBOLT_API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ ...sharedOptions, format: 'mp4' })
});
fs.writeFileSync('demo/walkthrough.mp4', Buffer.from(await mp4Res.arrayBuffer()));
// Record GIF for README embed
const gifRes = await fetch('https://api.pagebolt.dev/v1/video', {
method: 'POST',
headers: { 'x-api-key': process.env.PAGEBOLT_API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ ...sharedOptions, format: 'gif' })
});
fs.writeFileSync('demo/walkthrough.gif', Buffer.from(await gifRes.arrayBuffer()));
console.log('Saved demo/walkthrough.mp4 and demo/walkthrough.gif');
Both files land in demo/ ready to commit.
Embed in the README
GitHub renders GIFs inline. Link to the MP4 for anyone who wants the narrated audio version.
## Demo

[Watch narrated demo →](./demo/walkthrough.mp4)
Keep it current with GitHub Actions
Add a workflow that re-records whenever your main branch changes:
name: Update README Demo
on:
push:
branches: [main]
paths:
- 'src/**' # only re-record when source changes
- 'demo/script.js' # or when the demo script changes
jobs:
record:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '20' }
- name: Record demo
run: node demo/record.js
env:
PAGEBOLT_API_KEY: ${{ secrets.PAGEBOLT_API_KEY }}
- name: Commit updated demo files
run: |
git config user.name "github-actions"
git config user.email "actions@github.com"
git add demo/walkthrough.gif demo/walkthrough.mp4
git diff --staged --quiet || git commit -m "chore: update demo GIF and video"
git push
The GIF in your README stays current automatically. When you redesign the UI, push to main — the demo updates on the next run.
Why this beats screen recording
| Screen recorder | Generated demo |
|---|---|
| 20–40 min to record, edit, export | ~2 min to write script, run command |
| Re-record on every UI change | Update JSON, re-run |
| Audio sync issues | Narration synced to steps automatically |
| Hosted on Loom/YouTube | Artifact in your repo or CDN |
The demo definition lives next to your code. It's versioned, reviewable, and reproducible.
Try it free — 100 requests/month, no credit card. → pagebolt.dev
Get Started Free
100 requests/month, no credit card
Screenshots, PDFs, video recording, and browser automation — no headless browser to manage.
Get Your Free API Key →