Capture states behind clicks (flows)
npx demovie capture photographs every page as it loads. Many of the best moments in a product video only appear after
an action: a dialog, a filled form, a result. A flow replays those steps in the real app and captures each state on
the way.
1. Pick the moments#
Write down the states you want to show, in order. For a "create a project" story:
- the board, before anything happens;
- the "New project" dialog;
- the dialog with a name typed in;
- the new project's page.
2. Scaffold the flow#
npx demovie flow new create-project --start /app/projectsThis writes .demovie/flows/create-project.flow.yaml, starting on the page you name (after logging in, if that page
needs it).
3. Write the steps#
Each step acts on one element, found the way a person would describe it: by its role and name, its label or its text.
name: create-project
start: /app/projects
steps:
- capture: board
- click: { role: button, name: New project }
- waitFor: { role: dialog }
- capture: dialog
- fill: { label: Project name, value: Q4 Launch }
- capture: dialog-filled
- click: { role: button, name: Create project }
- waitFor: { text: Launch checklist }
- capture: createdHow to find the right target:
- Look at a capture's
elements.json. Every element is listed with its role and name:button:new-projectmeans{ role: button, name: New project }. - Prefer roles, labels and visible text over CSS selectors: they survive redesigns.
testIdworks for elements with adata-testid. For elements with neither a name nor a test id, ask your team before adding adata-demovie="…"attribute to the app.- Wait for the result of each action (
waitFor) before the nextcapture.
The full list of steps and targets is in the flows reference.
4. Run it and look#
npx demovie flow run create-projectEach state lands in .demovie/captures/flows/create-project@desktop/<state>/screen.png. Open them. If a state shows a
spinner or the wrong screen, add a waitFor before its capture.
From now on, npx demovie capture runs the flow with everything else, and your agent can use
flows/create-project@desktop/dialog like any other capture.
Good to know#
- Demo data is reloaded before every run, so a flow that creates something can run again and again.
- Destructive steps (delete, remove, cancel…) are refused unless the flow sets
allowDestructive: true. Only do that against demo data. - Logic YAML can't express?
npx demovie flow new checkout --tswrites a TypeScript flow instead.