ForkFree

Prompts / Coding

Code-Built Animated Explainer in One File

You get a working, looping animation in a single file that you can open in any browser, plus a plan you can edit. Asking for a scene timeline first and a self-check at the end keeps the code organised and cuts down on broken output.

Struggled in our testThe reply is cut off mid-code (ends at `class="f`), so the HTML is incomplete and has no closing tags. It is missing the rest of the scenes, the JS timeline, the replay button logic, and the two closing lines on speed and colours. The timeline table is good, but the main deliverable is unfinished.

The prompt

You are a front-end developer who specialises in motion graphics written as code.

Task: Build a short animated explainer as one self-contained HTML file, using only {animation_tech} and no external images, that shows {animation_concept} to {target_audience}.

Steps:
1. Plan the animation as a timeline of 4 to 6 scenes. For each scene give a start time, a duration and one sentence on what appears and moves.
2. Write the code around a single master timeline so scenes can be reordered, and keep colours, fonts and timings as constants at the top of the file.
3. Style it to match {visual_style}, apply easing to every movement, and keep on-screen captions to eight words or fewer.
4. Make it loop cleanly, scale to any window size, and include a replay button.
5. Re-read the code for mistakes, such as undefined variables or missing closing tags, and fix them before replying.

Output: First the scene timeline as a short table, then the complete HTML in one code block, then two lines explaining how to change the speed and the colours.

Change the parts in curly braces. Use it when you need a quick explainer, product demo or landing-page visual and have no video editing tools or budget.

What happened when we ran it

We sent

You are a front-end developer who specialises in motion graphics written as code.

Task: Build a short animated explainer as one self-contained HTML file, using only plain HTML, inline SVG and CSS animations with a small amount of vanilla JavaScript and no external images, that shows how a customer's online order travels from the checkout button through payment, the warehouse and the courier to their front door, taking about 30 seconds in total to small shop owners who have never run an online store and want to understand what happens after a sale.

Steps:
1. Plan the animation as a timeline of 4 to 6 scenes. For each scene give a start time, a duration and one sentence on what appears and moves.
2. Write the code around a single master timeline so scenes can be reordered, and keep colours, fonts and timings as constants at the top of the file.
3. Style it to match a calm, friendly look with a cream background, rounded shapes, a teal and orange palette and a clean sans-serif font, apply easing to every movement, and keep on-screen captions to eight words or fewer.
4. Make it loop cleanly, scale to any window size, and include a replay button.
5. Re-read the code for mistakes, such as undefined variables or missing closing tags, and fix them before replying.

Output: First the scene timeline as a short table, then the complete HTML in one code block, then two lines explaining how to change the speed and the colours.

The model replied

