LLM-driven web product demo automation framework.
DemoForge turns web applications into polished demo videos, GIFs, and interactive demo sites — automatically. Write a declarative demo script, and DemoForge replays it in a real browser, captures the action, adds narration and captions, and produces production-ready output assets.
demoforge.yaml ← Declarative demo script
│
▼
┌─────────────────────────────────────────────────────────┐
│ T6 CLI ── orchestration, config loading, subcommands │
│ │ │
│ ├─ T10a Explorer Agent (LLM-driven discovery) │
│ │ │
│ └─ T9a Renderer (deterministic script replay) │
│ │ │
│ ├─ T5 Browser (Playwright abstraction) │
│ ├─ T9b Cursor (synthetic cursor overlay) │
│ ├─ T11 Effects (zoom, spotlight, callouts) │
│ ├─ T15 Virtual Time (animation stabilization)│
│ └─ T9c Capture (ffmpeg encoding pipeline) │
│ │ │
│ ├─ T12a TTS (narration audio) │
│ ├─ T12b Captions (SRT/VTT/burned-in)│
│ └─ T13 Screenshots (annotation/redaction)
│ │
│ ▼
│ T17 Site (static demo gallery)
│ T16 Matrix (viewport/theme/locale variations)
└─────────────────────────────────────────────────────────┘
| Dependency | Minimum Version | Purpose |
|---|---|---|
| Node.js | 20 (LTS) | Runtime |
| TypeScript | 5.x | Development |
| ffmpeg | 5.x | Video/GIF/WebP encoding |
| Playwright browsers | latest | Browser automation |
| llama-server | latest | LLM-powered exploration (optional for render-only) |
# Clone the repository
git clone https://github.com/your-org/demo-forge.git
cd demo-forge
# Install dependencies
npm install
# Build all packages
npm run build
# Verify the installation
npx demoforge --help
# ffmpeg (Debian/Ubuntu)
sudo apt-get install ffmpeg
# ffmpeg (macOS)
brew install ffmpeg
# Playwright browsers
npx playwright install chromium
# Verify all dependencies
npx demoforge doctor
npx demoforge init
This creates a demoforge.yaml scaffold in the current directory.
Create .demoforge/my-demo.json with a valid Demo Script:
{
"demo": "my-demo",
"title": "My First Demo",
"viewport": { "width": 1280, "height": 720, "scale": 1 },
"narration_mode": "none",
"steps": [
{ "goto": "https://example.com" },
{ "narrate": "Welcome to the demo." },
{ "click": { "role": "link", "name": "More" } },
{ "wait_for": { "text": "Content loaded" } },
{ "done": true }
]
}
npx demoforge render my-demo
This produces video (MP4), GIF, and WebM output in .demoforge/output/my-demo/.
npx demoforge site
This creates a static HTML demo gallery in dist/ with embedded videos and step timelines.
# Start llama-server
llama-server --model ./models/llama-3.2-3b-instruct.Q4_K_M.gguf --port 8080
# Explore a web application
npx demoforge explore http://localhost:3000 --goal "Show the user onboarding flow"
DemoForge is structured as an npm workspaces monorepo with five core packages:
| Package | Scope | Purpose |
|---|---|---|
@demoforge/core | packages/core | Types, schemas, config, LLM client, explorer agent, seed hooks, heal engine |
@demoforge/browser | packages/browser | Shared Playwright abstraction for browser session management |
@demoforge/cli | packages/cli | CLI framework with Commander.js, subcommands, and command handlers |
@demoforge/renderer | packages/renderer | Script replay engine, video capture, effects, TTS, captions, matrix rendering |
@demoforge/site | packages/site | Static demo site generator with gallery and per-flow pages |
demoforge.yaml ──► Config ──► CLI ──► Renderer ──► ffmpeg ──► Output assets
│ │
│ └─► Explorer Agent ──► LLM ──► Demo Script (JSON)
│
└─► Site Generator ──► HTML/CSS/JS ──► dist/
A Demo Script is a JSON or YAML file with the following structure:
{
"demo": "my-flow",
"title": "My Demo Flow",
"viewport": { "width": 1280, "height": 720, "scale": 1 },
"narration_mode": "none",
"steps": [
{ "goto": "https://example.com" },
{ "click": { "role": "button", "name": "Sign Up" } },
{ "fill": { "target": { "role": "textbox", "name": "Email" }, "value": "[email protected]" } },
{ "narrate": "The user enters their email address." },
{ "done": true }
]
}
| Step | Key | Description |
|---|---|---|
| Navigation | { "goto": "<url>" } | Navigate to a URL. Optional settle policy. |
| Click | { "click": <selector> } | Click an element. Optional effect for visual highlight. |
| Hover | { "hover": <selector> } | Hover over an element. |
| Fill | { "fill": { "target": <selector>, "value": "..." } } | Fill an input. Optional typing style. |
| Select | { "select": { "target": <selector>, "value": "..." } } | Select an option from a dropdown. |
| Press | { "press": { "key": "Enter" } } | Press a keyboard key. |
| Scroll | { "scroll": { "amount": 500 } } | Scroll the page by pixels. |
| Wait | { "wait_for": { "text": "Loaded" } } | Wait for text or selector. |
| Narrate | { "narrate": "..." } | Add narration text (for TTS/captions). |
| Screenshot | { "screenshot": { "name": "step-1" } } | Capture a screenshot. |
| Flow Start | { "mark_flow_start": { "name": "flow-1" } } | Mark the start of a named flow. |
| Flow End | { "mark_flow_end": { "name": "flow-1" } } | Mark the end of a named flow. |
| Done | { "done": true } | Signal the end of the demo. |
| Pause | { "pause": 2000 } | Pause for N milliseconds. |
Selectors can be specified in five formats:
{ "role": "button", "name": "Submit" } { "label": "Email" } { "text": "Sign In" }
{ "css": ".submit-btn" } { "xpath": "//button[@type='submit']" } ".submit-btn"
| Option | Short | Description |
|---|---|---|
--config <path> | Path to a custom config file | |
--verbose | -v | Enable debug logging |
--quiet | -q | Suppress non-error output |
--output <dir> | Default output directory |
demoforge initInitialize a new DemoForge project with a scaffold demoforge.yaml.
npx demoforge init
npx demoforge init -o ./my-project
Options:
| Option | Description |
|---|---|
-o, --output <dir> | Directory to initialize in (default: current directory) |
demoforge explore <url>Explore a web application and generate a demo script using the LLM explorer agent.
npx demoforge explore http://localhost:3000 --goal "Show the checkout flow"
npx demoforge explore http://localhost:3000 --goal "Demo the user dashboard" -o .demoforge
Arguments:
| Argument | Description |
|---|---|
<url> | URL of the web application to explore |
Options:
| Option | Description |
|---|---|
--goal <goal> | Description of the demo goal for the explorer |
-o, --output <dir> | Output directory for the generated script (default: .demoforge) |
demoforge render [flows...]Render demo scripts into video and other output assets.
npx demoforge render
npx demoforge render login dashboard
npx demoforge render login -o ./output --skip-seed
Arguments:
| Argument | Description |
|---|---|
[flows...] | Flow names to render (default: all flows in .demoforge/) |
Options:
| Option | Description |
|---|---|
-o, --output <dir> | Output directory for rendered assets |
--skip-seed | Skip the seed-data hook before rendering |
--strict | Fail if no seed hook is configured and app is in empty state |
demoforge siteGenerate a static demo site from rendered flows.
npx demoforge site
npx demoforge site --output dist --title "Product Demos" --theme dark --validate
Options:
| Option | Description |
|---|---|
-o, --output <dir> | Output directory for the static site (default: dist) |
-s, --source <dir> | Source directory with rendered assets (default: .demoforge/output) |
-t, --title <title> | Site title (default: DemoForge Demos) |
--theme <mode> | Theme mode: light or dark (default: light) |
--no-search | Disable search functionality |
--no-tags | Hide tags on pages |
--no-metadata | Hide metadata on flow pages |
--format <format> | Default video format: mp4, webm, gif, webp (default: mp4) |
--validate | Validate assets before generating site |
demoforge doctorCheck system dependencies and report status.
npx demoforge doctor
Checks: ffmpeg, Playwright browsers, llama-server, xvfb.
demoforge heal [flows...]Repair broken selectors in demo scripts using LLM-assisted analysis.
npx demoforge heal login --step 3 --accept
npx demoforge heal login dashboard --step 2 --url http://localhost:3000
Arguments:
| Argument | Description |
|---|---|
[flows...] | Flow names or script file patterns to heal (default: all scripts in .demoforge/) |
Options:
| Option | Description |
|---|---|
-a, --accept | Automatically accept proposed repairs without review |
-o, --output <dir> | Output directory for healed scripts (default: .demoforge) |
-s, --step <index> | Step index to heal (default: auto-detect from render failure) |
-e, --error <message> | Error message from render failure (for context) |
-u, --url <url> | URL to navigate to for page state capture |
demoforge.yamlFull configuration file with all options and defaults:
# Project identification
demo: my-project
title: "My DemoForge Project"
# LLM endpoint (used by explorer agent and heal command)
llm:
base_url: http://localhost:8080
model: llama-3.2-3b-instruct
context_budget: 4096
# Render matrix configuration
render:
viewports:
- width: 1440
height: 900
themes: [light, dark]
locales: [en-US]
# Seed-data hook (runs before browser launch)
seed:
# command: npx prisma db seed
timeout: 30000
# Redaction rules for screenshot blurring
redaction: []
# Output format and size budgets
output:
formats: [mp4, webm, gif]
budgets:
gif: 5242880 # 5 MB
# Narration configuration
narration:
mode: none # none | captions | tts
voice: # Optional: voice identifier for TTS
speed: 1.0 # Optional: speech rate multiplier
# Explorer agent configuration
explorer:
maxSteps: 50 # Maximum exploration steps
maxTime: 60000 # Maximum exploration time (ms)
guardrails:
allowedOrigins: [] # Only allow navigation within these origins
destructiveButtonPatterns:
- "delete account"
- "reset"
- "empty database"
- "permanently delete"
- "wipe data"
destructiveUrlPatterns: []
| Field | Type | Default | Description |
|---|---|---|---|
demo | string | (required) | Project identifier |
title | string | undefined | Human-readable project title |
llm.base_url | string | http://localhost:8080 | OpenAI-compatible API base URL |
llm.model | string | llama-3.2-3b-instruct | Model name |
llm.context_budget | number | 4096 | Token budget for LLM context window |
render.viewports | array | [{width: 1440, height: 900}] | Viewport dimensions for matrix rendering |
render.themes | array | [light, dark] | Color scheme variations |
render.locales | array | [en-US] | Locale variations |
seed.command | string | undefined | Command to run for seed data |
seed.timeout | number | 30000 | Seed hook timeout in ms |
redaction | array | [] | Redaction rules for sensitive data |
output.formats | array | [mp4, webm, gif] | Output formats to produce |
output.budgets.gif | number | 5242880 | GIF size budget in bytes |
narration.mode | string | none | Narration mode: none, captions, or tts |
narration.voice | string | undefined | TTS voice identifier |
narration.speed | number | 1.0 | TTS speech rate |
explorer.maxSteps | number | 50 | Max exploration steps |
explorer.maxTime | number | 60000 | Max exploration time (ms) |
explorer.guardrails.allowedOrigins | array | [] | Allowed navigation origins |
explorer.guardrails.destructiveButtonPatterns | array | (defaults) | Blocked destructive button patterns |
explorer.guardrails.destructiveUrlPatterns | array | [] | Blocked destructive URL patterns |
@demoforge/coreCore types, schemas, and utilities.
import {
// Types
type DemoScript,
type DemoStep,
type Viewport,
type Selector,
type Effect,
type NarrationMode,
type ActionType,
type ViewportConfig,
type RenderMatrix,
// Schemas
demoScriptSchema,
demoStepSchema,
validateDemoScript,
// Errors
DemoForgeError,
ValidationError,
RenderError,
ExplorerError,
HealError,
ConfigError,
LlmUnavailableError,
LlmTimeoutError,
LlmApiError,
SeedError,
// LLM client
LlmClient,
TokenCounter,
plannerConfig,
copywriterConfig,
// Config
type Config,
type LLMConfig,
type RenderConfig,
type SeedConfig,
type ExplorerConfig,
defaults,
loadConfig,
initConfig,
// Explorer agent
ExplorerAgent,
Guardrails,
// Seed hook
runSeedHook,
// Heal engine
type HealConfig,
type FailingStep,
type HealResult,
healStep,
applyPatches,
extractFailingStep,
// Logger
createLogger,
createSilentLogger,
createDebugLogger,
} from "@demoforge/core";
@demoforge/browserShared Playwright abstraction.
import {
BrowserSession,
BrowserSetup,
resolveSelector,
} from "@demoforge/browser";
// Usage
const browser = new BrowserSession({
headless: true,
viewport: { width: 1280, height: 720 },
});
await browser.launch();
await browser.goto("https://example.com");
await browser.click({ role: "link", name: "More" });
await browser.screenshot({ fullPage: true });
await browser.close();
@demoforge/rendererScript replay engine and video capture.
import {
// Replay
Renderer,
RenderError,
stabilityDetect,
detectCSP,
accessibilityDiff,
// Virtual time
VirtualTimeController,
// Cursor
Cursor,
cubicBezier,
easeInOut,
easeOut,
// TTS
TtsEngine,
PiperBackend,
KokoroBackend,
OpenAiBackend,
generateLicenseFile,
// Captions
CaptionGenerator,
BurnedInCaptions,
SidecarCaptionWriter,
// Effects
EffectsManager,
// Capture
type CapturePipelineConfig,
// Matrix
RenderMatrix,
generateCellId,
computeMatrixCombinations,
calculateSSIM,
} from "@demoforge/renderer";
@demoforge/siteStatic demo site generator.
import { SiteGenerator } from "@demoforge/site";
const generator = new SiteGenerator("./dist", {
siteTitle: "My Demos",
searchEnabled: true,
showTags: true,
showMetadata: true,
defaultVideoFormat: "mp4",
theme: {
mode: "light",
colors: { primary: "#3b82f6" },
fonts: { heading: "Inter, sans-serif" },
},
});
// Discover and add flows
generator.addFlow(flowConfig);
// Generate the site
generator.generate();
// Validate assets
const result = generator.validateAssets();
See the examples/ directory for complete, schema-validated demo scripts:
| Script | Description | Steps |
|---|---|---|
examples/login-flow.json | User login flow with form fill and dashboard landing | 10 |
examples/dashboard-walkthrough.json | Dashboard navigation with metric highlights | 12 |
examples/form-submission.json | Contact form with validation and success confirmation | 14 |
# Place example scripts in .demoforge/
cp examples/*.json .demoforge/
# Render all example demos
npx demoforge render
# Render a specific example
npx demoforge render login-flow
DemoForge produces its own demo assets using the full pipeline:
# Build DemoForge first
npm run build
# Run dogfooding: produce demo assets using DemoForge itself
# This exercises: CLI, renderer, capture pipeline, TTS, captions, site generator
# 1. Render demo assets
npx demoforge render --source examples --output demo-assets
# 2. Generate demo site from dogfood assets
npx demoforge site --source demo-assets --output demo-site
# 3. Verify the site
open demo-site/index.html
The dogfooding pipeline uses:
demoforge render, demoforge site)See CONTRIBUTING.md for details on:
MIT
LLM-driven web product demo automation framework.
DemoForge turns web applications into polished demo videos, GIFs, and interactive demo sites — automatically. Write a declarative demo script, and DemoForge replays it in a real browser, captures the action, adds narration and captions, and produces production-ready output assets.
demoforge.yaml ← Declarative demo script
│
▼
┌─────────────────────────────────────────────────────────┐
│ T6 CLI ── orchestration, config loading, subcommands │
│ │ │
│ ├─ T10a Explorer Agent (LLM-driven discovery) │
│ │ │
│ └─ T9a Renderer (deterministic script replay) │
│ │ │
│ ├─ T5 Browser (Playwright abstraction) │
│ ├─ T9b Cursor (synthetic cursor overlay) │
│ ├─ T11 Effects (zoom, spotlight, callouts) │
│ ├─ T15 Virtual Time (animation stabilization)│
│ └─ T9c Capture (ffmpeg encoding pipeline) │
│ │ │
│ ├─ T12a TTS (narration audio) │
│ ├─ T12b Captions (SRT/VTT/burned-in)│
│ └─ T13 Screenshots (annotation/redaction)
│ │
│ ▼
│ T17 Site (static demo gallery)
│ T16 Matrix (viewport/theme/locale variations)
└─────────────────────────────────────────────────────────┘
| Dependency | Minimum Version | Purpose |
|---|---|---|
| Node.js | 20 (LTS) | Runtime |
| TypeScript | 5.x | Development |
| ffmpeg | 5.x | Video/GIF/WebP encoding |
| Playwright browsers | latest | Browser automation |
| llama-server | latest | LLM-powered exploration (optional for render-only) |
# Clone the repository
git clone https://github.com/your-org/demo-forge.git
cd demo-forge
# Install dependencies
npm install
# Build all packages
npm run build
# Verify the installation
npx demoforge --help
# ffmpeg (Debian/Ubuntu)
sudo apt-get install ffmpeg
# ffmpeg (macOS)
brew install ffmpeg
# Playwright browsers
npx playwright install chromium
# Verify all dependencies
npx demoforge doctor
npx demoforge init
This creates a demoforge.yaml scaffold in the current directory.
Create .demoforge/my-demo.json with a valid Demo Script:
{
"demo": "my-demo",
"title": "My First Demo",
"viewport": { "width": 1280, "height": 720, "scale": 1 },
"narration_mode": "none",
"steps": [
{ "goto": "https://example.com" },
{ "narrate": "Welcome to the demo." },
{ "click": { "role": "link", "name": "More" } },
{ "wait_for": { "text": "Content loaded" } },
{ "done": true }
]
}
npx demoforge render my-demo
This produces video (MP4), GIF, and WebM output in .demoforge/output/my-demo/.
npx demoforge site
This creates a static HTML demo gallery in dist/ with embedded videos and step timelines.
# Start llama-server
llama-server --model ./models/llama-3.2-3b-instruct.Q4_K_M.gguf --port 8080
# Explore a web application
npx demoforge explore http://localhost:3000 --goal "Show the user onboarding flow"
DemoForge is structured as an npm workspaces monorepo with five core packages:
| Package | Scope | Purpose |
|---|---|---|
@demoforge/core | packages/core | Types, schemas, config, LLM client, explorer agent, seed hooks, heal engine |
@demoforge/browser | packages/browser | Shared Playwright abstraction for browser session management |
@demoforge/cli | packages/cli | CLI framework with Commander.js, subcommands, and command handlers |
@demoforge/renderer | packages/renderer | Script replay engine, video capture, effects, TTS, captions, matrix rendering |
@demoforge/site | packages/site | Static demo site generator with gallery and per-flow pages |
demoforge.yaml ──► Config ──► CLI ──► Renderer ──► ffmpeg ──► Output assets
│ │
│ └─► Explorer Agent ──► LLM ──► Demo Script (JSON)
│
└─► Site Generator ──► HTML/CSS/JS ──► dist/
A Demo Script is a JSON or YAML file with the following structure:
{
"demo": "my-flow",
"title": "My Demo Flow",
"viewport": { "width": 1280, "height": 720, "scale": 1 },
"narration_mode": "none",
"steps": [
{ "goto": "https://example.com" },
{ "click": { "role": "button", "name": "Sign Up" } },
{ "fill": { "target": { "role": "textbox", "name": "Email" }, "value": "[email protected]" } },
{ "narrate": "The user enters their email address." },
{ "done": true }
]
}
| Step | Key | Description |
|---|---|---|
| Navigation | { "goto": "<url>" } | Navigate to a URL. Optional settle policy. |
| Click | { "click": <selector> } | Click an element. Optional effect for visual highlight. |
| Hover | { "hover": <selector> } | Hover over an element. |
| Fill | { "fill": { "target": <selector>, "value": "..." } } | Fill an input. Optional typing style. |
| Select | { "select": { "target": <selector>, "value": "..." } } | Select an option from a dropdown. |
| Press | { "press": { "key": "Enter" } } | Press a keyboard key. |
| Scroll | { "scroll": { "amount": 500 } } | Scroll the page by pixels. |
| Wait | { "wait_for": { "text": "Loaded" } } | Wait for text or selector. |
| Narrate | { "narrate": "..." } | Add narration text (for TTS/captions). |
| Screenshot | { "screenshot": { "name": "step-1" } } | Capture a screenshot. |
| Flow Start | { "mark_flow_start": { "name": "flow-1" } } | Mark the start of a named flow. |
| Flow End | { "mark_flow_end": { "name": "flow-1" } } | Mark the end of a named flow. |
| Done | { "done": true } | Signal the end of the demo. |
| Pause | { "pause": 2000 } | Pause for N milliseconds. |
Selectors can be specified in five formats:
{ "role": "button", "name": "Submit" } { "label": "Email" } { "text": "Sign In" }
{ "css": ".submit-btn" } { "xpath": "//button[@type='submit']" } ".submit-btn"
| Option | Short | Description |
|---|---|---|
--config <path> | Path to a custom config file | |
--verbose | -v | Enable debug logging |
--quiet | -q | Suppress non-error output |
--output <dir> | Default output directory |
demoforge initInitialize a new DemoForge project with a scaffold demoforge.yaml.
npx demoforge init
npx demoforge init -o ./my-project
Options:
| Option | Description |
|---|---|
-o, --output <dir> | Directory to initialize in (default: current directory) |
demoforge explore <url>Explore a web application and generate a demo script using the LLM explorer agent.
npx demoforge explore http://localhost:3000 --goal "Show the checkout flow"
npx demoforge explore http://localhost:3000 --goal "Demo the user dashboard" -o .demoforge
Arguments:
| Argument | Description |
|---|---|
<url> | URL of the web application to explore |
Options:
| Option | Description |
|---|---|
--goal <goal> | Description of the demo goal for the explorer |
-o, --output <dir> | Output directory for the generated script (default: .demoforge) |
demoforge render [flows...]Render demo scripts into video and other output assets.
npx demoforge render
npx demoforge render login dashboard
npx demoforge render login -o ./output --skip-seed
Arguments:
| Argument | Description |
|---|---|
[flows...] | Flow names to render (default: all flows in .demoforge/) |
Options:
| Option | Description |
|---|---|
-o, --output <dir> | Output directory for rendered assets |
--skip-seed | Skip the seed-data hook before rendering |
--strict | Fail if no seed hook is configured and app is in empty state |
demoforge siteGenerate a static demo site from rendered flows.
npx demoforge site
npx demoforge site --output dist --title "Product Demos" --theme dark --validate
Options:
| Option | Description |
|---|---|
-o, --output <dir> | Output directory for the static site (default: dist) |
-s, --source <dir> | Source directory with rendered assets (default: .demoforge/output) |
-t, --title <title> | Site title (default: DemoForge Demos) |
--theme <mode> | Theme mode: light or dark (default: light) |
--no-search | Disable search functionality |
--no-tags | Hide tags on pages |
--no-metadata | Hide metadata on flow pages |
--format <format> | Default video format: mp4, webm, gif, webp (default: mp4) |
--validate | Validate assets before generating site |
demoforge doctorCheck system dependencies and report status.
npx demoforge doctor
Checks: ffmpeg, Playwright browsers, llama-server, xvfb.
demoforge heal [flows...]Repair broken selectors in demo scripts using LLM-assisted analysis.
npx demoforge heal login --step 3 --accept
npx demoforge heal login dashboard --step 2 --url http://localhost:3000
Arguments:
| Argument | Description |
|---|---|
[flows...] | Flow names or script file patterns to heal (default: all scripts in .demoforge/) |
Options:
| Option | Description |
|---|---|
-a, --accept | Automatically accept proposed repairs without review |
-o, --output <dir> | Output directory for healed scripts (default: .demoforge) |
-s, --step <index> | Step index to heal (default: auto-detect from render failure) |
-e, --error <message> | Error message from render failure (for context) |
-u, --url <url> | URL to navigate to for page state capture |
demoforge.yamlFull configuration file with all options and defaults:
# Project identification
demo: my-project
title: "My DemoForge Project"
# LLM endpoint (used by explorer agent and heal command)
llm:
base_url: http://localhost:8080
model: llama-3.2-3b-instruct
context_budget: 4096
# Render matrix configuration
render:
viewports:
- width: 1440
height: 900
themes: [light, dark]
locales: [en-US]
# Seed-data hook (runs before browser launch)
seed:
# command: npx prisma db seed
timeout: 30000
# Redaction rules for screenshot blurring
redaction: []
# Output format and size budgets
output:
formats: [mp4, webm, gif]
budgets:
gif: 5242880 # 5 MB
# Narration configuration
narration:
mode: none # none | captions | tts
voice: # Optional: voice identifier for TTS
speed: 1.0 # Optional: speech rate multiplier
# Explorer agent configuration
explorer:
maxSteps: 50 # Maximum exploration steps
maxTime: 60000 # Maximum exploration time (ms)
guardrails:
allowedOrigins: [] # Only allow navigation within these origins
destructiveButtonPatterns:
- "delete account"
- "reset"
- "empty database"
- "permanently delete"
- "wipe data"
destructiveUrlPatterns: []
| Field | Type | Default | Description |
|---|---|---|---|
demo | string | (required) | Project identifier |
title | string | undefined | Human-readable project title |
llm.base_url | string | http://localhost:8080 | OpenAI-compatible API base URL |
llm.model | string | llama-3.2-3b-instruct | Model name |
llm.context_budget | number | 4096 | Token budget for LLM context window |
render.viewports | array | [{width: 1440, height: 900}] | Viewport dimensions for matrix rendering |
render.themes | array | [light, dark] | Color scheme variations |
render.locales | array | [en-US] | Locale variations |
seed.command | string | undefined | Command to run for seed data |
seed.timeout | number | 30000 | Seed hook timeout in ms |
redaction | array | [] | Redaction rules for sensitive data |
output.formats | array | [mp4, webm, gif] | Output formats to produce |
output.budgets.gif | number | 5242880 | GIF size budget in bytes |
narration.mode | string | none | Narration mode: none, captions, or tts |
narration.voice | string | undefined | TTS voice identifier |
narration.speed | number | 1.0 | TTS speech rate |
explorer.maxSteps | number | 50 | Max exploration steps |
explorer.maxTime | number | 60000 | Max exploration time (ms) |
explorer.guardrails.allowedOrigins | array | [] | Allowed navigation origins |
explorer.guardrails.destructiveButtonPatterns | array | (defaults) | Blocked destructive button patterns |
explorer.guardrails.destructiveUrlPatterns | array | [] | Blocked destructive URL patterns |
@demoforge/coreCore types, schemas, and utilities.
import {
// Types
type DemoScript,
type DemoStep,
type Viewport,
type Selector,
type Effect,
type NarrationMode,
type ActionType,
type ViewportConfig,
type RenderMatrix,
// Schemas
demoScriptSchema,
demoStepSchema,
validateDemoScript,
// Errors
DemoForgeError,
ValidationError,
RenderError,
ExplorerError,
HealError,
ConfigError,
LlmUnavailableError,
LlmTimeoutError,
LlmApiError,
SeedError,
// LLM client
LlmClient,
TokenCounter,
plannerConfig,
copywriterConfig,
// Config
type Config,
type LLMConfig,
type RenderConfig,
type SeedConfig,
type ExplorerConfig,
defaults,
loadConfig,
initConfig,
// Explorer agent
ExplorerAgent,
Guardrails,
// Seed hook
runSeedHook,
// Heal engine
type HealConfig,
type FailingStep,
type HealResult,
healStep,
applyPatches,
extractFailingStep,
// Logger
createLogger,
createSilentLogger,
createDebugLogger,
} from "@demoforge/core";
@demoforge/browserShared Playwright abstraction.
import {
BrowserSession,
BrowserSetup,
resolveSelector,
} from "@demoforge/browser";
// Usage
const browser = new BrowserSession({
headless: true,
viewport: { width: 1280, height: 720 },
});
await browser.launch();
await browser.goto("https://example.com");
await browser.click({ role: "link", name: "More" });
await browser.screenshot({ fullPage: true });
await browser.close();
@demoforge/rendererScript replay engine and video capture.
import {
// Replay
Renderer,
RenderError,
stabilityDetect,
detectCSP,
accessibilityDiff,
// Virtual time
VirtualTimeController,
// Cursor
Cursor,
cubicBezier,
easeInOut,
easeOut,
// TTS
TtsEngine,
PiperBackend,
KokoroBackend,
OpenAiBackend,
generateLicenseFile,
// Captions
CaptionGenerator,
BurnedInCaptions,
SidecarCaptionWriter,
// Effects
EffectsManager,
// Capture
type CapturePipelineConfig,
// Matrix
RenderMatrix,
generateCellId,
computeMatrixCombinations,
calculateSSIM,
} from "@demoforge/renderer";
@demoforge/siteStatic demo site generator.
import { SiteGenerator } from "@demoforge/site";
const generator = new SiteGenerator("./dist", {
siteTitle: "My Demos",
searchEnabled: true,
showTags: true,
showMetadata: true,
defaultVideoFormat: "mp4",
theme: {
mode: "light",
colors: { primary: "#3b82f6" },
fonts: { heading: "Inter, sans-serif" },
},
});
// Discover and add flows
generator.addFlow(flowConfig);
// Generate the site
generator.generate();
// Validate assets
const result = generator.validateAssets();
See the examples/ directory for complete, schema-validated demo scripts:
| Script | Description | Steps |
|---|---|---|
examples/login-flow.json | User login flow with form fill and dashboard landing | 10 |
examples/dashboard-walkthrough.json | Dashboard navigation with metric highlights | 12 |
examples/form-submission.json | Contact form with validation and success confirmation | 14 |
# Place example scripts in .demoforge/
cp examples/*.json .demoforge/
# Render all example demos
npx demoforge render
# Render a specific example
npx demoforge render login-flow
DemoForge produces its own demo assets using the full pipeline:
# Build DemoForge first
npm run build
# Run dogfooding: produce demo assets using DemoForge itself
# This exercises: CLI, renderer, capture pipeline, TTS, captions, site generator
# 1. Render demo assets
npx demoforge render --source examples --output demo-assets
# 2. Generate demo site from dogfood assets
npx demoforge site --source demo-assets --output demo-site
# 3. Verify the site
open demo-site/index.html
The dogfooding pipeline uses:
demoforge render, demoforge site)See CONTRIBUTING.md for details on:
MIT