If you have ever generated a video loop with AI, you have seen it snap. The clip plays, reaches the end, and jumps — because the last frame is close to the first but not the same as it, and the eye catches the difference every single time.
There is a fix, it takes one extra step at generation time, and it is at 3:02. It will save you a dozen failed generations.
The rest is a full scroll-driven build: a DNA strand extracted to 192 WebP frames and tied to scroll position, a glass-morphism bento grid that converges as you scroll, and a footer that refused to stay sticky until the second attempt. The animation was made by AI, the site was built by AI, and the two were connected by AI — but not in one prompt, which is the point made at 9:03.
01Screenshot a reference frame by frame
Find a reference video of the motion you want and screenshot it at intervals rather than trying to describe the movement from memory.
You are not copying it. You are building an accurate description of a movement, and stills are far easier to describe precisely than a remembered clip.
From the library
Get the prompt for this build
The designs used in this lesson live in the library. Open one to copy the prompt behind it.
02Have ChatGPT turn the frames into a prompt
Feed the screenshots to ChatGPT and ask it to describe the animation sequence as a video prompt. Generate two candidate prompts and merge them into one, taking the strongest parts of each.
Merging beats picking. The two attempts usually get different things right.
03Isolate clean start and end frames
Pull one clean frame for the start of the motion and one for the end. Clean means no motion blur and no partially occluded subject — these two images are about to define the entire clip.
This is the setup for the loop trick in the next step, and it does not work with soft frames.
04The trick to a loop that does not drift
In Google Flow with Veo 3.1 Quality, give it a start frame, an end frame and the prompt — and make the end frame the same image as the start frame.
The model then generates a clip that travels through the motion and arrives back exactly where it began. Because the first and last frames are the same file, there is nothing to snap between; the loop is seamless by construction rather than by luck.
Generating and hoping is what produces the drift. This removes the hope.
- Start frame and end frame set to the same image
- The prompt describes the journey between them, not the endpoints
- Use the quality model — sampling amplifies compression artifacts
05Extract to WebP at maximum quality
192 frames — eight seconds at 24fps — exported as WebP at maximum quality settings.
WebP rather than JPEG or PNG for a reason: it is the only common format that gives you PNG-grade edges at roughly JPEG file sizes, and a frame sequence is the one place on a page where both matter at once. Max quality here is affordable precisely because WebP is doing the compression.
- 192 frames = 8 seconds at 24fps
- WebP at max quality, not JPEG
- Zero-padded filenames so the sequence sorts correctly
06Prompt the build section by section
In Claude Code with React and Vite, the site goes up one section at a time: navbar redesigned from a Pinterest reference, then the frame-driven hero, then a glass-morphism bento grid built with Framer Motion that converges as you scroll, then the footer from its own reference.
Each section gets its own reference image and its own prompt. As the video says at 9:03, this is never a one-prompt build — and treating it as one is how you get a site where every section is slightly wrong.
- One reference image per section
- Finish a section before starting the next
07Expect a real bug near the end
The footer would not stay sticky. The first fix attempt failed outright; the second one worked.
Worth including because it is the honest shape of these builds. Position and stacking bugs are the most common failure in scroll-driven layouts, they rarely resolve on the first try, and one failed attempt is not a reason to start over.
What you end up with
A scroll-driven site whose hero animation loops seamlessly because it was generated to, rather than trimmed until it nearly did.
The loop trick is the piece to remember. Setting the end frame equal to the start frame costs nothing at generation time and removes an entire class of problem you would otherwise be fighting in the edit.


