I record full product demos with no human touching the keyboard — a real Chrome instance drives the app end to end, clicks through the flow, and a recorder captures every frame. The interesting part turned out not to be the clicking. It was deciding when the page was actually ready for the next step, and realizing the thing I'd built was a state machine wearing a recorder's clothes.
Here's what I learned building it for Kynth, where the demos have to look hand-driven even though nobody's there.
Why do fixed timeouts break automated demos?
Fixed timeouts break because they encode a guess about the network and the machine, and both change under you. The classic version is await page.waitForTimeout(2000) after a navigation. On my laptop with a warm cache, 2000ms is 1500ms of dead air on camera. On a cold CI runner rendering the same page, 2000ms is 400ms short and I capture a spinner mid-flight — a demo that pauses awkwardly, then jump-cuts into a half-loaded dashboard.
You can't win this by tuning the number. A bigger timeout wastes screen time on every fast run; a smaller one flakes on every slow one. The number is wrong in both directions at once because it's answering the wrong question. I don't care that 2 seconds passed. I care that the page stopped changing.