## Scene timeline | # | Start | Duration | Scene | What appears and moves | |---|-------|----------|-------|------------------------| | 1 | 0.0 s | 4.5 s | Checkout | A shop page slides up, a cursor glides to **Pay now**, the button presses and an order ticket arcs out. | | 2 | 4.5 s | 6.5 s | Payment | A card travels to a secure shield, the padlock closes and a tick draws, then a coin rolls into the shop. | | 3 | 11.0 s | 7.0 s | Packing | The order slip appears, the mug lifts off the shelf into a box, the flaps close, tape and label appear, and the box slides out. | | 4 | 18.0 s | 6.5 s | Courier | A van drives in, the parcel slides in, and the van drives off past scrolling hills and trees. | | 5 | 24.5 s | 5.5 s | Delivered | A courier walks up, tosses the parcel by the door and rings the bell, then walks off as the door opens and a tick badge pops. | The scenes total 30 s, plus a 0.8 s pause before the loop restarts. ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>From checkout to front door</title> <script> /* ================================================================== 1. CONSTANTS: colours, font, easing and timings. Edit here only. ================================================================== */ const THEME = { cream: '#FFF4E0', // page background paper: '#FFFBF3', // the "stage" card white: '#FFFFFF', ink: '#1F4B50', // text and dark details teal: '#2A9D8F', tealDark: '#1D7A72', mint: '#D3EEE8', grass: '#A8D8CD', orange: '#E06F1F', orangeDark: '#C45A12', peach: '#F6B77A', // cardboard peachDark: '#E39A55', sand: '#F3E3C3', sandDark: '#E3CFA6', skin: '#F3C7A2', road: '#46636A', wall: '#FBEBD3' // warehouse wall }; const FONT = '"Nunito", ui-rounded, "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif'; const EASING = { inOut: 'cubic-bezier(.65,0,.35,1)', // default for every movement out: 'cubic-bezier(.16,1,.3,1)', // arrivals pop: 'cubic-bezier(.34,1.56,.64,1)' // gentle overshoot }; const TIMING = { speed: 1, // 1 = normal, 0.8 = slower, 1.25 = faster gap: 0.8, // pause (timeline seconds) before the loop restarts // Order here = order on screen. Each id matches an element id="scene-<id>". scenes: [ { id: 'checkout', label: 'Checkout', dur: 4.5 }, { id: 'payment', label: 'Payment', dur: 6.5 }, { id: 'warehouse', label: 'Packing', dur: 7.0 }, { id: 'courier', label: 'Courier', dur: 6.5 }, { id: 'doorstep', label: 'Delivered', dur: 5.5 } ] }; /* Push the constants into CSS custom properties */ (function applyTheme() { const root = document.documentElement; Object.keys(THEME).forEach(function (k) { root.style.setProperty('--' + k, THEME[k]); }); root.style.setProperty('--font', FONT); root.style.setProperty('--ease', EASING.inOut); root.style.setProperty('--ease-out', EASING.out); root.style.setProperty('--ease-pop', EASING.pop); root.style.setProperty('--u', (1 / TIMING.speed) + 's'); // one timeline second in real time })(); </script> <style> *{box-sizing:border-box} html,body{height:100%;margin:0;background:var(--cream);font-family:var(--font);overflow:hidden} #wrap{position:fixed;inset:0;display:flex;align-items:center;justify-content:center} #movie{width:100%;height:100%;display:block} text{font-family:var(--font)} /* Replay button */ #replay{position:fixed;top:max(12px,2vmin);right:max(12px,2vmin);z-index:5;display:inline-flex;align-items:center;gap:.5em; padding:.65em 1.2em;border:0;border-radius:999px;background:var(--ink);color:var(--cream); font:700 clamp(14px,2.2vmin,18px) var(--font);cursor:pointer;box-shadow:0 4px 14px rgba(31,75,80,.25); transition:transform .3s var(--ease-pop),background .3s var(--ease)} #replay:hover{transform:scale(1.06);background:var(--tealDark)} #replay:focus-visible{outline:3px solid var(--orange);outline-offset:3px} /* Colour helpers (values come from THEME) */ .f-ink{fill:var(--ink)}.f-teal{fill:var(--teal)}.f-tealDark{fill:var(--tealDark)}.f-mint{fill:var(--mint)} .f-orange{fill:var(--orange)}.f-orangeDark{fill:var(--orangeDark)}.f-peach{fill:var(--peach)}.f-peachDark{fill:var(--peachDark)} .f-sand{fill:var(--sand)}.f-sandDark{fill:var(--sandDark)}.f-white{fill:var(--white)}.f-paper{fill:var(--paper)} .f-cream{fill:var(--cream)}.f-skin{fill:var(--skin)}.f-grass{fill:var(--grass)}.f-road{fill:var(--road)}.f-wall{fill:var(--wall)} .s-ink{stroke:var(--ink)}.s-teal{stroke:var(--teal)}.s-tealDark{stroke:var(--tealDark)}.s-orange{stroke:var(--orange)} .s-white{stroke:var(--white)}.s-sand{stroke:var(--sand)}.s-sandDark{stroke:var(--sandDark)} /* Text styles */ .cap{font-size:42px;font-weight:700;fill:var(--ink);text-anchor:middle} .lbl{font-size:26px;font-weight:700;fill:var(--ink);text-anchor:middle} .step{font-size:20px;font-weight:700;fill:var(--ink);text-anchor:middle;opacity:.65} .prod{font-size:28px;font-weight:700;fill:var(--ink)} .price{font-size:46px;font-weight:800;fill:var(--orangeDark)} .btn{font-size:28px;font-weight:800;fill:var(--white)} .url{font-size:16px;font-weight:600;fill:var(--white)} .hdr{font-size:16px;font-weight:800;fill:var(--white);text-anchor:middle;letter-spacing:.08em} .coin{font-size:30px;font-weight:800;fill:var(--orangeDark)} .plus{font-size:40px;font-weight:800;fill:var(--tealDark);text-anchor:middle} /* Progress dots (built by JS) */ .track{stroke:var(--sandDark);stroke-width:4;stroke-linecap:round} .dot{fill:var(--sandDark);transform-box:fill-box;transform-origin:center; transition:fill .4s var(--ease),transform .5s var(--ease-pop)} .dot.done{fill:var(--teal)} .dot.active{fill:var(--orange);transform:scale(1.5)} /* ================================================================== 2. ANIMATION ENGINE A scene's animations only run while the scene has the class "play". Every animated element gets class "an" plus ONE motion class, and sets its own start (--at) and length (--for) in timeline seconds, counted from the start of its scene. ================================================================== */ .scene{visibility:hidden} .scene.play{visibility:visible;animation:sceneFade calc(var(--d) * var(--u)) var(--ease) both} @keyframes sceneFade{0%{opacity:0}6%{opacity:1}94%{opacity:1}100%{opacity:0}} /* custom properties inherit, so reset them on every animated element */ .an{transform-box:fill-box;transform-origin:center; --at:initial;--for:initial;--n:initial;--fx:initial;--fy:initial;--fs:initial;--tx:initial;--ty:initial; --rot:initial;--ps:initial;--rs:initial;--len:initial;--apex:initial;--dx:initial;--dy1:initial;--dy2:initial} .dash{stroke-dasharray:var(--len,60)} .scene.play .an{ animation-duration:calc(var(--for,1) * var(--u)); animation-delay:calc(var(--at,0) * var(--u)); animation-timing-function:var(--ease); animation-fill-mode:both; animation-iteration-count:var(--n,1)} .scene.play .out{animation-timing-function:var(--ease-out)} .scene.play .pop{animation-timing-function:var(--ease-pop)} .scene.play .appear{animation-name:appear} .scene.play .go{animation-name:go} .scene.play .press{animation-name:press} .scene.play .ripple{animation-name:ripple} .scene.play .spin{animation-name:spin} .scene.play .draw{animation-name:draw} .scene.play .close{animation-name:close} .scene.play .grow{animation-name:grow} .scene.play .toss{animation-name:toss} .scene.play .bob{animation-name:bob} .scene.play .flip{animation-name:flip} .scene.play .squash{animation-name:squash} .scene.play .show{animation-name:show} .scene.play .hide{animation-name:hide} .scene.play .shrink{animation-name:shrink} .scene.play .openDoor{animation-name:openDoor} .scene.play .mugTravel{animation-name:mugTravel} @keyframes appear{from{opacity:0;transform:translate(var(--fx,0px),var(--fy,0px)) scale(var(--fs,1))}to{opacity:1;transform:none}} @keyframes go{from{transform:translate(var(--fx,0px),var(--fy,0px))}to{transform:translate(var(--tx,0px),var(--ty,0px))}} @keyframes press{0%,100%{transform:scale(1)}45%{transform:scale(var(--ps,.92))}} @keyframes ripple{0%{opacity:0;transform:scale(.3)}15%{opacity:.75}100%{opacity:0;transform:scale(var(--rs,2.6))}} @keyframes spin{from{transform:rotate(0deg)}to{transform:rotate(var(--rot,360deg))}} @keyframes draw{from{stroke-dashoffset:var(--len,60)}to{stroke-dashoffset:0}} @keyframes close{from{transform:rotate(var(--rot,-100deg))}to{transform:rotate(0deg)}} @keyframes grow{from{transform:scaleY(0)}to{transform:scaleY(1)}} @keyframes toss{ 0%{transform:translate(0px,0px);animation-timing-function:ease-out} 50%{transform:translate(calc(var(--tx) / 2),var(--apex));animation-timing-function:ease-in} 100%{transform:translate(var(--tx),var(--ty))}} @keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-7px)}} @keyframes flip{from{transform:scaleX(1)}to{transform:scaleX(-1)}} @keyframes squash{0%,100%{transform:scale(1,1)}40%{transform:scale(1.14,.82)}} @keyframes show{from{opacity:0}to{opacity:1}} @keyframes hide{from{opacity:1}to{opacity:0}} @keyframes shrink{from{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.3)}} @keyframes openDoor{from{transform:scaleX(1)}to{transform:scaleX(.16)}} @keyframes mugTravel{ 0%{transform:translate(0px,0px)} 55%{transform:translate(var(--dx),var(--dy1))} 100%{transform:translate(var(--dx),var(--dy2))}} </style> </head> <body> <main id="wrap"> <svg id="movie" viewBox="0 0 1280 720" preserveAspectRatio="xMidYMid meet" role="img" aria-label="Animated explainer: an online order goes from checkout to payment, packing, courier and the customer's front door."> <title>How an online order reaches the customer</title> <defs> <clipPath id="stageClip"><rect x="60" y="60" width="1160" height="500" rx="40"/></clipPath> <clipPath id="doorClip"><rect x="885" y="336" width="70" height="134" rx="10"/></clipPath> <filter id="soft" x="-5%" y="-10%" width="110%" height="125%"> <feDropShadow dx="0" dy="10" stdDeviation="14" style="flood-color:var(--ink);flood-opacity:.14"/> </filter> <!-- the product --> <g id="mug"> <path d="M22,-10 h8 a10,10 0 0 1 0,20 h-8" class="s-teal" fill="none" stroke-width="7" stroke-linecap="round"/> <rect x="-22" y="-26" width="44" height="52" rx="11" class="f-teal"/> <rect x="-22" y="-6" width="44" height="9" class="f-orange"/> </g> <!-- a parcel, 84 x 64 --> <g id="parcel"> <rect x="-42" y="-32" width="84" height="64" rx="9" class="f-peach"/> <rect x="-8" y="-32" width="16" height="64" class="f-orange"/> <rect x="14" y="4" width="20" height="16" rx="3" class="f-white"/> </g> </defs> <!-- stage --> <rect x="60" y="60" width="1160" height="500" rx="40" class="f-paper" filter="url(#soft)"/> <g clip-path="url(#stageClip)"> <!-- ============ SCENE: CHECKOUT ============ --> <g id="scene-checkout" class="scene"> <g transform="translate(640,310)"> <g class="an appear out" style="--at:0;--for:.9;--fy:40px"> <rect x="-300" y="-200" width="600" height="400" rx="28" class="f-white s-sandDark" stroke-width="3"/> <path d="M-300,-152 V-172 A28,28 0 0 1 -272,-200 H272 A28,28 0 0 1 300,-172 V-152 Z" class="f-teal"/> <circle cx="-268" cy="-176" r="6" class="f-cream"/> <circle cx="-248" cy="-176" r="6" class="f-cream"/> <circle cx="-228" cy="-176" r="6" class="f-cream"/> <rect x="-170" y="-188" width="340" height="24" rx="12" class="f-white" opacity=".28"/> <text x="0" y="-171" text-anchor="middle" class="url">yourshop.com/checkout</text> <rect x="-264" y="-124" width="236" height="250" rx="22" class="f-mint"/> <circle cx="-146" cy="-10" r="82" class="f-white" opacity=".65"/> <ellipse cx="-146" cy="68" rx="58" ry="9" class="f-ink" opacity=".12"/> <use href="#mug" transform="translate(-146,-6) scale(2.4)"/> <text x="20" y="-90" class="prod">Handmade mug</text> <text x="20" y="-34" class="price">$24</text> <rect x="20" y="0" width="230" height="12" rx="6" class="f-sand"/> <rect x="20" y="26" width="170" height="12" rx="6" class="f-sand"/> <g class="an press" style="--at:2.2;--for:.4"> <rect x="20" y="80" width="240" height="64" rx="32" class="f-orange"/> <text x="140" y="122" text-anchor="middle" class="btn">Pay now</text> </g> </g> </g> <!-- click ripple on the button --> <g transform="translate(780,422)"> <circle r="40" fill="none" class="s-orange an ripple" stroke-width="6" style="--at:2.2;--for:.9;--rs:3"/> </g> <!-- order ticket pops out and arcs away --> <g transform="translate(780,422)"> <g class="an toss" style="--at:2.55;--for:1.3;--tx:260px;--ty:-172px;--apex:-210px"> <g class="an appear pop" style="--at:2.55;--for:.5;--fs:.3"> <rect x="-62" y="-44" width="124" height="88" rx="16" class="f-white s-teal" stroke-width="5"/> <rect x="-38" y="-24" width="76" height="9" rx="4.5" class="f-sand"/> <rect x="-38" y="-6" width="52" height="9" rx="4.5" class="f-sand"/> <path d="M-12,24 L-4,32 L14,14" class="s-teal dash an draw" fill="none" stroke-width="6" stroke-linecap="round" stroke-linejoin="round" style="--at:3.1;--for:.5;--len:50"/> </g> </g> </g> <!-- cursor --> <g transform="translate(790,432)"> <g class="an go" style="--at:.6;--for:1.5;--fx:240px;--fy:-170px"> <g class="an press" style="--at:2.2;--for:.35;--ps:.8;transform-origin:0% 0%"> <path d="M0,0 L0,34 L9,26 L15,40 L21,37 L15,24 L27,24 Z" class="f-ink s-white" stroke-width="2.5" stroke-linejoin="round"/> </g> </g> </g> <text class="cap an appear" x="640" y="612" style="--at:.3;--for:.7;--fy:16px">A customer taps Pay now.</text> </g> <!-- ============ SCENE: PAYMENT ============ --> <g id="scene-payment" class="scene"> <!-- dotted track --> <g class="an appear" style="--at:.2;--for:.8"> <line x1="320" y1="320" x2="950" y2="320" class="s-sandDark" stroke-width="8" stroke-linecap="round" stroke-dasharray="1 20"/> </g> <!-- secure shield --> <g transform="translate(640,310)"> <g class="an appear pop" style="--at:.2;--for:.7;--fs:.6"> <g class="an press" style="--at:2.5;--for:.5;--ps:1.1"> <path d="M0,-100 L88,-66 V8 C88,62 48,98 0,120 C-48,98 -88,62 -88,8 V-66 Z" class="f-teal s-tealDark" stroke-width="6" stroke-linejoin="round"/> <rect x="-30" y="-8" width="60" height="48" rx="10" class="f-white"/> <g class="an go" style="--at:2.6;--for:.5;--fy:-16px"> <path d="M-18,-8 V-26 a18,18 0 0 1 36,0 V-8" class="s-white" fill="none" stroke-width="9" stroke-linecap="round"/> </g> <path d="M-14,16 L-4,27 L15,5" class="s-teal dash an draw" fill="none" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" style="--at:3.3;--for:.5;--len:60"/> </g> </g> </g> <!-- the shop --> <g transform="translate(1040,325)"> <g class="an appear pop" style="--at:.35;--for:.7;--fs:.6"> <g class="an press" style="--at:5.35;--for:.5;--ps:1.07"> <rect x="-75" y="-60" width="150" height="130" rx="14" class="f-white s-teal" stroke-width="5"/> <rect x="-90" y="-104" width="180" height="46" rx="16" class="f-orange"/> <circle cx="-68" cy="-58" r="23" class="f-orange"/> <circle cx="-23" cy="-58" r="23" class="f-orangeDark"/> <circle cx="23" cy="-58" r="23" class="f-orange"/> <circle cx="68" cy="-58" r="23" class="f-orangeDark"/> <rect x="-18" y="0" width="36" height="70" rx="8" class="f-teal"/> <rect x="-62" y="-30" width="34" height="34" rx="7" class="f-mint"/> <rect x="28" y="-30" width="34" height="34" rx="7" class="f-mint"/> </g> </g> </g> <!-- customer's card flies in and is absorbed --> <g transform="translate(220,320)"> <g class="an appear" style="--at:0;--for:.7;--fx:-40px"> <g class="an go" style="--at:.9;--for:1.5;--tx:420px"> <g class="an shrink" style="--at:2.4;--for:.5"> <rect x="-70" y="-46" width="140" height="92" rx="14" class="f-orange"/> <rect x="-70" y="-24" width="140" height="18" class="f-ink"/> <rect x="-50" y="8" width="30" height="20" rx="5" class="f-sand"/> <rect x="-8" y="14" width="56" height="8" rx="4" class="f-white" opacity=".7"/> </g> </g> </g> </g> <!-- coin travels to the shop --> <g transform="translate(640,320)"> <g class="an go" style="--at:4;--for:1.4;--tx:378px"> <g class="an appear pop" style="--at:4;--for:.4;--fs:.3"> <g class="an shrink" style="--at:5.2;--for:.3"> <circle r="26" class="f-peach s-orange" stroke-width="5"/> <text y="10" text-anchor="middle" class="coin">$</text> </g> </g> </g> </g> <text x="1040" y="196" class="plus an appear" style="--at:5.4;--for:.6;--fy:18px">+$24</text> <text x="220" y="478" class="lbl an appear" style="--at:.4;--for:.6">Card</text> <text x="640" y="478" class="lbl an appear" style="--at:.4;--for:.6">Secure check</text> <text x="1040" y="478" class="lbl an appear" style="--at:.4;--for:.6">Your shop</text> <text class="cap an appear" x="640" y="612" style="--at:.3;--for:.7;--fy:16px">Payment is checked securely.</text> </g> <!-- ============ SCENE: WAREHOUSE / PACKING ============ --> <g id="scene-warehouse" class="scene"> <rect x="60" y="60" width="1160" height="460" class="f-wall"/> <rect x="60" y="520" width="1160" height="40" class="f-mint"/> <!-- shelf --> <g class="an appear" style="--at:0;--for:.8;--fx:-40px"> <rect x="106" y="108" width="14" height="414" rx="7" class="f-tealDark"/> <rect x="520" y="108" width="14" height="414" rx="7" class="f-tealDark"/> <rect x="106" y="108" width="428" height="14" rx="7" class="f-tealDark"/> <rect x="106" y="232" width="428" height="14" rx="7" class="f-tealDark"/> <rect x="106" y="352" width="428" height="14" rx="7" class="f-tealDark"/> <rect x="106" y="472" width="428" height="14" rx="7" class="f-tealDark"/> <!-- top row --> <rect x="150" y="172" width="70" height="60" rx="8" class="f-peach"/> <rect x="240" y="192" width="56" height="40" rx="8" class="f-mint"/> <rect x="330" y="162" width="60" height="70" rx="8" class="f-teal" opacity=".85"/> <rect x="410" y="182" width="80" height="50" rx="8" class="f-peachDark"/> <!-- middle row (the mug lives at x=330) --> <rect x="150" y="292" width="64" height="60" rx="8" class="f-peachDark"/> <rect x="240" y="312" width="50" height="40" rx="8" class="f-mint"/> <rect x="410" y="302" width="70" height="50" rx="8" class="f-peach"/> <!-- bottom row --> <rect x="150" y="412" width="80" height="60" rx="8" class="f-peach"/> <rect x="260" y="432" width="60" height="40" rx="8" class="f-mint"/> <rect x="350" y="402" width="70" height="70" rx="8" class="f-teal" opacity=".85"/> <rect x="440" y="422" width="50" height="50" rx="8" class="f-peachDark"/> </g> <!-- highlight ring on the picked item --> <g transform="translate(330,324)"> <circle r="44" fill="none" class="s-orange an ripple" stroke-width="6" style="--at:.9;--for:.7;--n:2;--rs:1.6"/> </g> <!-- order slip --> <g transform="translate(1040,200) rotate(4)"> <g class="an appear pop" style="--at:.2;--for:.7;--fy:-30px;--fs:.8"> <rect x="-72" y="-84" width="144" height="176" rx="14" class="f-white s-teal" stroke-width="4"/> <rect x="-72" y="-84" width="144" height="30" rx="14" class="f-teal"/> <rect x="-72" y="-70" width="144" height="16" class="f-teal"/> <text x="0" y="-63" class="hdr">ORDER</text> <use href="#mug" transform="translate(-40,-18) scale(.55)"/> <rect x="-14" y="-24" width="48" height="10" rx="5" class="f-sand"/> <path d="M40,-14 L47,-7 L60,-22" class="s-teal dash an draw" fill="none" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" style="--at:3.75;--for:.4;--len:40"/> <rect x="-52" y="22" width="104" height="9" rx="4.5" class="f-sand"/> <rect x="-52" y="40" width="80" height="9" rx="4.5" class="f-sand"/> <rect x="-52" y="58" width="92" height="9" rx="4.5" class="f-sand"/> </g> </g> <!-- packing table --> <rect x="560" y="420" width="520" height="18" rx="9" class="f-tealDark"/> <rect x="590" y="438" width="16" height="82" class="f-tealDark"/> <rect x="1034" y="438" width="16" height="82" class="f-tealDark"/> <!-- box + mug (slides away as one group at the end) --> <g transform="translate(780,420)"> <g class="an go" style="--at:5.6;--for:1;--tx:220px"> <!-- mug: shelf -> above box -> down into the box (hidden behind the box front) --> <g transform="translate(-450,-96)"> <g class="an mugTravel" style="--at:1.7;--for:2.2;--dx:450px;--dy1:-174px;--dy2:26px"> <use href="#mug"/> </g> </g> <g class="an appear pop" style="--at:.3;--for:.7;--fs:.6;--fy:20px"> <rect x="-80" y="-110" width="160" height="110" rx="10" class="f-peach"/> <!-- flaps --> <g class="an close" style="--at:3.9;--for:.7;--rot:-105deg;transform-origin:0% 100%"> <rect x="-80" y="-122" width="80" height="12" rx="4" class="f-peachDark"/> </g> <g class="an close" style="--at:3.9;--for:.7;--rot:105deg;transform-origin:100% 100%"> <rect x="0" y="-122" width="80" height="12" rx="4" class="f-peachDark"/> </g> <!-- tape --> <g class="an grow" style="--at:4.6;--for:.45;transform-origin:50% 0%"> <rect x="-14" y="-122" width="28" height="76" rx="3" class="f-orange"/> </g> <!-- label --> <g transform="translate(46,-34)"> <g class="an appear pop" style="--at:5.05;--for:.45;--fs:.3"> <rect x="-25" y="-18" width="50" height="36" rx="5" class="f-white"/> <rect x="-17" y="-10" width="3" height="14" class="f-ink"/> <rect x="-11" y="-10" width="2" height="14" class="f-ink"/> <rect x="-6" y="-10" width="4" height="14" class="f-ink"/> <rect x="1" y="-10" width="2" height="14" class="f-ink"/> <rect x="6" y="-10" width="3" height="14" class="f-ink"/> <rect x="12" y="-10" width="2" height="14" class="f-ink"/> <rect x="-17" y="8" width="34" height="4" rx="2" class="f-sandDark"/> </g> </g> </g> </g> </g> <text class="cap an appear" x="640" y="612" style="--at:.3;--for:.7;--fy:16px">You pick and pack the order.</text> </g> <!-- ============ SCENE: COURIER ============ --> <g id="scene-courier" class="scene"> <!-- far hills --> <g class="an go" style="--at:3.3;--for:2.9;--tx:-160px"> <ellipse cx="250" cy="470" rx="380" ry="110" class="f-mint"/> <ellipse cx="900" cy="485" rx="420" ry="120" class="f-mint" opacity=".75"/> <ellipse cx="1500" cy="470" rx="400" ry="115" class="f-mint"/> </g> <!-- clouds --> <g class="an go" style="--at:3.3;--for:2.9;--tx:-260px"> <g transform="translate(300,150)" opacity=".8"> <ellipse rx="64" ry="22" class="f-mint"/><circle cx="-22" cy="-16" r="26" class="f-mint"/><circle cx="20" cy="-22" r="30" class="f-mint"/> </g> <g transform="translate(820,210)" opacity=".8"> <ellipse rx="54" ry="18" class="f-mint"/><circle cx="-18" cy="-14" r="22" class="f-mint"/><circle cx="16" cy="-18" r="26" class="f-mint"/> </g> <g transform="translate(1150,135)" opacity=".8"> <ellipse rx="60" ry="20" class="f-mint"/><circle cx="-20" cy="-15" r="24" class="f-mint"/><circle cx="18" cy="-20" r="28" class="f-mint"/> </g> </g> <rect x="60" y="455" width="1160" height="105" class="f-grass"/> <!-- trees (scroll left while the van drives) --> <g class="an go" style="--at:3.3;--for:2.9;--tx:-700px"> <g transform="translate(140,472) scale(1.1)"><rect x="-7" y="-58" width="14" height="58" rx="5" class="f-peachDark"/><circle cy="-86" r="36" class="f-teal"/><circle cx="-20" cy="-68" r="24" class="f-tealDark" opacity=".55"/></g> <g transform="translate(470,472)"><rect x="-7" y="-58" width="14" height="58" rx="5" class="f-peachDark"/><circle cy="-86" r="36" class="f-teal"/><circle cx="-20" cy="-68" r="24" class="f-tealDark" opacity=".55"/></g> <g transform="translate(820,472) scale(1.2)"><rect x="-7" y="-58" width="14" height="58" rx="5" class="f-peachDark"/><circle cy="-86" r="36" class="f-teal"/><circle cx="-20" cy="-68" r="24" class="f-tealDark" opacity=".55"/></g> <g transform="translate(1100,472)"><rect x="-7" y="-58" width="14" height="58" rx="5" class="f-peachDark"/><circle cy="-86" r="36" class="f-teal"/><circle cx="-20" cy="-68" r="24" class="f-tealDark" opacity=".55"/></g> <g transform="translate(1450,472) scale(1.1)"><rect x="-7" y="-58" width="14" height="58" rx="5" class="f-peachDark"/><circle cy="-86" r="36" class="f-teal"/><circle cx="-20" cy="-68" r="24" class="f-tealDark" opacity=".55"/></g> <g transform="translate(1800,472)"><rect x="-7" y="-58" width="14" height="58" rx="5" class="f-peachDark"/><circle cy="-86" r="36" class="f-teal"/><circle cx="-20" cy="-68" r="24" class="f-tealDark" opacity=".55"/></g> </g> <!-- road --> <rect x="60" y="490" width="1160" height="56" class="f-road"/> <g class="an go" style="--at:3.3;--for:2.9;--tx:-640px"> <line x1="0" y1="518" x2="1920" y2="518" class="s-sand" stroke-width="5" stroke-dasharray="36 28"/> </g> <!-- van --> <g transform="translate(640,525)"> <g class="an go out" style="--at:0;--for:1.7;--fx:-760px"> <g class="an go" style="--at:3.3;--for:2.9;--tx:900px"> <!-- speed lines behind the van --> <g class="an appear" style="--at:3.4;--for:.6;--fx:24px"> <path d="M-128,-90 H-170 M-128,-66 H-190 M-128,-42 H-160" class="s-tealDark" fill="none" stroke-width="6" stroke-linecap="round" opacity=".35"/> </g> <!-- parcel: drops in beside the van, then slides in behind the cargo box --> <g transform="translate(-190,-62)"> <g class="an appear pop" style="--at:1.7;--for:.5;--fy:-70px"> <g class="an go" style="--at:2.4;--for:.8;--tx:175px"> <use href="#parcel"/> </g> </g> </g> <!-- van body --> <rect x="-110" y="-120" width="150" height="106" rx="14" class="f-orange"/> <path d="M36,-96 H74 Q92,-96 102,-72 L116,-42 Q120,-34 120,-24 V-14 H36 Z" class="f-orange"/> <path d="M48,-84 H72 Q83,-84 89,-68 L96,-52 H48 Z" class="f-mint"/> <circle cx="62" cy="-66" r="11" class="f-skin"/> <path d="M51,-68 a11,11 0 0 1 22,0 z" class="f-teal"/> <rect x="-110" y="-48" width="230" height="9" class="f-tealDark"/> <circle cx="-35" cy="-84" r="22" class="f-white"/> <use href="#parcel" transform="translate(-35,-84) scale(.46)"/> <rect x="100" y="-26" width="24" height="12" rx="5" class="f-ink"/> <circle cx="114" cy="-38" r="6" class="f-sand"/> <!-- wheels --> <g transform="translate(-62,-6)"> <g class="an spin out" style="--at:0;--for:1.7;--rot:1800deg"> <g class="an spin" style="--at:3.3;--for:2.9;--rot:2150deg"> <circle r="24" class="f-ink"/><circle r="10" class="f-cream"/> <line x1="0" y1="0" x2="0" y2="-17" class="s-cream" stroke="var(--cream)" stroke-width="5" stroke-linecap="round"/> </g> </g> </g> <g transform="translate(74,-6)"> <g class="an spin out" style="--at:0;--for:1.7;--rot:1800deg"> <g class="an spin" style="--at:3.3;--for:2.9;--rot:2150deg"> <circle r="24" class="f-ink"/><circle r="10" class="f-cream"/> <line x1="0" y1="0" x2="0" y2="-17" stroke="var(--cream)" stroke-width="5" stroke-linecap="round"/> </g> </g> </g> </g> </g> </g> <text class="cap an appear" x="640" y="612" style="--at:.3;--for:.7;--fy:16px">A courier collects the parcel.</text> </g> <!-- ============ SCENE: DOORSTEP ============ --> <g id="scene-doorstep" class="scene"> <ellipse cx="300" cy="480" rx="430" ry="150" class="f-mint"/> <ellipse cx="1000" cy="490" rx="380" ry="120" class="f-mint" opacity=".7"/> <rect x="60" y="470" width="1160" height="90" class="f-grass"/> <rect x="60" y="474" width="1160" height="28" class="f-sand"/> <!-- trees --> <g class="an appear" style="--at:0;--for:.8"> <g transform="translate(170,474)"><rect x="-7" y="-58" width="14" height="58" rx="5" class="f-peachDark"/><circle cy="-86" r="36" class="f-teal"/><circle cx="-20" cy="-68" r="24" class="f-tealDark" opacity=".55"/></g> <g transform="translate(340,474) scale(.8)"><rect x="-7" y="-58" width="14" height="58" rx="5" class="f-peachDark"/><circle cy="-86" r="36" class="f-teal"/><circle cx="-20" cy="-68" r="24" class="f-tealDark" opacity=".55"/></g> <g transform="translate(1160,474)"><rect x="-7" y="-58" width="14" height="58" rx="5" class="f-peachDark"/><circle cy="-86" r="36" class="f-teal"/><circle cx="-20" cy="-68" r="24" class="f-tealDark" opacity=".55"/></g> </g> <!-- house --> <g class="an appear out" style="--at:0;--for:.9;--fy:30px"> <rect x="990" y="160" width="28" height="70" class="f-orangeDark"/> <rect x="800" y="250" width="240" height="220" rx="8" class="f-white s-sandDark" stroke-width="3"/> <polygon points="770,262 920,140 1070,262" class="f-orange s-orange" stroke-width="14" stroke-linejoin="round"/> <rect x="822" y="290" width="44" height="44" rx="8" class="f-mint"/> <rect x="974" y="290" width="44" height="44" rx="8" class="f-mint"/> <rect x="885" y="336" width="70" height="134" rx="10" class="f-ink"/> <!-- customer waiting behind the door --> <g clip-path="url(#doorClip)"> <g class="an appear" style="--at:3.7;--for:.5;--fy:18px"> <path d="M893,470 V440 Q893,416 920,416 Q947,416 947,440 V470 Z" class="f-orange"/> <circle cx="920" cy="392" r="17" class="f-skin"/> <circle cx="914" cy="389" r="2" class="f-ink"/> <circle cx="926" cy="389" r="2" class="f-ink"/> <path d="M912,397 Q920,405 928,397" class="s-ink" fill="none" stroke-width="2.5" stroke-linecap="round"/> </g> </g> <!-- door --> <g class="an openDoor" style="--at:3.4;--for:.6;transform-origin:0% 50%"> <rect x="885" y="336" width="70" height="134" rx="10" class="f-teal"/> <rect x="895" y="346" width="50" height="48" rx="6" fill="none" class="s-white" stroke-width="3" opacity=".4"/> <circle cx="944" cy="408" r="5" class="f-sand"/> </g> <rect x="870" y="470" width="100" height="10" rx="5" class="f-sandDark"/> <!-- doorbell --> <circle cx="973" cy="405" r="6" class="f-orange"/> <g transform="translate(973,405)"> <circle r="14" fill="none" class="s-orange an ripple" stroke-width="3" style="--at:2.9;--for:.55;--n:2;--rs:2.4"/> </g> </g> <!-- parcel dropped by the courier --> <g transform="translate(744,430)"> <g class="an toss" style="--at:1.9;--for:.7;--tx:92px;--ty:30px;--apex:-70px"> <g class="an show" style="--at:1.9;--for:.01"> <g class="an squash" style="--at:2.6;--for:.45;transform-origin:50% 100%"> <use href="#parcel" transform="scale(.8)"/> </g> </g> </g> </g> <!-- courier: walks in, drops parcel, turns, walks away --> <g transform="translate(700,500)"> <g class="an go" style="--at:3.3;--for:1.4;--tx:-780px"> <g class="an bob" style="--at:3.3;--for:.7;--n:2"> <g class="an go out" style="--at:.3;--for:1.4;--fx:-780px"> <g class="an bob" style="--at:.3;--for:.7;--n:2"> <g class="an flip" style="--at:3;--for:.35"> <rect x="-80" y="-150" width="160" height="150" fill="none"/> <rect x="-19" y="-38" width="15" height="38" rx="6" class="f-ink"/> <rect x="4" y="-38" width="15" height="38" rx="6" class="f-ink"/> <rect x="-28" y="-102" width="56" height="72" rx="20" class="f-teal"/> <circle cx="0" cy="-124" r="22" class="f-skin"/> <path d="M-23,-128 A23,23 0 0 1 23,-128 Z" class="f-orange"/> <rect x="4" y="-132" width="28" height="8" rx="4" class="f-orange"/> <circle cx="9" cy="-120" r="2.6" class="f-ink"/> <path d="M3,-112 Q10,-107 17,-113" class="s-ink" fill="none" stroke-width="2.5" stroke-linecap="round"/> <g class="an hide" style="--at:1.9;--for:.01"> <use href="#parcel" transform="translate(44,-70) scale(.8)"/> </g> <path d="M4,-92 L28,-66" class="s-teal" fill="none" stroke-width="14" stroke-linecap="round"/> <circle cx="30" cy="-64" r="7" class="f-skin"/> </g> </g> </g> </g> </g> </g> <!-- delivered badge --> <g transform="translate(1120,200)"> <g class="an appear pop" style="--at:4.4;--for:.5;--fs:.2"> <circle r="46" class="f-teal s-white" stroke-width="6"/> <path d="M-18,2 L-6,15 L19,-14" class="s-white dash an draw" fill="none" stroke-width="9" stroke-linecap="round" stroke-linejoin="round" style="--at:4.7;--for:.5;--len:70"/> </g> </g> <text class="cap an appear" x="640" y="612" style="--at:.3;--for:.7;--fy:16px">Delivered to their front door!</text> </g> </g><!-- /stage clip --> <!-- progress dots (built from TIMING.scenes) --> <g id="dots"></g> </svg> </main> <button id="replay" type="button" aria-label="Replay animation"> <svg viewBox="0 0 24 24" width="18" height="18" aria-hidden="true"> <path d="M20 12a8 8 0 1 1-2.34-5.66" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"/> <path d="M20 4v5h-5" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/> </svg> Replay </button> <script> /* ================================================================== 3. MASTER TIMELINE One clock decides which scene is "playing". Scene start times are worked out from the order and durations in TIMING.scenes, so reordering that list reorders the film. ================================================================== */ (function () { var NS = 'http://www.w3.org/2000/svg'; var svg = document.getElementById('movie'); var dotsLayer = document.getElementById('dots'); // Build the scene list with cumulative start times var cursor = 0; var scenes = TIMING.scenes.map(function (s) { var el = document.getElementById('scene-' + s.id); if (!el) { throw new Error('Missing scene group: scene-' + s.id); } var item = { id: s.id, label: s.label, dur: s.dur, el: el, start: cursor, dot: null }; cursor += s.dur; el.style.setProperty('--d', s.dur); return item; }); var total = cursor + TIMING.gap; // Progress dots function make(tag, attrs) { var e = document.createElementNS(NS, tag); Object.keys(attrs).forEach(function (k) { e.setAttribute(k, attrs[k]); }); return e; } var spacing = 170, mid = (scenes.length - 1) / 2; dotsLayer.appendChild(make('line', { x1: 640 - mid * spacing, x2: 640 + mid * spacing, y1: 652, y2: 652, 'class': 'track' })); scenes.forEach(function (s, i) { var x = 640 + (i - mid) * spacing; s.dot = make('circle', { cx: x, cy: 652, r: 8, 'class': 'dot' }); dotsLayer.appendChild(s.dot); var label = make('text', { x: x, y: 690, 'class': 'step' }); label.textContent = s.label; dotsLayer.appendChild(label); }); // Show scene i (i === scenes.length means the pause before looping) var current = -2; function show(i) { if (i === current) { return; } current = i; scenes.forEach(function (s, j) { s.el.classList.remove('play'); s.dot.classList.toggle('active', j === i); s.dot.classList.toggle('done', j < i); }); void svg.getBoundingClientRect(); // force reflow so CSS animations restart if (i < scenes.length) { scenes[i].el.classList.add('play'); } } var t0 = performance.now(); var rafId = 0; function frame(now) { var t = ((now - t0) / 1000) * TIMING.speed; // timeline seconds if (t < 0) { t = 0; } if (t >= total) { t0 = now; t = 0; } // loop var i = -1; for (var k = 0; k < scenes.length; k++) { if (t >= scenes[k].start && t < scenes[k].start + scenes[k].dur) { i = k; break; } } if (i === -1) { i = scenes.length; } show(i); rafId = requestAnimationFrame(frame); } function replay() { cancelAnimationFrame(rafId); t0 = performance.now(); current = -2; show(0); rafId = requestAnimationFrame(frame); } document.getElementById('replay').addEventListener('click', replay); document.addEventListener('visibilitychange', function () { if (document.visibilityState === 'visible') { replay(); } // keep CSS and clock in step }); replay(); })(); </script> </body> </html> ``` **Speed:** change `TIMING.speed` at the top of the file (for example `0.8` for slower, `1.25` for faster). The scene clock and every CSS animation scale together. **Colours:** edit the hex values in `THEME` (and `FONT`) in the same constants block. Every shape reads from them, and reordering the entries in `TIMING.scenes` reorders the film.

Run on Claude Sonnet 5.5, 30 Oct 2026. Automatic check: 1 out of 5.

Mentioned for

Claude Opus 5.5

Where it came from

Found on GitHub, shared by yihui-dev: yihui-dev/awesome-opus5-5-videos.

This is our own version of the idea, written and tested by us. The original may differ.

More coding prompts

Coding Partly worked
Evidence-Backed Feature Tracing

You get a clear, step-by-step explanation of one feature, with every claim tied to a line of code. It works because the reply must split proven facts from guesses and gaps, so you can trust what you read.

Found on GitHub, shared by JoasASantos
Coding Struggled in our test
Fast Evidence-Based Binary Investigation

It gives you an agent run that finds answers in unfamiliar binaries or app bundles quickly, with each claim tied to evidence. Batching commands and labelling certainty cuts wasted turns and stops guesses passing as facts.

Found on GitHub, shared by aicodeking
Coding Partly worked
Build a Pass/Fail Test Set for Prompts

You get a ready-made set of test inputs with yes/no checks and a pass mark for any prompt you rely on. Turning vague quality worries into specific checks lets you compare prompt versions fairly and spot regressions.

Found on GitHub, shared by promptfoo