Demo Reels (Playwright)
Category: Documentation & Demos · Areas: ui, frontend
Description
Category
demo
Areas
ui, frontend
Components
- Recording tool: Playwright — headless browser automation with video capture
- Output: WebM video files (Playwright native) and/or MP4 (via ffmpeg)
- Playback:
<video>embed in microsite, or converted to GIF for README - Reproducible capture: Scripted Playwright spec that drives the UI walkthrough
- Demo scripts: Playwright test files that exercise the app and narrate visually
Constraints
- Demo reels are Playwright specs in
tests/e2e/with areelprefix or tag — they are both valid E2E tests and visual recordings - Video recording is always-on for reel specs (not just on-failure)
- Reel specs run against a seeded database with realistic demo data — the same seed data used for E2E tests
- Recordings must be reproducible — re-running the reel spec should produce equivalent output
- Do not record manual browser sessions — always use a scripted reel spec
- Viewport: 1280x720 (720p) for consistent framing across machines
- No audio — the visual flow must be self-explanatory
- Pacing: include deliberate pauses (
page.waitForTimeout) between actions so the viewer can follow at 1x speed
Demo Reel Requirements
Reel spec conventions
- File pattern:
tests/e2e/00-reel.spec.ts(numbered to run first, before mutation-heavy tests that might dirty the seed data) - Structured as
test.describeblocks, one per section/act - Each test within a describe block is one scene in the reel
- Scenes execute sequentially (
test.describe.serial) — the reel tells a story with state building across scenes - Include visual narration via injected overlay text or page titles between scenes — the viewer should understand what is being demonstrated
Narrative structure
A demo reel tells a story, parallel to demo-asciinema:
- Setup — Show the app’s landing state, dashboard, or login
- Navigation — Demonstrate moving between modules/sections
- Search — Show finding data via search, filters, or command palette
- Editing — Create, update, or delete entities through forms
- Verification — Show the result: updated list, success state, changed data
- Summary — Return to dashboard or overview showing the final state
What to include in a reel
- The app’s primary user journey from start to finish
- Real UI interactions that a user would perform (clicks, typing, navigation)
- Visible data that proves the app works (populated tables, completed forms)
- Transitions between major sections showing the app’s breadth
- Loading states and confirmations — the viewer sees what the user sees
What NOT to include
- Login flows (pre-authenticate or use seeded session)
- Long waits for API responses (seed data should be local/fast)
- Error states (unless error handling IS the demo topic)
- Browser chrome, DevTools, or console output
- Tooltips or hover states that flash too quickly to read at 1x
Playwright Configuration for Reels
// playwright.config.ts — reel-specific settings
const reelConfig = {
use: {
video: {
mode: "on", // always record for reel specs
size: { width: 1280, height: 720 },
},
viewport: { width: 1280, height: 720 },
launchOptions: {
slowMo: 50, // slight delay between actions for visual flow
},
},
};Or per-spec override in the reel file:
test.use({
video: { mode: "on", size: { width: 1280, height: 720 } },
});Video Post-Processing
After the reel spec runs, Playwright writes .webm files to the test
output directory (test-results/).
Post-processing steps:
- Extract: Copy the
.webmfromtest-results/todocs/demos/<name>/recordings/ - Convert (optional):
ffmpeg -i reel.webm -c:v libx264 reel.mp4for broader browser support - Trim (optional): Cut dead time at start/end with ffmpeg
- GIF (optional):
ffmpeg -i reel.webm -vf "fps=10,scale=640:-1" reel.giffor README embedding (keep under 5MB) - Copy to microsite: Place in
website/static/demos/for embedding
Microsite Embedding
Use a standard HTML5 video element or a Hugo shortcode:
<video autoplay loop muted playsinline width="100%">
<source src="/demos/app-reel.mp4" type="video/mp4">
<source src="/demos/app-reel.webm" type="video/webm">
</video>Or a Hugo shortcode (create layouts/shortcodes/demo-video.html):
{{< demo-video src="app-reel" >}}Drift Signals (anti-patterns to reject in review)
- Manual screen recording instead of scripted Playwright spec → automate it
- Reel spec with
video: "off"orvideo: "retain-on-failure"→ must be"on" - Reel spec that depends on external services without seed data → seed locally
- Video with browser chrome visible → use headless or fullscreen viewport
- Reel with no pauses between actions → add
waitForTimeoutfor pacing - Screenshot-only demo → use video for multi-step workflows
When to use
Any project with a web UI that needs to demonstrate functionality to users,
stakeholders, or evaluators. The web equivalent of demo-asciinema — scripted,
reproducible, and version-controlled. Composes with e2e-playwright for the
testing infrastructure and ux-radix for the interaction patterns being
demonstrated.
ADR References
Practices by activity
Agents working in any of these activities inherit the practices below via the bead’s context digest.
Requirements (Frame activity)
- Identify which user journeys need demo reels — prioritize the “first impression” experience (dashboard → search → create → verify)
- Define the narrative arc: what should the viewer understand after watching?
- Determine target audience: evaluators seeing the product for the first time, or users learning a specific workflow?
- Ensure seed data exists that makes the demo look realistic (real names, realistic numbers, populated lists)
Design
- One reel per major workflow or product area — do not combine unrelated features into one recording
- Reel spec lives alongside E2E tests:
tests/e2e/00-reel.spec.ts - Numbered
00-prefix so it runs first, before mutation-heavy tests - Sequential scenes within
test.describe.serialblocks — each scene builds on the previous state - Narrative structure: Landing → Navigate → Search → Edit → Verify → Summary
- Viewport: 1280x720 (720p) — consistent across all recordings
- Pacing: 500-1000ms pause between major actions via
page.waitForTimeout
Implementation
Reel spec structure
import { test } from "@playwright/test";
test.use({
video: { mode: "on", size: { width: 1280, height: 720 } },
viewport: { width: 1280, height: 720 },
});
test.describe.serial("Product Demo Reel", () => {
test("Act 1: Dashboard overview", async ({ page }) => {
await page.goto("/");
await page.waitForTimeout(1000); // let viewer absorb the layout
// assert key elements visible
});
test("Act 2: Navigate to module", async ({ page }) => {
await page.goto("/");
await page.click('[data-testid="nav-finance"]');
await page.waitForTimeout(500);
});
test("Act 3: Search for entity", async ({ page }) => {
await page.goto("/finance");
await page.keyboard.press("Meta+k"); // command palette
await page.waitForTimeout(300);
await page.fill('[role="combobox"]', "Orbital");
await page.waitForTimeout(500);
// select result, navigate
});
test("Act 4: Edit entity", async ({ page }) => {
// create or update via form
await page.waitForTimeout(500);
});
test("Act 5: Verify result", async ({ page }) => {
// show updated list, success toast, changed data
await page.waitForTimeout(1000);
});
});Seed data requirements
- Reel specs run against the same seeded database as E2E tests
- Seed data must look realistic: real company names, plausible addresses, varied statuses, enough rows to fill tables without looking empty
- Deterministic seeds (fixed UUIDs,
ON CONFLICT DO NOTHING) so reels are reproducible - Include multiple entity states (draft, pending, approved, completed) to show workflow progression
Pacing guidelines
| Action | Pause after |
|---|---|
| Page navigation | 1000ms |
| Modal/dialog open | 500ms |
| Form field fill | 300ms per field |
| Button click (submit) | 500ms |
| Search result appear | 500ms |
| Success confirmation | 1000ms |
| Section transition | 1500ms |
Visual narration
Since there is no audio, the UI itself must tell the story:
- Use page titles and breadcrumbs to show location
- Ensure visible feedback for every action (toasts, status changes, count updates)
- Fill forms with readable demo data (not “test123” — use “Orbital Dynamics Corp”, “Q4 2026 Revenue Accrual”)
- If the app has a command palette, show it — it demonstrates power-user capability
Recording
- Ensure seed data:
bun run seedorbun run demoto populate the database - Run the reel spec with video:
bun run test:e2e -- tests/e2e/00-reel.spec.ts - Extract video: Playwright writes
.webmtotest-results/ - Convert (optional):
ffmpeg -i test-results/.../video.webm -c:v libx264 -crf 23 reel.mp4 - Copy to microsite:
cp reel.mp4 website/static/demos/ - Embed: Use
demo-videoshortcode or<video>tag - Commit: Both the source recordings and microsite copy
Steps 1-3 are fully autonomous — an agent or CI job can run them without human interaction as long as the app and database are running.
Testing
- Reel specs are valid E2E tests — they assert correctness, not just visual appearance
- Run reel specs in CI without video (
video: "off") as a smoke test - Run with video locally or in a scheduled CI job to regenerate recordings
- After UI changes that affect the demo flow, re-record and review
Quality Gates
- Reel spec passes (exit 0) — broken demos must not produce recordings
- Video file exists and is playable
- Video is under 30MB for web embedding (compress further with ffmpeg if needed)
- All scenes in the reel exercise real functionality against seeded data
- Demo page in microsite loads and plays the video
Maintenance
- Re-record after major UI changes, navigation restructuring, or data model changes
- Keep seed data aligned with the reel script — if the reel searches for “Orbital Dynamics”, the seed must contain that entity
- When the reel drifts from the actual app behavior, treat it as a bug — either the reel or the app needs fixing
- Reel specs are executable documentation — they must stay correct