At a glance
CreativeDesignTools hands Claude Fable 5 one plain English brief and, writing no code by hand, builds a cinematic landing page for a made up bath and body brand called Wallow, live at wallow-bath-body-63.aura.build. The background is one continuous 36 second film that reacts to your scroll: scroll down and it plays forward, scroll up and it runs in reverse, and it never jumps between sections. The trick is that it is not a video at all. It is a numbered sequence of still frames drawn onto a canvas and mapped to scroll position, so it holds around 60 frames a second, never stalls, and does the exact same thing forward and backward. The whole thing ships as one self contained lightweight HTML file, and the host directs Claude through every step: writing the script, generating the clips in Google Flow, stitching them seamlessly, cutting them to frames, building the scroll engine, adding the effects, and verifying the result. This page rebuilds the entire video in order and then turns it into a reproduction spec you can point Claude Code at to build the same kind of site.
The big idea: frames, not video
The instinct, when you want a moving background that responds to scroll, is to drop in a video file and scrub it back and forth. The host shows exactly why that fails and why a numbered frame sequence wins.
A video is a compressed stream. To show any single moment, the browser has to seek to that spot inside the file and decode it. Seeking mid file only works reliably when the server it came from is configured to allow byte range jumps. Off a plain file or a simple host, it is not, so the video locks onto one frame and refuses to move. The host puts the two side by side on screen: the video version freezes on a single frame and will not budge, while the frame sequence glides.
A frame sequence has nothing to seek and nothing to unpack. Every picture is already loaded into memory as its own image, so moving to any moment is just drawing a different one. That buys four things a video background cannot give you: it works with no internet at all, it works on phones, it moves identically forward and backward, and the moment you stop scrolling it stops doing any work whatsoever. A playing video can never go fully idle. There is also the money angle: a real video background is a big file that eats bandwidth every visit, which on a hosted site becomes a surprise bill.
| What matters | Video background, scrubbed by scroll | Scroll scrubbed frame sequence |
|---|---|---|
| Seeking to a moment | must jump inside the file, needs byte range support on the server | nothing to seek, the frame is already an image in memory |
| Scrubbing backward | often freezes on one frame off a plain host | identical to forward, never stalls |
| Bandwidth and hosting cost | one big file streamed every visit, a surprise bill | a set of small images, easy to cache |
| Works offline and on phones | flaky | yes, once the frames are loaded |
| Cost while idle | a playing video keeps working | stops drawing the instant you stop scrolling |
| Smoothness | tied to decode and seek | around 60fps, a redraw only when the frame changes |
The three layers
Everything on the page stacks into three layers, and the wow factor comes from planning all three together rather than as separate parts.
The first layer is the film: six real clips, each 6 seconds long, for 36 seconds total. These are the pieces you generate first. The second layer is the scroll engine: it takes the finished film, extracts its frames, and draws them onto a canvas that is driven by how far down the page you have scrolled. The third layer is the web elements: the sections, the copy, the marquee, the product cards, the effects and sticky animations, everything a visitor reads and clicks. Combine the moving background with the web elements and you get the experience.
The host stresses that the layers are designed as a whole. On the finished page the subject sits on the right with the title on top and text on the left, then the next section flips it, text on the right and subject on the other side. At the closing call to action the button sits dead center and the background is centered to match, so everything feels in sync. You think about the background, the images, the clips, and the elements together, not separately. When a background runs through the entire page like this one does, you plan the film and the elements as one. When you only want a moving background in some sections, you can work it section by section instead.
Building it, in the video's order
It is not a video, it is a website built with Fable 5
The host opens on the finished Wallow site and scrolls it: the background is one continuous film, forward on the way down, reverse on the way up, smooth transitions and no jumping between sections. It is a 36 second film, but not a video file, and it is tied to the scroll. The promise for the video is the full workflow, so you can build your own template, customize it, and bring it to your own project, plus the way to think about and direct the experience. He points out the finishing move up front: at the end there is a big blast of color and the call to action button sits about in the middle, an example of planning the film and the elements to work together.
Composing the wow factor
The wow factor is not one effect, it is the background and the elements moving as one. Subject right, title on top, text left, then the next section mirrors it. At the call to action the button is centered and the background is centered with it, so the whole thing reads as in sync. The lesson: treat your background, images, clips, and elements as a whole. Because Wallow uses a background that spans the entire landing page, the host plans the film and the web elements together. If your product only needs a moving background in some sections, you plan it section by section instead.
What Fable 5 is, and when to use it
The site was built with Fable 5, which the host frames as recently returned after being pulled back over security concerns, and now genuinely impressive. The catch is price: it runs at roughly two times the cost of Opus, and Sonnet 5 just launched at far lower cost. So he uses Fable 5 deliberately, as a planner. Let Fable 5 think, research, and plan the whole thing out, the way the old plan mode and act mode split used to work, then hand the plan to Sonnet or Opus to implement, because those are still excellent models and Opus is great at execution. A useful aside: if a request trips one of the classifiers, Opus automatically downgrades to Opus 4.8 anyway.
The important part: the technique is not bound to any one model version. It is not Fable 5 only. Any capable model works. Planning with Fable 5 first just makes the rest easier. And if you already know the technique cold, you can run the whole thing on Opus, because you already know the outcome you want.
Start with a script, not code
Every cinematic page starts the same way, and it is not about the code. You start with a script. Ask the model to act like an advertisement agency. You are building an experience, so you think through all the interactions before writing any HTML. Think of the model as a director writing a script and drawing a storyboard for an ad. An ad agency does not cut the commercial first, it writes the script, sketches the storyboard, and plans the transitions. You do the same: nail the experience first, polish everything, then transition into building.
The script assigns one color per section. Wallow runs orange, then pink, then lime, then purple, and finally a call to action that carries all the colors at once and blends everything together. That color plan lines up exactly with the sections on the finished page. This scripting stage is the planning phase, and it matters most because video generation is expensive, so you want the plan locked before you spend a credit.
Google Flow and what video really costs
The host generates the film in Google Flow. The cost math is the whole reason to plan first.
A single 6 second video on the cheapest model, called Omni Flash, costs 10 credits. Ask for two iterations per step and it doubles to 20. The high quality model is drastically pricier: about 100 credits for one output, 200 for two. On the plans, the Pro tier gives around 1,000 credits a month, roughly 10 best model videos, and the cheapest plan gives 200 credits, only about two videos a month. For real production you want a Google AI Ultra plan, which runs into the tens of thousands of credits a month (the host cites tiers around 10,000 and about 20,000), lands near 140 Canadian on a 3 month promotion, and settles around 27 Canadian, roughly 20 US dollars, after the promo. Ultra is what unlocks up to 4K resolution and watermark removal, which is why it matters for production.
The Wallow build used six clips, which is already about 600 credits before you count the reality that AI output is not perfect. Most first shots are not good, so you iterate, and every image or clip you regenerate costs more. That is why it is cheaper to iterate on text, the script and the prompts, than to keep testing live in the generator. One relief: images are free. On Flow the best image model (Nano Banana Pro) costs zero credits, up to some monthly cap you rarely hit, which is central to the next step. You can swap in ChatGPT images, Midjourney for images and video, or Grok for images and video, but Flow's free images plus cheap Omni Flash clips make it ideal for iterating on templates.
The director prompt: real product, one color per section
To get what you want out of Flow you have to prompt it, and the first prompt writes the director script for the experience. Ask the model to act as an art director, and tell it explicitly: before you write any HTML, write a director script, and generate no code until it is approved. You read the output, approve it, and tweak the experience until it fits.
Two rules make the script production ready. First, use a real product and real copy, not placeholders, so that from the script onward you have a genuine visual reference and the template feels real. Second, for every section give the model a row of five things: one color, one job, the film and camera angle behind it, the real final onscreen copy, and one layer effect. The background combined with your HTML is what creates the unique feel of each section. This scripting stage is where you iterate the most, because once you move to video generation it gets expensive fast. The host notes all the prompts are in the video description so you can copy them, and repeats that production quality needs the Google AI Ultra plan for 4K and no watermark.
Reference images for consistency
The other rule that makes it look real is consistency. Wallow has one hero product, a bath bomb, and it cannot morph into a different object from clip to clip or that would look broken. Same product, same logo, same features in every clip. The way to guarantee that: create the product image first, then use it as the reference for the next image and the next video, so the product, brand, and logo are always in the generator's context. Once you have the hero image, ask for more images of it from different angles, so you have a set of consistent references ready when you start generating video. All of this still serves the script: a coherent product plus a planned experience is what a visitor remembers, and memory is what converts. Ads are impactful because they are built on emotion and rhythm, and that is what you want your page to carry too.
Make the first image free, and the two checks
Now it builds live. The first thing you make is a still image, not a video, for a simple reason: in Flow, images are free and videos cost credits. Make a free picture first, judge it, and only turn it into a video once you like it.
Set it up by clicking the small settings button on the prompt box. Choose Image as the type, Nano Banana Pro as the model, widescreen 16:9, one image per generation. The bottom of the panel literally says the generation will yield zero credits. Then paste the exact prompt that made the real film: an underwater shot of a white bath sphere releasing an orange cloud of dye, with two very specific demands, plenty of empty space around the sphere and a completely calm left side with no dye.
When the image comes back, run two checks before using it, and reprompt for free if it fails either. First, check the margins all the way around the frame, because Flow stamps a small watermark near a corner of every video it makes, and the plan is to crop the edges off later to remove it. So nothing you need to keep can touch the edge, or it gets cropped out. Second, check that the left third stays clean and calm, because that is where the brand name and the hero elements will sit once this becomes a website. If either check fails, paste the same prompt and run it again at no cost.
Turn the image into a video, in Frames mode
Once you approve an image, turn it into a video. Click the same settings button, choose Video, and pick the mode called Frames. Frames mode lets you hand Flow a starting image and optionally an ending image (not needed here), and it animates out from your first frame. That mode is what the whole method is built on. Choose Omni Flash, the cheapest video model, which is all this technique needs, then 6 seconds, widescreen, and a single video output. Check the price line before sending, because a stray earlier setting might be set to two or four outputs and quietly burn credits. Verify the number makes sense, then send.
Next, set the starting image. Click the slot labeled Start and a picker opens with the project's images. Your approved one sits at the top because it is the newest. Choose it, and now the video knows exactly what its first frame must be. Then add the motion prompt, which only describes what happens inside the already approved scene: the dye keeps blooming, the sphere stays small and high, the left side stays calm, a gentle opening shot. Send it, and that costs the 10 credits for the generation. A couple of minutes later the dye blooming clip renders. Open it, click the download icon at the top right, and it lands in your working folder as clip one.
The seam trick: chaining clips frame perfect
Here is the most important move in the method: making clip two continue perfectly from clip one with no visible jump at the cut. The problem is that an AI video never ends exactly where you expect. The fix is to extract the last frame of clip one and use it as the starting frame of clip two.
The host does it through Claude Code in a terminal open in the same folder as the clip, with one sentence: take the exact final frame of clip one and give it to me as an image so I can upload it as the start pin of clip two in Flow. Claude finds the clip, pulls the true final frame, and even double checks that it is literally frame 144 of 144, the actual last frame, not merely near the end. You can also do it by hand with an ffmpeg command by seeking a tenth of a second before the end and saving one frame, but here the AI does it.
Back in Flow, that extracted frame is now the newest file at the top of the image picker. Pin it into the Start slot of clip two. That is the entire trick: clip one ends on this exact frame, clip two now starts on this exact frame, so the cut lands on two identical images and nothing can jump. The prompt for clip two is the handoff: the orange dye slowly clears and drifts away, the sphere sinks gently toward the lower left, and a new pink magenta cloud starts blooming. Send it, another 10 credits.
Then prove the seam is real instead of claiming it. Back in the terminal: take the very first frame of clip two and put it side by side with clip one's last frame in a single image. Claude grabs frame one of clip two, stacks the two pictures next to each other, and you see clip one's ending frame on the left and clip two's opening frame on the right. They are identical, so the cut will never jump. Repeat this to stitch all six clips together, and you can chain as many clips as a project needs.
Join and upscale the film
With the clips chained, join them into one continuous film in order with no fade or blend between them. You can ask for no fade precisely because of the seam work: the end of one clip and the start of the next are the same picture, so there is nothing to smooth over, and a fade would only make it look worse. In the same request, make the film bigger and a little sharper so it fills a 1600 by 900 frame. The cheap video model outputs 720p, which is fairly low resolution, and Flow has no enlarge button unless you are on an Ultra plan, so Claude upscales and sharpens it in one command.
Frames, not video: the scroll engine
Now turn the film into something people scroll through, without shipping a video file. The scroll engine takes no video at all. It only needs numbered still pictures, like a flip book. So cut the film into separate frames, again through Claude, and phrase the request carefully to dodge one error.
The tool that cuts frames is ffmpeg, a free program for working with video. Ask for the frames the obvious way and it does the wrong thing: it hands you one big file instead of hundreds of separate pictures, and the scroll engine cannot use that. So spell it out in the request, write separate numbered pictures, one per file, not a single combined file. That one instruction is the whole fix. Out come frame one, frame two, and on up, one picture per file. On the real template these are saved as webp, a lighter image format. Plain numbered pictures work the same way.
The engine itself is only about 30 lines, and you describe it to Claude rather than writing it by hand. It loads every frame up front. As you scroll it works out how far down the page you are, from zero at the top to one at the bottom, and draws the matching frame onto the canvas, which is just a blank drawing surface stretched across the background. Two touches make it feel premium. First it eases: instead of snapping to the exact frame it drifts toward it, so the film feels smooth and slightly weighted. Second it saves work: the moment you stop scrolling it settles on a frame and stops drawing, so the page goes completely quiet, and it only ever redraws when the frame actually changes. Smooth when you move, nothing when you do not.
The wow layer: headlines, marquee, card tilt
With the background done, add the components that combine with it for the wow effect. They follow one rule: only ever move two things, where something sits and how see through it is (position and opacity). Never move anything that forces the browser to recompute the whole page layout, because that is what makes a page lag. You ask for each effect in plain words to Claude. The three worth the most on the finished page:
- The letter by letter headline. Each word is a little box that hides anything poking outside it, and each letter sits inside that box. As the section scrolls into view, each letter slides up from below the edge one just after another, so the line gets dealt out like cards instead of appearing all at once. It shows up three times: on the big Wallow, on "on god", and on the closing "a brighter bath".
- The double marquee. Behind the product range, two rows of giant words slide across in opposite directions. One row is filled solid, the other is just an outline, and they move at slightly different speeds so they never quite line up, which keeps them feeling alive, and they fade out at the edges.
- The product card tilt. Move the cursor over a card and it leans toward you while a soft bend of light slides across it. It is a small tilt that follows the pointer, never touches the page layout, and makes the card feel like a real object you could pick up.
All of it is customizable, and the host's reminder is that synchronizing the elements with the background is what makes it feel premium and expensive. Mix and match layouts, components, and effects until it feels unique.
Verify it with one command
Optionally, run a check. The check is a small program that opens your finished page in an invisible browser, one a script controls instead of a person, and loads the page exactly like a real visitor would, then tests it. The free tool underneath is Puppeteer, but you never touch it directly. You describe the checks you want and Claude writes and runs the script, or you just ask Claude to verify the features directly.
It tests eight things in order: nothing on the page crashed; there is no error in the console log; everything the page needed actually loaded; the moving background is really drawing and not frozen; the page is not blank (proven by screenshotting it and confirming the picture is not one flat color); it stays smooth while scrolling (measured as redraws per second, which must stay above 30); it still works shrunk to a phone screen; and the reduced motion version, for people who turn animations off, does not break. Build your own list of whatever matters to you, tell Claude, and it runs them. On the finished page it passes eight of eight, holding around 34 frames a second.
Wrap up
That is the whole build from start to finish: script the experience, generate a free reference image, animate it in Frames mode, chain the clips frame perfect, join and upscale, cut to numbered frames, wire the roughly 30 line scroll engine, layer on transform and opacity effects, and verify with a headless check. The finished result is a single self contained HTML file you can host and sell on Aura.
The reproduction spec: point Claude Code at this to rebuild it
This section is the copy and paste build guide. Point Claude Code at this page and follow it in order to reproduce a scroll scrubbed film site. Plan with Fable 5 if you want, implement with Sonnet 5 or Opus.
Step 1: the director brief (no code until approved)
Give the model a plain English brief in this shape. The rules are: a real brand and real product, real copy not placeholders, a script and storyboard before any HTML, one color and one job per section, and no code until you approve the script.
Act as an art director for a cinematic scroll website.
Brand: Wallow, a bath and body brand. Hero product: a single white bath sphere.
Before writing ANY HTML, write a director script. Generate no code until I approve it.
Rules:
- Real product and real on-screen copy only, no placeholders.
- The background is one continuous 36s film across the whole page.
- Break the film into 6 shots of 6 seconds. For EACH section give me a row of five:
1) one color 2) one job 3) the film shot + camera angle
4) the real final on-screen copy 5) one layer effect
- Color journey: orange -> pink -> lime -> purple -> indigo -> a CTA that carries all colors.
- Keep the hero product identical in every shot (same object, same logo).
Output the script as a table I can approve and tweak. Then stop and wait.
Iterate on this text until the experience is right. Text is cheap; video is not.
Step 2: generate the film in Google Flow
- Free reference image first. In Google Flow, settings button, Image type, model Nano Banana Pro, 16:9 widescreen, 1 image. The panel confirms 0 credits. Prompt the first shot, for example: an underwater shot of a white bath sphere releasing an orange cloud of dye, with plenty of empty space around the sphere and a completely calm left third with no dye. Two checks before you accept it: keep everything you need away from the frame edges (Flow watermarks a corner and you will crop the edges), and keep the left third clean (the brand name and hero text go there). Reprompt for free until both pass.
- Reference set for consistency. Ask for the same product from a few angles so the object, brand, and logo stay identical across every clip.
- Animate in Frames mode. Settings button, Video, mode Frames, model Omni Flash, 6s, widescreen, 1 output. Pin the approved image into the Start slot. Confirm the credit line before sending. Add a motion prompt that only describes movement inside the approved scene, for example: the dye keeps blooming, the sphere stays small and high, the left side stays calm, a gentle opening shot. Cost is about 10 credits per 6s clip.
- Chain each clip from the previous clip's last frame (Step 3 below). Repeat for all six shots, one color per shot.
Step 3: chain the clips frame perfect (the seam)
For each new clip, pin the previous clip's exact final frame as its Start image, so the cut lands on two identical frames. Extract that frame with ffmpeg (or ask Claude to):
# grab the exact final frame of a clip as a still (0.1s before the end)
ffmpeg -sseof -0.1 -i clip1.mp4 -frames:v 1 -q:v 2 clip1_last.png
# grab the first frame of the next clip and prove the seam is identical
ffmpeg -i clip2.mp4 -frames:v 1 -q:v 2 clip2_first.png
ffmpeg -i clip1_last.png -i clip2_first.png -filter_complex hstack seam_check.png
-sseof -0.1 seeks to a tenth of a second before the end. Upload clip1_last.png into Flow's Start slot for clip 2. The two halves of seam_check.png must be the same picture.
Step 4: join and upscale the film
Join the clips in order with no fade (the seams are already identical, so a crossfade would only smear them), then upscale and lightly sharpen to 1600 by 900:
# concat the six clips with no transition (they share codec/params)
printf "file 'clip1.mp4'\nfile 'clip2.mp4'\nfile 'clip3.mp4'\nfile 'clip4.mp4'\nfile 'clip5.mp4'\nfile 'clip6.mp4'\n" > list.txt
ffmpeg -f concat -safe 0 -i list.txt -c copy film_joined.mp4
# upscale 720p -> 1600x900 and sharpen a touch
ffmpeg -i film_joined.mp4 -vf "scale=1600:900:flags=lanczos,unsharp=5:5:0.6" -c:v libx264 -crf 18 -pix_fmt yuv420p film_1600.mp4
Step 5: cut the film to a numbered frame sequence (and the trap)
This is the ffmpeg gotcha that costs everyone twenty minutes. WebP, GIF, and APNG are animation capable container formats, so if you point ffmpeg at a single .webp output with no numbered pattern, it packs the whole film into one animated file, which the scroll engine cannot use. The fix is the %04d counter in the output name, which switches ffmpeg to the image sequence writer and produces one still per file:
mkdir -p frames
# CORRECT: %04d writes frame_0001.webp, frame_0002.webp, ... one still per file
ffmpeg -i film_1600.mp4 -vsync 0 -q:v 80 "frames/frame_%04d.webp"
# WRONG: no counter -> one animated webp, useless to the scroll engine
# ffmpeg -i film_1600.mp4 frames/film.webp
Count the frames so the engine knows the total: ls frames | wc -l.
Step 6: the scroll engine (about 30 lines, drop in)
A full viewport <canvas> and this vanilla JS. It preloads every numbered frame, maps scroll progress to a frame index, eases the current frame toward the target, draws it cover fit, and stops the loop when idle. No dependencies.
<canvas id="film" style="position:fixed;inset:0;width:100vw;height:100vh;z-index:-1"></canvas>
// Scroll scrubbed film: numbered frames drawn to a full viewport canvas.
const TOTAL = 216; // frames you cut in Step 5
const src = i => `frames/frame_${String(i + 1).padStart(4, '0')}.webp`;
const canvas = document.getElementById('film');
const ctx = canvas.getContext('2d');
const frames = [];
let ready = 0, target = 0, current = 0, running = false;
// 1. Preload every frame up front so scrubbing never waits on the network.
for (let i = 0; i < TOTAL; i++) {
const img = new Image();
img.onload = () => { if (++ready === 1) size(); }; // first frame in, paint
img.src = src(i);
frames[i] = img;
}
// 2. Map scroll position (0 at top, 1 at bottom) to a target frame index.
addEventListener('scroll', () => {
const max = document.documentElement.scrollHeight - innerHeight;
const progress = max > 0 ? scrollY / max : 0;
target = Math.min(TOTAL - 1, Math.round(progress * (TOTAL - 1)));
if (!running) { running = true; requestAnimationFrame(tick); }
}, { passive: true });
addEventListener('resize', size);
// 3. Ease toward the target frame, draw it, and stop the loop when settled.
function tick() {
current += (target - current) * 0.12; // weighted drift, not a jump
draw(Math.round(current));
if (Math.abs(target - current) > 0.4) requestAnimationFrame(tick);
else { current = target; draw(target); running = false; } // settle and go quiet
}
function size() { canvas.width = innerWidth; canvas.height = innerHeight; draw(Math.round(current)); }
function draw(i) { // cover fit, centered
const img = frames[i];
if (!img || !img.complete || !img.width) return;
const s = Math.max(canvas.width / img.width, canvas.height / img.height);
const w = img.width * s, h = img.height * s;
ctx.drawImage(img, (canvas.width - w) / 2, (canvas.height - h) / 2, w, h);
}
Give the page real scroll height (tall sections stacked over the fixed canvas) so there is room to scrub through all the frames.
Step 7: the wow layer (transform and opacity only)
Every effect moves position and opacity, nothing that triggers layout.
Split letter headline reveal. Wrap each letter in a masked span, stagger it, and reveal on scroll:
<h2 class="reveal">a brighter bath</h2>
.reveal .word { display:inline-block; overflow:hidden; vertical-align:top; }
.reveal .ltr { display:inline-block; transform:translateY(110%); transition:transform .6s cubic-bezier(.2,.7,.2,1); }
.reveal.in .ltr { transform:translateY(0); }
const io = new IntersectionObserver((es, o) =>
es.forEach(e => { if (e.isIntersecting) { e.target.classList.add('in'); o.unobserve(e.target); } }),
{ threshold: 0.4 });
document.querySelectorAll('.reveal').forEach(el => {
el.innerHTML = el.textContent.trim().split(' ').map(word =>
`<span class="word">${[...word].map(c => `<span class="ltr">${c}</span>`).join('')}</span>`
).join(' ');
el.querySelectorAll('.ltr').forEach((s, i) => s.style.transitionDelay = `${i * 40}ms`); // dealt like cards
io.observe(el);
});
The double marquee. Two rows, opposite directions, different speeds, one solid and one outline (duplicate the text inside each row so the loop is seamless):
.marquee { display:flex; overflow:hidden; white-space:nowrap; -webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent); }
.marquee span { padding-right:.3em; will-change:transform; animation:slide 22s linear infinite; }
.marquee.rev span { animation-direction:reverse; animation-duration:28s; } /* opposite way, different speed */
.marquee.outline span { -webkit-text-stroke:1px currentColor; color:transparent; }
@keyframes slide { to { transform:translateX(-50%); } } /* text is duplicated, so -50% loops */
Pointer driven card tilt with a light sweep. Transform only, plus a gradient that follows the pointer:
document.querySelectorAll('.card').forEach(card => {
card.addEventListener('pointermove', e => {
const r = card.getBoundingClientRect();
const px = (e.clientX - r.left) / r.width - 0.5; // -0.5 .. 0.5
const py = (e.clientY - r.top) / r.height - 0.5;
card.style.transform = `perspective(700px) rotateX(${-py * 8}deg) rotateY(${px * 8}deg)`;
card.style.setProperty('--mx', `${(px + 0.5) * 100}%`); // drives the shine
});
card.addEventListener('pointerleave', () => { card.style.transform = ''; });
});
.card { transition:transform .2s ease; position:relative; }
.card::after { content:""; position:absolute; inset:0; opacity:0; transition:opacity .2s;
background:radial-gradient(circle at var(--mx,50%) 0%, rgba(255,255,255,.35), transparent 60%); }
.card:hover::after { opacity:1; } /* the soft bend of light */
Step 8: verify with one headless command
Ask Claude to write a Puppeteer script (or run the check directly) that opens the page in a headless browser and asserts eight things in order:
node verify.mjs ./index.html
The eight checks: (1) no uncaught crash, (2) no console errors, (3) all requested assets loaded, (4) the canvas is actually drawing, not frozen, (5) a screenshot is not one flat color (page not blank), (6) redraws per second stay above 30 while scrolling, (7) it still works at a phone viewport, (8) the prefers-reduced-motion version does not break. Target: 8 of 8, roughly 34fps. Then ship the single HTML file on Aura.
When Fable 5 vs Opus or Sonnet
Fable 5 costs about two times Opus, so use it as the planner: let it think, research, and write the director script and the build plan. Hand the plan to Sonnet 5 or Opus to implement, since both are strong at execution and Opus quietly downgrades to Opus 4.8 if a classifier trips. The technique is model agnostic. If you already know it cold, run the whole thing on Opus.
Chapters
0:00 It's Not a Video: A Website Built With Fable 5 2:10 The Three Layers 3:02 Composing the Wow Factor 4:40 What Fable 5 Is (and When to Use It) 7:01 Start With a Script, Not Code 8:43 Google Flow and What Video Really Costs 13:29 The Director Prompt: Real Product, One Color Per Section 15:49 Reference Images for Consistency 18:37 Make the First Image Free (and the Two Checks) 21:45 Turn the Image Into a Video (Frames Mode) 24:11 The Seam Trick: Chaining Clips Frame-Perfect 28:14 Join and Upscale the Film 29:34 Frames, Not Video: The Scroll Engine 33:10 The Wow Layer: Headlines, Marquee, Card Tilt 35:09 Verify It With One Command 36:45 Wrap Up
Notable quotes
"It's not a video. It's actually a 36 second film. And you can go preview this template at this link right here." (0:20)
"So everything here fits in three layers. The first one is obviously the film. Then we go into the engine which takes the actual videos and extract the frames from them and then we draw it on the canvas which will be driven by our scroll animation." (2:10)
"So we can think of Fable 5 if you want to do it in an optimal way then you can use it to plan, to think, research and plan everything out. So then you can hand it over to Sonnet or Opus because they are still really good models." (5:30)
"Any cinematic page will start the same way and it's not about the code. So we are starting with a script. We're going to ask it to kind of act like an advertisement agency." (7:01)
"It's cheaper to write text, the script, prompting AI than to come here and test." (9:40)
"So before you write any HTML you ask it to write a director script. This is very important because we don't want the AI to generate any code, no code until it is approved." (13:40)
"Now comes the most important move in this whole method. Making clip two continue perfectly from clip one with no visible jump at the cut." (24:20)
"Clip one ends on this exact frame and clip two now starts on this exact frame. The cut between them lands on two identical images. So there's nothing that's going to jump." (26:40)
"If you ask for the frames in the obvious way it does the wrong thing. It hands you one big file instead of hundreds of separate pictures. So in my request I spell it out. I tell it to write separate numbered pictures, one per file, not a single combined file. That one instruction is the whole fix." (29:50)
"The engine itself is only about 30 lines and you don't have to write them by hand either. You describe it to Claude and it's going to build it for you." (31:10)
"It follows one rule: only ever move two things, where something sits and how see-through it is. Never anything that forces the browser to work out the whole page layout again because that's what makes a page laggy." (33:20)
"So you can see that here it passes all eight of eight. So everything is good. It's holding around 34 frames a second." (36:20)
Resources mentioned
- Wallow finished example site, the live cinematic scroll page built in the video, scroll it to feel the scrubbed film background.
- Aura, where the single self contained HTML file is hosted and sold.
- Google Flow, the AI image and video generator used for the film (free Nano Banana Pro images, cheap Omni Flash 6 second clips, Frames mode).
- Google AI plans and Ultra, the credit tiers referenced, with Ultra unlocking 4K and watermark removal for production.
- Neuform, AI design and site building tool linked by the creator.
- Claude and Claude Code, the model and terminal agent that drive every build step; Fable 5 for planning, Sonnet 5 and Opus for implementation.
- ffmpeg, the free tool that extracts the seam frames, joins and upscales the film, and cuts it into numbered stills.
- Puppeteer, the headless browser library behind the eight point verify check.
- Canvas API and WebP, the drawing surface for the frames and the lightweight image format the template uses.
- Other generators the host names as alternatives: ChatGPT images, Midjourney images and video, and Grok images and video.
- Template link and Prompts document, the creator provides a template and a Google Drive of the exact prompts in the video description.
- CreativeDesignTools on YouTube, the creator's channel, hosted by Vannarot Roeung, known as VanhDes.


