🌐 Website & docs · Showcase · Quick start · GitHub
Domotion turns real HTML/CSS into one self-contained, animated SVG — an accurate reproduction of the rendered page, with optional animation and simulated interaction built in. It embeds the exact captured glyph data and positioning, so playback never falls back to a viewer's system fonts; the output scales crisply at any size and embeds anywhere with a plain <img>, no external assets.
Beyond raw capture it ships Domotion Studio, a local visual workspace for authoring and reviewing versioned projects; a template library that turns a few flags into a polished animated SVG; terminal-session capture (a recording → an animated terminal); scroll capture (a long page replayed as one self-contained scrolling SVG); multi-frame animation with parameterized and custom transitions, overlays, and simulated interaction; scene storyboarding (sequence distinct scenes end-to-end); brand kits and social-format presets (reel / square / portrait / landscape); device-chrome framing; nested compositing (animated layers inside animated layers); one-command SVG → MP4/WebM; and fidelity review tools.
A real UI captured and brought to life — one self-contained SVG. More demos →
Animated demos for product marketing and documentation usually mean either:
- A bundle of MP4s — heavy, hard to scale, no inline embedding.
- A live iframe — slow, requires the source app to be online, breaks accessibility.
- Hand-authored SVG animations — accurate but enormously time-consuming for anything beyond a couple of frames.
Domotion captures real HTML/CSS as it renders in Chromium, then emits a single inline-embeddable SVG that replays the same pixels with CSS keyframe transitions. Author the demo as plain HTML/CSS in your real app, capture frames, and ship the result as a <img src="demo.svg"> that loads lazily and scales without artifacts.
Actively developed, with a broad shipped surface — capture, multi-frame animation (transitions, overlays, simulated interaction), the template library, terminal capture, nested compositing, and the video/image exports — exercised by an extensive visual-regression suite. The CLIs and the animate-config schema are stable in practice.
Domotion runs on macOS, Linux, and Windows, and all three are calibrated. It renders text by extracting the glyphs Chromium selected on the platform you run it on (CoreText on macOS, fontconfig on Linux, DirectWrite on Windows), then embeds those glyphs instead of asking the viewer's machine to perform font fallback. macOS is held to pixel-exact parity; Linux and Windows match Chromium's glyph selection and metrics within a documented native-hinting margin. Linux fidelity is a required CI check; Windows has first-class native validation and release checks, with its slower broad suites dispatched on demand.
Issues, fixes, and platform feedback are welcome on GitHub.
npm install domotion-svg
npx domotion capture https://example.com -o example.svgOpen example.svg in a browser. You should see a self-contained, scalable
capture of the page with no external fonts, images, or scripts.
Domotion installs Playwright's Chromium binary on first use. CI jobs can run
npx playwright install chromium ahead of time to keep capture runtime
predictable. For a zero-install trial, run
npx -p domotion-svg domotion capture https://example.com -o example.svg.
- Capture one page: use
domotion capture; see the capture guide. - Animate a product flow: use
domotion animate; follow the animation guide. - Generate a polished asset from flags: use
domotion template; browse the template guide. - Author and review a versioned project visually: use
domotion-studio; see the Studio guide.
The Quick start walks through the first capture and animation end to end.
After the first capture works, the same CLI accepts local files, stdin, element selection, custom viewports, optimization, and scrolling pages:
# Capture one element from a local file at a specific viewport.
domotion capture ./demo.html \
--width 1200 --height 600 \
--selector ".hero" \
--optimize \
-o hero.svg
# Capture HTML from stdin.
cat demo.html | domotion capture - -o demo.svg
# Capture a long page as one animated scrolling SVG (scrolls to the bottom over 8s).
domotion capture https://example.com --scroll "down:bottom/8s" -o scroll.svgNavigation waits for the page's load event, then Domotion applies its normal
font/image/paint readiness checks. Pages with a finite request chain can opt
into Playwright's stricter network-idle heuristic with --network-idle; it is
off by default because analytics, long polling, and streaming requests may
never become idle.
Same-origin <iframe> content is recursed into the capture as native SVG rather than flattened to a screenshot; opt into cross-origin frames you trust with --cross-origin-frames "<hosts>".
Text defaults to self-contained, pixel-faithful embedded fonts. For inline SVG,
--real-text adds a paintless authored-text layer for search, selection, copy,
and assistive technology. --text-mode system-font instead paints authored
<text> using the viewer's installed fonts; it can be smaller, but it is not
pixel-faithful and should be used only when those fonts are guaranteed.
For a multi-frame animated SVG, write a JSON config and run:
domotion animate ./demo.jsonThe config describes frames, timing, transitions, waits, overlays, and simulated
interaction. See domotion --help for the full grammar and the
animation guide for
examples ranging from simple transitions to continuous interactive sessions.
Transitions are not limited to fixed presets. Parameterized push, reveal,
zoom, and shine forms control direction/angle, distance, origin, radius, and
highlight styling. A strict custom recipe can safely combine incoming/outgoing
opacity, translate, scale, reveal clip, and shine channels—plus explicit reduced-
motion and loop behavior—without accepting raw CSS or script.
The fastest way to a polished result without writing any HTML. Each built-in is a parameterized generator; pass a few flags and get a self-contained animated SVG. domotion template list shows them, domotion template <name> --help shows a template's parameters.
domotion template lower-third --title "Ada Lovelace" --subtitle "First Programmer" -o banner.svg
domotion template chart --type donut --data "42,28,18,12" --labels "Search,Direct,Social,Email" -o chart.svg
domotion template kinetic-text --text "Ship it" --variant pop --by char -o title.svgBuilt-ins (14): lower-third (broadcast banner) · kinetic-text (animated typography) · chart (column / bar / line / pie / donut) · chat (message thread) · subscribe (follow pop-up) · background-loop (seamless looping background) · device-mockup (wrap a page in a phone / browser / window bezel) · and a creative-template pack of full-bleed text/number cards: title-card, quote, caption, cta, counter, stat, compare. Every template adapts to a --format social preset (reel / square / portrait / landscape) and a --brand kit (palette / type / logo). Third-party templates are npm packages named domotion-template-<name>.
Domotion Studio is a local, browser-based workspace for building and reviewing versioned Domotion projects. It provides story and scene authoring, a detailed multitrack timeline, embedded playback and review annotations, real-interaction import, and generation/review hooks while keeping project files as portable, validated JSON inside an explicitly scoped workspace.
# Open a workspace, or pass an existing Studio project JSON file.
domotion-studio --workspace ./demo-project
domotion-studio ./demo-project/product-tour.jsonStudio opens locally by default. In automation, pass --no-open and use the
printed loopback URL. Run domotion-studio --help or read the
Studio guide.
Turn a recorded terminal session into a self-contained animated SVG — real text, real color, native SVG (no raster frames). Record with asciinema, then convert:
asciinema rec demo.cast -c "npm test"
domotion term --cast demo.cast -o demo.svgdomotion composite stacks layers — a cast, a template, or a pre-rendered svg, any of which may be animated — into one SVG, each placed and on its own timeline with its animation preserved. This is how you nest one animated thing inside another, e.g. a terminal window resizing on a desktop. See domotion composite --help and examples/composite/.
The package also ships a standalone svg-to-video CLI that renders an animated SVG (a domotion animate output, or any CSS-/SMIL-animated SVG) to a video file. It steps the animation timeline frame by frame in Chromium for frame-accurate timing, then pipes the frames to ffmpeg (a required external dependency — install via brew / apt / winget).
# h264/mp4 at 30fps, contained to 1280px wide.
svg-to-video demo.svg -o demo.mp4 --width 1280
# 60fps VP9/webm with looping background music.
svg-to-video demo.svg -o demo.webm --format vp9 --fps 60 --music bed.mp3Supports target size (--width/--height, aspect-preserving), --fps, --format / --container, supersampling (--scale), background music / foreground audio / captions, and a disk-space pre-flight. See svg-to-video --help.
To turn a single SVG into an image — to look at a render, embed a thumbnail, or hand off a flat asset — the package ships an svg-to-image CLI. The output format follows the -o extension: PNG / WebP / AVIF / TIFF (keep alpha for transparent SVGs), JPEG (--quality), or a single-page vector PDF. (WebP/AVIF/TIFF are transcoded with the bundled sharp — no extra install.)
svg-to-image card.svg -o card.png # PNG at the SVG's intrinsic size
svg-to-image card.svg -o card@2x.png --scale 2 # crisp retina (2×) raster
svg-to-image demo.svg -o frame.png --at 4000 # one frame of an animated SVG, at 4s
svg-to-image poster.svg -o poster.pdf # vector PDF--at <ms> samples an animated SVG's timeline, --width/--height contain preserving aspect, --scale supersamples raster output. See svg-to-image --help.
If a capture comes out looking different from how Chromium painted the source page, the package ships an svg-review CLI to help you file a focused bug report. Capture once with --debug to get a reproduction bundle (HAR + the Chromium screenshot of the source + the SVG we produced), then open the bundle in the local review UI:
domotion capture https://example.com --debug -o example.svg
svg-review --expected example.debug/expected.png --actual example.debug/actual.svgThe browser opens a single review card showing the expected / actual / diff PNGs. Arrow keys cycle through the three at full size; drag on any image to mark a problem region and caption it. The side panel builds a GitHub-issue-ready Markdown block as you go — copy it, then file the issue at https://github.com/brianwestphal/domotion/issues/new and attach expected.png + actual.svg so a maintainer can reproduce.
For automation, pass --no-open (or set DOMOTION_NO_OPEN=1) and drive the
printed local URL headlessly; Review and Scrubber otherwise open the system
browser for interactive use.
Animation runs have the same evidence path. domotion animate demo.json --debug
writes the final actual.svg, one shared HAR, and an expected.png plus
captured-tree.json for each composed frame. Use --debug-dir <path> to choose
the bundle location.
For an animated SVG, the package also ships svg-scrubber — a local video-style bench to play / pause / scrub / mark an in-out range, export the current frame as PNG, export the range as MP4, or trim it to a new self-contained animated SVG. Add --review to file a focused issue against a moment in the timeline: it writes an importable .ticket (frame time, range, and drawn regions) the same way svg-review builds a report for a still.
When you outgrow the CLI — custom interaction loops, programmatic frame composition, custom overlays — the same primitives are available as a library:
import { captureElementTree, elementTreeToSvg, launchChromium } from "domotion-svg";
const browser = await launchChromium();
const page = await browser.newPage();
await page.setContent(`<div style="padding:20px;color:white;background:#0d1117">Hello</div>`);
const tree = await captureElementTree(page, "body", { x: 0, y: 0, width: 800, height: 200 });
const svg = elementTreeToSvg(tree, 800, 200, {
// Optional: searchable/selectable text when this SVG is embedded inline.
// This cannot expose text through <img src="…">.
realTextLayer: true,
// Optional: how text is emitted. Default "embedded-font" is self-contained
// and pixel-faithful. "system-font" instead emits authored <text> painted
// by the VIEWER's installed fonts — smaller output, but not pixel-faithful
// and only correct where the fonts are present (CLI: --text-mode system-font).
// renderTextMode: "system-font",
});
console.log(svg);
await browser.close();For animated demos, capture multiple frames and pass them to generateAnimatedSvg (see examples/).
Library callers can collect a reproduction entirely in memory with
captureElementTreeWithDebug() and assembleCaptureDebugBundle(). The caller
keeps ownership of the browser, files, and optional HAR lifecycle; see the
scripting API.
npm run build # tsc → dist/
npm test # unit tests
npm run demos:test # feature visual-regression suite
npm run demos:test:all # features + showcase + html-test-suite
npm run demos:review # local server to compare expected/actual/diff PNGs
npm run demos:examples # run the bundled example demo scriptsFEATURES.md— per-feature support checklist with links to test fixtures.docs/— requirements docs covering rendering fidelity, supported CSS features, and known caveats.llms.txt— a concise, self-contained guide for AI agents using Domotion as a tool (Claude, Cursor, etc.): the CLIs, config schema, template library, API, gotchas, and a required rendered-pixel/video review gate before an SVG is handed back. Point your agent at it.CLAUDE.md— guidance for AI assistants working on this repo's source (different audience fromllms.txt).
MIT © Brian Westphal