Domotion

Capture a single frame

URLs, local HTML, your own running app, third-party sites.

Single-frame capture is the most common use of Domotion: take a piece of rendered HTML and turn it into a portable, self-contained SVG. This page walks through the four scenarios you'll actually run into.

Scenario 1: A site you don't control

You want to capture a third-party page — a docs site, a competitor's landing page, your client's existing site before a rebuild. You only have the URL.

domotion capture https://example.com -o example.svg

Tighten the viewport, target a specific section, optimize:

domotion capture https://example.com \
  --width 1280 --height 720 \
  --selector ".hero" \
  --optimize \
  -o hero.svg

For pages that fetch async content, wait for a "ready" element to appear:

domotion capture https://example.com/dashboard \
  --wait-for ".chart-loaded" \
  -o dashboard.svg

Scenario 2: Your real product UI (running locally)

The most accurate marketing demo is your real product. Run your dev server, then capture the page just like a user would see it:

domotion capture http://localhost:3000/pricing \
  --width 1280 --height 720 \
  --wait-for ".price[data-loaded='true']" \
  --optimize \
  -o pricing.svg

For authenticated pages, you have a few options:

  • Add a dev-only login route that sets a session cookie on GET. Then capture with the URL parameter or by visiting that route first via the JS API.
  • Use a magic-link / dev-token flow in the URL itself — the CLI will pass it through.
  • Drop down to DemoRecorder from the JS API, which has explicit dev-login support (see DemoRecorder).

Scenario 3: HTML in your repo

Best when the demo content should ship with the rest of your repo and shouldn't depend on a server. Author plain HTML, capture, commit the SVG.

demos/hero.html:

<!doctype html>
<html><body style="margin:0;font-family:-apple-system,sans-serif;background:#0d1117;color:#e6edf3;">
  <div style="padding:32px;">
    <h1 style="font-size:32px;margin:0;">Hello, Domotion</h1>
    <p style="color:#8b949e;">Captured live from Chromium.</p>
  </div>
</body></html>
domotion capture demos/hero.html --width 800 --height 200 --optimize -o demos/hero.svg

Wire it into a package.json script so the SVG is regenerated whenever the source changes:

{
  "scripts": {
    "demos": "domotion capture demos/hero.html --width 800 --height 200 --optimize -o demos/hero.svg"
  }
}

Scenario 4: HTML produced by a build step

If your demo HTML is generated (e.g. from React via SSR, from a templating engine, or from a script), pipe stdout straight into the CLI:

node build-demo.js | domotion capture - --width 1200 --height 600 --optimize -o demo.svg

This is also handy for parametric demos — generate one HTML per variant, loop the capture command:

for color in red blue green; do
  node build-card.js --color="$color" | domotion capture - --width 400 --height 200 -o "card-$color.svg"
done

Common readiness waits

What you're waiting forHow
HTML loaded(default) Domotion uses networkidle on URLs.
Web fonts loaded(default) Domotion waits for document.fonts.ready. Disable with --no-fonts-ready.
Specific element appeared--wait-for ".ready"
CSS transitions settled--wait 500
JS app idle--wait-for "[data-loaded='true']" on a marker element your app sets.

Capturing just one component

Use --selector to capture a single element. The SVG is the size of the element's bounding box.

domotion capture http://localhost:3000 \
  --width 1280 --height 720 \
  --selector ".product-card" \
  --optimize \
  -o card.svg

Or use --clip x,y,w,h to capture an arbitrary rectangle of the viewport — useful when no clean selector wraps the region you want.

Pause running animations

If your page has running CSS animations, captures will hit them at random points. The CLI doesn't yet have a flag for this; either add a query-param override to your dev page that pauses animations, or capture via the JS API and inject this stylesheet:

await page.addStyleTag({
  content: `*, *::before, *::after {
    animation-play-state: paused !important;
    transition: none !important;
  }`,
});

See also