Democraft

Steps

The fifteen step kinds that compose a scene.

A step is the atomic unit of a scene. Democraft has fifteen step kinds, grouped into five families: browser actions, assertions, camera moves, timeline control, and overlays.

Browser actions

Steps that drive the page and capture a screenshot.

MethodKindDescription
scene.goto(path)browser.gotoNavigate to a path relative to source.baseUrl.
scene.click(target)browser.clickClick a target.
scene.fill(target, value)browser.fillFill an input with text.
scene.select(target, value)browser.selectChoose an option from a <select>.

Each browser action captures a screenshot after the action settles. That screenshot becomes the visual frame for the step's duration in the timeline.

Assertions

Steps that verify state without advancing the visual.

MethodKindDescription
scene.expectVisible(target)assert.visibleAssert a target is present and visible.
scene.expectText(target, text)assert.textAssert a target contains text.
scene.expectUrl(path)assert.urlAssert the current URL path.

Assertions fail the capture if unmet, producing a diagnostic (DC0xx). They do not produce their own screenshot — they validate the state produced by preceding browser actions.

Camera moves

Steps that control what the rendered camera shows.

MethodKindDescription
scene.establish(target?)camera.establishPull back to show the whole viewport (or a target's context).
scene.focus(target, opts?)camera.focusZoom/pan to a target. opts.padding adds breathing room.

focus accepts { padding }:

await scene.focus("project-name-input", { padding: 24 });

Within a scene, an establish followed by a focus produces a smooth zoom-to-target. See the timeline page for how these resolve into camera tracks.

Timeline control

Steps that govern pacing and transitions.

MethodKindDescription
scene.hold(duration)timeline.holdHold the current state for a duration string.
scene.transition(opts?)timeline.transitionCut or crossfade into the next step.

hold accepts duration strings like "5000ms", "1s", "2s":

await scene.hold("5000ms");
await scene.hold("1s");

transition accepts { type: "cut" | "crossfade", duration }:

await scene.transition({ type: "crossfade", duration: "500ms" });

Overlays

Steps that add text or annotation layers on top of the captured frames.

MethodKindDescription
scene.caption(text, opts?)overlay.captionFull-width or centered caption text.
scene.callout(target, opts)overlay.calloutAnnotated pointer at a target.
scene.visual(id, props, opts?)overlay.visualA custom React visual declared in demo.ts.

callout requires { title } and accepts { description, renderer }:

await scene.callout("project-card", {
  title: "Your project is ready",
  description: "The browser journey produced this card.",
  renderer: "remocn.glass-callout",
});

caption and callout accept a renderer option — a named visual component. The built-in renderers are motion.caption (default), remocn.kinetic-title, motion.callout (default), and remocn.glass-callout. Remocn is the primary component library; see Components and remocn for the full catalog and how to add your own.

visual accepts a visual ID, JSON-serializable props, and an optional { duration }. It renders a component declared in the demo's visuals map. See Components and remocn for a complete example.

Cue markers

MethodKindDescription
scene.cue(name)cueA named bookmark in the timeline.

Cues do not render visually. They are reference points that the Studio and future programmatic consumers can use to jump to or annotate specific moments (e.g. "scene highlight at the cue named result").

Step options

Every step accepts an optional { id }:

PropTypeDefault
name
-
type
-

Explicit step IDs are optional but recommended — they make diagnostics, diffs, and Studio references stable. Without them, Democraft generates IDs from the step's position, which shift when you reorder steps.

Adding or removing a step is a structural change — it changes the IR content hash and triggers a re-capture. Editing a caption's text or a hold's duration is a content change — only a re-resolve is needed. See capture-once.

On This Page

On this page