Product & UI · Oct 14, 2026

I had Claude Code film my real app from a script. Sharing repo and skill.

I had Claude Code film my real app from a script. Sharing repo and skill. by IvanVoitovych. Watch the product & ui video, explore the shared prompt and visit…

IvanVoitovychu/IvanVoitovych
View on Reddit
Model not specified · creator-reported
0 net upvotes on Reddit, checked Oct 15, 2026
From the creator’s post · IvanVoitovych on Reddit
Most of the "Claude made my launch video" posts animate a drawn copy of the interface. I did that too, and it works. But I wanted the real product on screen, and I wanted to shoot it again after every UI change without doing anything by hand. So I had Claude Code build a small recorder. The video above is my real app, driven by a script. Nobody touched the mouse. **How it works** A video is a plain HTML page animated with CSS. A script moves every animation to the time of each frame, takes a screenshot in headless Chrome, and ffmpeg encodes the frames. No React, no Remotion, no video editor. For the real app, a scenario file clicks, types and drags as a demo user. This is from the example in the repo: await t.click({ text: 'Orders', in: 'nav a' }); t.say('It clicks, types and drags like a person', 3.4); await t.click('#new'); await t.cam('.dialog', 1.45, .8); // zoom the camera onto the dialog await t.click({ label: 'Customer' }); await…
From the creator

The prompt behind it.

Original prompt
posts animate a drawn copy of the interface. I did that too, and it works. But I wanted the real product on screen, and I wanted to shoot it again after every UI change without doing anything by hand.

So I had Claude Code build a small recorder. The video above is my real app, driven by a script. Nobody touched the mouse.

**How it works**

A video is a plain HTML page animated with CSS. A script moves every animation to the time of each frame, takes a screenshot in headless Chrome, and ffmpeg encodes the frames. No React, no Remotion, no video editor.

For the real app, a scenario file clicks, types and drags as a demo user. This is from the example in the repo:

    await t.click({ text: 'Orders', in: 'nav a' });
    t.say('It clicks, types and drags like a person', 3.4);
    await t.click('#new');
    await t.cam('.dialog', 1.45, .8);              
    // zoom the camera onto the dialog
    await t.click({ label: 'Customer' });
    await t.type('Priya Raman', .07);
    await t.select({ label: 'Plant' }, 'Fiddle-leaf fig');
    await t.drag('input[name=quantity]', .02, .3);
    await t.click({ text: 'Save order', in: 'button' });

The trick that makes the frame rate exact: the whole page runs in slow motion. CSS animations play at one tenth of the speed, the page's timers are stretched ten times, and one frame is taken every third of a second. Chrome's virtual time was the first idea and it hung.

The cursor, click rings, camera moves and captions are not in the recording. They are drawn when the video is rendered, so I can restyle them without recording again.

The music is code too. No samples, so nothing to license: a quiet piano, and one short sound for each thing that happens on screen.

**How Claude Code was used**

It wrote all of it. I directed and watched every cut. The first version, renderer and recorder, took one working day. The prompts I ended up with are in the repo, cleaned up so you can paste them.

The first result was bad. A slideshow. What made it good was not the first prompt, it was the notes after each screening:

*

Video and prompt by IvanVoitovych. Original post ↗