DEV Community

Custodia-Admin
Custodia-Admin

Posted on • Originally published at pagebolt.dev

How to generate a product tour video for your SaaS landing page

How to Generate a Product Tour Video for Your SaaS Landing Page

Most SaaS landing pages have the same problem: the product tour video was recorded six months ago, the UI has changed twice since then, and nobody has time to re-record it. Visitors watch a demo of an interface that no longer exists.

The fix is generating the tour programmatically, so it can be regenerated whenever the product changes.

Define the tour

Write the key screens as a step sequence. This is also your script:

import fs from 'fs';

const res = 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({
    steps: [
      { action: 'navigate', url: 'https://yourapp.com/dashboard', note: 'The dashboard' },
      { action: 'click', selector: '#new-project', note: 'Create a project' },
      { action: 'fill', selector: '#project-name', value: 'My First Project', note: 'Name it' },
      { action: 'click', selector: '#invite-team', note: 'Invite teammates' },
      { action: 'scroll', direction: 'down', amount: 300, note: 'See the activity feed' }
    ],
    audioGuide: {
      enabled: true,
      voice: 'nova',
      script: "This is your dashboard. {{1}} Create a project in one click. {{2}} Give it a name. {{3}} Invite your team — {{4}} and your activity feed updates in real time. {{5}}"
    },
    frame: { enabled: true, style: 'macos' },
    background: { enabled: true, type: 'gradient', gradient: 'ocean' },
    cursor: { style: 'highlight', persist: true },
    pace: 'cinematic'
  })
});

fs.writeFileSync('public/tour.mp4', Buffer.from(await res.arrayBuffer()));
Enter fullscreen mode Exit fullscreen mode

pace: 'cinematic' adds generous pauses between steps — right for a landing page tour where viewers need time to absorb each screen.

Regenerate on deploy

Add a post-deploy script that re-records the tour against your production URL:

// scripts/regenerate-tour.js
const res = 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({
    steps: JSON.parse(fs.readFileSync('tour/steps.json')),
    audioGuide: {
      enabled: true,
      script: fs.readFileSync('tour/narration.txt', 'utf-8')
    },
    frame: { enabled: true, style: 'macos' },
    pace: 'cinematic'
  })
});

fs.writeFileSync('public/tour.mp4', Buffer.from(await res.arrayBuffer()));
console.log('Tour video updated');
Enter fullscreen mode Exit fullscreen mode

Keep tour/steps.json and tour/narration.txt in the repo. When the UI changes, update the JSON. On next deploy, the tour video reflects the current product.

For the GIF preview

Visitors on slow connections or mobile won't autoplay video. Generate a GIF for the above-the-fold preview, linking to the full narrated MP4:

// Generate GIF version for above-the-fold
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({ ...tourOptions, format: 'gif', audioGuide: { enabled: false } })
});
fs.writeFileSync('public/tour-preview.gif', Buffer.from(await gifRes.arrayBuffer()));
Enter fullscreen mode Exit fullscreen mode

Silent GIF loads instantly. Click-to-play reveals the narrated MP4.

What this removes from your workflow

  • No screen recorder setup
  • No "I need to re-record the tour" in your backlog
  • No Loom subscription for a video that lives on one page
  • No stale UI in your product demo

The tour definition is a JSON file and a text script. It's reviewable in a PR, versioned with the product, and regeneratable in 30 seconds.


Try it free — 100 requests/month, no credit card. → pagebolt.dev

Top comments (0)