Hi there again! In the project where we use webreel, the number of demo videos keeps growing. A single config becomes hard to manage, and there's no built-in way to run selective subsets in CI/CD pipelines.
This PR is a working prototype of multi-config support. The goal is to start a conversation about the right API design for scaling webreel to bigger projects and automated pipelines. Everything here is open for discussion -- naming, semantics, the whole surface area.
What the prototype includes
Config: extends
A config can inherit from a base file. Child values override base, theme and sfx get shallow sub-key merge, videos are combined. Chains work up to 10 levels deep, circular refs are detected.
// base.json
{
"baseUrl": "https://myapp.com",
"viewport": "desktop",
"defaultDelay": 500,
"theme": { "cursor": { "size": 32, "hotspot": "top-left" } }
} // webreel.config.json — inherits baseUrl, viewport, defaultDelay
// theme.cursor merges to { "size": 32, "hotspot": "center" }
{
"extends": "./base.json",
"theme": { "cursor": { "hotspot": "center" } },
"videos": {
"hero": { "url": "/", "steps": [{ "action": "pause", "ms": 500 }] },
"login": { "url": "/login", "steps": [{ "action": "pause", "ms": 500 }] }
}
}Config: scenarios
Split videos across multiple files or inline groups. Entries can be glob strings (each matched file loaded as a standalone config) or inline objects with their own videos. extends: true on an inline scenario inherits top-level defaults from the root config. videos is optional when scenarios is present.
// webreel.config.json
{
"baseUrl": "https://myapp.com",
"viewport": { "width": 1920, "height": 1080 },
"scenarios": [
"./demos/*.webreel.json",
{
"extends": true,
"videos": {
"inline-demo": { "url": "/demo", "steps": [] }
}
}
],
"videos": {
"hero": { "url": "/", "steps": [] }
}
} // demos/login.webreel.json — discovered by glob
{
"videos": {
"login": {
"url": "https://myapp.com/login",
"steps": [{ "action": "pause", "ms": 500 }]
}
}
}TypeScript equivalent with defineScenario:
import { defineConfig, defineScenario } from "webreel";
export default defineConfig({
baseUrl: "https://myapp.com",
scenarios: [
"./demos/*.webreel.ts",
defineScenario({
extends: true,
videos: {
login: { url: "/login", steps: [] },
},
}),
],
});CLI: repeatable --config
All commands (record, preview, composite, validate, list) now accept -c/--config multiple times to load several config files in one run. Glob patterns are supported.
$ webreel record -c web.json -c mobile.json
Recording: hero
Done: videos/hero.mp4
Recording: login
Done: videos/login.mp4
Recording: mobile-hero
Done: videos/mobile-hero.mp4
Recording: mobile-login
Done: videos/mobile-login.mp4 $ webreel record -c "configs/*.json"
Recording: hero
Done: videos/hero.mp4
Recording: login
Done: videos/login.mp4CLI: --project filtering
-p/--project filters videos by exact name or glob pattern. Repeatable. Available on record, composite, and list. When combined with positional video names, results are unioned.
# exact name
$ webreel record -p hero
Recording: hero
Done: videos/hero.mp4 # glob pattern
$ webreel record -c web.json -c mobile.json -p "mobile-*"
Recording: mobile-hero
Done: videos/mobile-hero.mp4
Recording: mobile-login
Done: videos/mobile-login.mp4 # multiple patterns
$ webreel record -p hero -p "mobile-*"
Recording: hero
Done: videos/hero.mp4
Recording: mobile-hero
Done: videos/mobile-hero.mp4
Recording: mobile-login
Done: videos/mobile-login.mp4 # union with positional names
$ webreel record login -p "mobile-*"
Recording: login
Done: videos/login.mp4
Recording: mobile-hero
Done: videos/mobile-hero.mp4
Recording: mobile-login
Done: videos/mobile-login.mp4CLI: new webreel list command
Lists all videos across configs with source file, URL, viewport, and step count. Supports --json for scripting and CI integration.
$ webreel list
3 video(s):
hero (webreel.config.json)
/ 1920x1080 3 step(s)
login (demos/login.webreel.json)
/login 1920x1080 5 step(s)
inline-demo (webreel.config.json [scenario #1])
/demo 1920x1080 2 step(s) $ webreel list -c web.json -c mobile.json -p "mobile-*"
2 video(s):
mobile-hero (mobile.json)
/ 393x852 3 step(s)
mobile-login (mobile.json)
/login 393x852 5 step(s) $ webreel list --json
[
{ "name": "hero", "url": "/", "source": "webreel.config.json", "steps": 3,
"viewport": { "width": 1920, "height": 1080 }, "output": "videos/hero.mp4" },
{ "name": "login", "url": "/login", "source": "demos/login.webreel.json", "steps": 5,
"viewport": { "width": 1920, "height": 1080 }, "output": "videos/login.mp4" }
]CLI: updated webreel validate
Validates multiple configs and checks for duplicate video names across them.
$ webreel validate -c web.json -c mobile.json
web.json: valid
mobile.json: valid
Cross-config: 4 video(s), no duplicatesCurrent state
This is a proof of concept meant to explore the design space. The code
works and is tested, but I'm sharing it early to align on direction
before polishing. Backward compatibility with single-config usage is
preserved, loadWebreelConfig return type is unchanged, extends and
scenarios only exist on input types.
Motivation
Two main use cases drove this:
- Large projects: dozens of demo videos organized by feature, viewport, or theme. Splitting configs across files with shared defaults keeps things maintainable.
- CI/CD: running selective subsets of recordings per pipeline stage, filtering by pattern, validating across configs before recording.
Looking for feedback on
The entire API design is open. I'd love to hear your thoughts on how you envision multi-config support for webreel - naming conventions, config structure, CLI flags, public API surface, merge semantics, anything. Happy to rework this from scratch based on your vision for the project.
Activity
8Thanks for this thoughtful contribution! The design is well considered — extends chains with circular detection, scenario merging, glob discovery, and the list command with --json are all things we'd want for scaling to larger projects. The test coverage is excellent too.
A few things to address before merging:
Bug: webreel validate -c config.json on a single config with a broken extends path (e.g. pointing to a nonexistent file) reports "valid" because it only runs schema validation. The full resolution check only kicks in when multiple configs are passed. Could you run loadWebreelConfig (or loadFullConfig) unconditionally so resolution errors are always caught?
Oversight: preview is the only command that didn't get the --project flag — was that intentional?
Design question: The --project flag filters videos by name, but webreel doesn't have a "project" concept — would --filter be clearer? Open to discussion on this.
Minor: loadFullConfig parses each config file 2-3x (once in loadWebreelConfig, then again to check for scenarios). Not a blocker, but worth a cleanup pass to parse once and thread the raw result through.
Everything else looks great. Backward compatibility is preserved, the docs updates are thorough, and the new dependencies are solid choices. Excited about this direction for multi-config support.
Thanks for this thoughtful contribution! The design is well considered — extends chains with circular detection, scenario merging, glob discovery, and the
listcommand with--jsonare all things we'd want for scaling to larger projects. The test coverage is excellent too.A few things to address before merging:
Bug:
webreel validate -c config.jsonon a single config with a brokenextendspath (e.g. pointing to a nonexistent file) reports "valid" because it only runs schema validation. The full resolution check only kicks in when multiple configs are passed. Could you runloadWebreelConfig(orloadFullConfig) unconditionally so resolution errors are always caught?Oversight:
previewis the only command that didn't get the--projectflag — was that intentional?Design question: The
--projectflag filters videos by name, but webreel doesn't have a "project" concept — would--filterbe clearer? Open to discussion on this.Minor:
loadFullConfigparses each config file 2-3x (once inloadWebreelConfig, then again to check forscenarios). Not a blocker, but worth a cleanup pass to parse once and thread the raw result through.Everything else looks great. Backward compatibility is preserved, the docs updates are thorough, and the new dependencies are solid choices. Excited about this direction for multi-config support.
Thanks for the detailed review! All feedback has been addressed in 742c3a2:
- Bug: validate now runs loadWebreelConfig unconditionally after schema validation for JSON configs, so broken extends paths are caught even with a single config
- Oversight: Added --filter to the preview command
- Design: Renamed --project to --filter (-f) across all commands (record, composite, list, preview), updated internal function names, error messages, tests, and docs
- Minor: Refactored loadFullConfig and resolveScenarios to parse each config once via an internal loadWebreelConfigFull that returns both the resolved config and the raw resolved object, eliminating the redundant loadRawConfig + resolveExtends calls
@sld0Ant is attempting to deploy a commit to the Vercel Labs Team on Vercel.
A member of the Team first needs to authorize it.