ForkFree

Prompts / Images and video

Code-Drawn Motion Film Brief

You get a style note, a timed beat sheet, working page code that can draw any frame, and a sound plan, all reviewed once. It works because the film is defined as a function of time, so it can be captured frame by frame and checked against clear style rules.

Struggled in our testThe reply is cut off mid-line (`const svg=document.getElementById('st`). It has no complete HTML or renderAt(t) function, no closing code block, no audio plan and no review summary. The style note and beat sheet are good, but the required steps and output format are not met.

The prompt

Act as a motion designer who builds short animated films entirely in code, with no image or video generators.

Task: Build a {film_length}-second animated film in the style of {visual_style} for {brand_or_topic}, as a single web page whose frame can be drawn for any moment in time.

Steps:
1. Write a style note listing the palette, type, shapes and movement rules that define {visual_style}.
2. Plan the film as a beat sheet, giving each scene a start time, end time and one clear idea, based on this message: {core_message}.
3. Write one self-contained HTML file with a function renderAt(t) that draws every element using SVG or Canvas, so any frame can be captured on demand.
4. Describe a soundtrack and sound effects that could be synthesised in code, matched to each beat.
5. Review your own work against the style note, name two weaknesses, then fix them.

Output: the style note, the beat sheet as a table, the complete HTML code in one block, the audio plan as a short list, and a two-line review summary.

Change the parts in curly braces. Use it when you need a short branded motion piece or social clip and want editable code rather than a generated video.

What happened when we ran it

We sent

Act as a motion designer who builds short animated films entirely in code, with no image or video generators.

Task: Build a 10-second animated film in the style of flat vector with bold colour blocks, rounded shapes and bouncy, springy easing for Greenfold, a small Bristol company that sells refillable cleaning products by subscription, as a single web page whose frame can be drawn for any moment in time.

Steps:
1. Write a style note listing the palette, type, shapes and movement rules that define flat vector with bold colour blocks, rounded shapes and bouncy, springy easing.
2. Plan the film as a beat sheet, giving each scene a start time, end time and one clear idea, based on this message: One bottle, refilled again and again, replaces dozens of plastic bottles thrown away each year, saving households money and cutting waste..
3. Write one self-contained HTML file with a function renderAt(t) that draws every element using SVG or Canvas, so any frame can be captured on demand.
4. Describe a soundtrack and sound effects that could be synthesised in code, matched to each beat.
5. Review your own work against the style note, name two weaknesses, then fix them.

Output: the style note, the beat sheet as a table, the complete HTML code in one block, the audio plan as a short list, and a two-line review summary.

The model replied

# Greenfold: "One Bottle" (10 s) I haven't opened this in a browser, so it is untested. It is a pure function of `t`, so you can check any frame with `?t=4.2`. ## 1. Style note - **Palette:** - Coral `#FF6B4A`, the problem colour. - Cream `#FFF3DC`, lime `#C6F26B` and deep green `#0E4D32`, the Greenfold colours. - Leaf green `#1F8A4C` and `#7ED957`, yellow `#FFC93C`, sky `#5CC8FF`, ink `#14301F`. - Dull grey-blue `#9DB4C6` is reserved for plastic, so waste always looks lifeless. - **Type:** One heavy rounded sans (Nunito, then Arial Rounded or Trebuchet, weight 900). Headlines are 46–120 px, with at most two lines at a time and ink on light or cream on dark. - **Shapes:** - Everything is a flat fill with no outlines, gradients or shadows. - Every corner is rounded (rx ≥ 8). - Circles act as colour blocks and wipe transitions. - Bottles, pouches, coins and leaves are built from rounded rectangles and one leaf path. - **Movement:** - Objects arrive with a damped spring that overshoots by about 15% and settles. - Falling things use a bounce. - Impacts add squash and stretch. - Scene changes are circle wipes that overshoot. - Nothing moves linearly, and nothing sits completely still. ## 2. Beat sheet | # | Start | End | Idea | |---|-------|-----|------| | 1 | 0.0 s | 2.0 s | **Problem:** a dozen plastic bottles bounce into a pile. "Dozens of plastic bottles binned every year." | | 2 | 2.0 s | 3.0 s | **Hero:** a cream wipe lands, one green Greenfold bottle drops in, and "One bottle, refilled again and again." appears. | | 3 | 3.0 s | 6.0 s | **Loop:** the bottle is used, a pouch tips in to refill it, and a ×1, ×2, ×3 counter pops, one cycle per second. | | 4 | 6.0 s | 8.0 s | **Payoff:** a lime wipe. A coin stack builds under "Save money. Cut waste." A long grey "Dozens" bar sits against a tiny green "1" bar. | | 5 | 8.0 s | 10.0 s | **Brand:** a deep-green wipe. A logo, "Greenfold", "Refill. Repeat." and "Bristol" appear, with two bottles hopping. | ## 3. HTML ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Greenfold - One Bottle</title> <style> html,body{margin:0;height:100%;background:#0b1a12;display:flex;flex-direction:column;align-items:center;justify-content:center;font-family:system-ui,sans-serif;color:#fff} svg{width:min(100vw,calc((100vh - 50px)*16/9));aspect-ratio:16/9;display:block; font-family:'Nunito','Baloo 2','Arial Rounded MT Bold','Trebuchet MS',system-ui,sans-serif;font-weight:900} #ui{display:flex;gap:12px;align-items:center;padding:10px;width:min(90vw,700px)} #ui input{flex:1} body.clean #ui{display:none} </style> </head> <body> <svg id="stage" viewBox="0 0 1280 720" xmlns="http://www.w3.org/2000/svg"></svg> <div id="ui"><button id="pb">Pause</button><input id="sc" type="range" min="0" max="10" step="0.01" value="0"><span id="tl">0.00s</span></div> <script> const W=1280,H=720,DUR=10; const C={cream:'#FFF3DC',coral:'#FF6B4A',coralD:'#E5502F',green:'#1F8A4C',deep:'#0E4D32',lime:'#C6F26B', leaf:'#7ED957',yellow:'#FFC93C',yellowD:'#E8A100',sky:'#5CC8FF',skyD:'#2E9FD6',ink:'#14301F', plastic:'#9DB4C6',plasticD:'#7C97AB'}; /* ---------- maths & easing ---------- */ const clamp=(x,a=0,b=1)=>Math.min(b,Math.max(a,x)); const lerp=(a,b,k)=>a+(b-a)*k; const sm=(a,b,x)=>{const k=clamp((x-a)/(b-a));return k*k*(3-2*k)}; const spring=p=>p<=0?0:p>=1?1:1-Math.exp(-5.5*p)*Math.cos(9*p); // ~15% overshoot, settles const pop=(t,s,d=0.8)=>spring((t-s)/d); const eob=p=>{p=clamp(p);const c1=1.70158,c3=c1+1;return 1+c3*Math.pow(p-1,3)+c1*Math.pow(p-1,2)}; const bounce=x=>{const n=7.5625,d=2.75;x=clamp(x); if(x<1/d)return n*x*x; if(x<2/d){x-=1.5/d;return n*x*x+.75} if(x<2.5/d){x-=2.25/d;return n*x*x+.9375} x-=2.625/d;return n*x*x+.984375}; const rnd=i=>{const x=Math.sin(i*127.1+311.7)*43758.5453;return x-Math.floor(x)}; /* ---------- primitives ---------- */ const T=(s,x,y,size,fill,o={})=>{ const k=o.k===undefined?1:o.k; if(k<=0.001)return ''; const op=o.op===undefined?clamp(k*4):o.op; return `<text transform="translate(${x} ${y}) rotate(${o.r||0}) scale(${k})" font-size="${size}" fill="${fill}" text-anchor="${o.a||'middle'}" opacity="${op}">${s}</text>`; }; const leaf=(x,y,s,rot,fill,vein)=>`<g transform="translate(${x} ${y}) rotate(${rot}) scale(${s})"> <path d="M-26 28 C-30 -10 0 -34 30 -32 C34 0 10 30 -26 28Z" fill="${fill}"/> <path d="M-22 24 L16 -16" stroke="${vein}" stroke-width="4" stroke-linecap="round"/></g>`; const bottle=(x,y,s,rot,body,cap)=>`<g transform="translate(${x} ${y}) rotate(${rot}) scale(${s})"> <rect x="-15" y="-44" width="30" height="40" rx="9" fill="${body}"/> <rect x="-18" y="-62" width="36" height="24" rx="9" fill="${cap}"/> <rect x="-38" y="-12" width="76" height="116" rx="26" fill="${body}"/> <rect x="-26" y="4" width="10" height="60" rx="5" fill="#fff" opacity=".5"/></g>`; function hero(x,y,s,lvl,q,sq,id,body=C.green){ const sx=s*(1-sq), sy=s*(1+sq); const capT=`translate(${q*80} ${-q*70}) rotate(${q*28} 0 -50)`; return `<g transform="translate(${x} ${y-104*s*sq}) scale(${sx} ${sy})"> <defs><clipPath id="${id}"><rect x="-24" y="0" width="48" height="64" rx="18"/></clipPath></defs> <rect x="-15" y="-44" width="30" height="40" rx="9" fill="${body}"/> <rect x="-38" y="-12" width="76" height="116" rx="26" fill="${body}"/> <rect x="-24" y="0" width="48" height="64" rx="18" fill="${C.cream}"/> <rect x="-24" y="${64*(1-lvl)}" width="48" height="${64*lvl+1}" fill="${C.leaf}" clip-path="url(#${id})"/> ${leaf(0,86,.42,0,C.cream,body)} <g transform="${capT}"><rect x="-18" y="-62" width="36" height="24" rx="9" fill="${C.yellow}"/></g></g>`; } function pouch(cx,cy,a){return `<g transform="translate(${cx} ${cy}) rotate(${a})"> <rect x="-55" y="-80" width="110" height="160" rx="30" fill="${C.yellow}"/> <rect x="-53" y="-100" width="26" height="30" rx="9" fill="${C.yellowD}"/> <rect x="-56" y="-110" width="32" height="16" rx="7" fill="${C.coral}"/> <circle cx="0" cy="12" r="34" fill="${C.coral}"/>${leaf(0,12,.55,0,C.cream,C.coral)} <rect x="-44" y="-62" width="9" height="90" rx="4.5" fill="#fff" opacity=".45"/></g>`} const coin=(x,y)=>`<rect x="${x-90}" y="${y-8}" width="180" height="44" rx="22" fill="${C.yellowD}"/> <rect x="${x-90}" y="${y-22}" width="180" height="44" rx="22" fill="${C.yellow}"/> <rect x="${x-58}" y="${y-12}" width="116" height="8" rx="4" fill="#FFE08A"/>`; function wipe(t,start,color,cx,cy){ const p=(t-start)/0.9; if(p<=0)return ''; return `<circle cx="${cx}" cy="${cy}" r="${1500*eob(sm(0,1,p))}" fill="${color}"/>`; // eased start, then overshoot } /* ---------- scene 1: the problem (0-2s) ---------- */ function s1(t){ let o=`<rect x="-20" y="676" width="1320" height="80" rx="30" fill="${C.coralD}"/>`; const rows=[5,4,3]; let i=0; for(let r=0;r<3;r++)for(let k=0;k<rows[r];k++,i++){ const d=0.15+i*0.1; if(t<d)continue; const p=clamp((t-d)/0.75); const rx=640+(k-(rows[r]-1)/2)*84+(rnd(i)-.5)*14, ry=616-r*66; const y=lerp(-140,ry,bounce(p)); const rot=(rnd(i+3)-.5)*110*sm(0,.8,p)+(1-p)*160*(rnd(i)>.5?1:-1); o+=bottle(rx,y,.62,rot,i%3==0?C.sky:C.plastic,i%3==0?C.skyD:C.plasticD); } o+=T('Dozens of plastic bottles',640,160,66,C.cream,{k:pop(t,.3)}); o+=T('binned every year.',640,240,66,C.yellow,{k:pop(t,.55)}); return o; } /* ---------- scene 2: hero + refill loop (2-6s) ---------- */ function s2(t){ let o=''; o+=`<circle cx="1150" cy="70" r="${80*pop(t,2.3)}" fill="${C.coral}"/>`; o+=`<circle cx="1090" cy="190" r="${34*pop(t,2.45)}" fill="${C.sky}"/>`; o+=`<circle cx="430" cy="470" r="${250*pop(t,2.15,.9)}" fill="${C.lime}"/>`; o+=`<rect x="-20" y="640" width="1320" height="100" rx="40" fill="${C.green}"/>`; // cycle state: 1.0 s per refill cycle (120 bpm, 2 beats) const c=(t-3)/1.0; let lvl=1,f=0,q=0,n=0,sq=0,amt=0; if(t>=3&&c<3){ f=c%1; lvl=f<.5?1-.8*sm(.05,.45,f):.2+.8*sm(.58,.93,f); q=f<.42?0:eob((f-.42)/.16)*(1-sm(.9,1,f)); amt=sm(.56,.6,f)*(1-sm(.92,.95,f)); } n=c>=1?Math.min(3,Math.floor(c)):0; if(n>=1){const f2=c-n; sq=0.09*Math.exp(-7*f2)*Math.cos(22*f2);} // pouch pose const ox=600*(1-eob((t-2.9)/0.7)); const a=lerp(-12,-135,q), ar=a*Math.PI/180; const pcx=lerp(780+ox,475,q), pcy=lerp(330,225,q); const spx=pcx+(-40)*Math.cos(ar)-(-104)*Math.sin(ar); const spy=pcy+(-40)*Math.sin(ar)+(-104)*Math.cos(ar); // pour stream sits BEHIND the bottle so it never crosses the (popped-off) cap if(amt>0.01){ const surf=440+64*(1-lvl)*1.9; o+=`<line x1="${spx}" y1="${spy}" x2="430" y2="${surf}" stroke="${C.leaf}" stroke-width="${14*amt}" stroke-linecap="round"/>`; } // bubbles while the bottle is being used if(t>=3&&c<3&&f<.5){ for(let i=0;i<5;i++){ const b=clamp((f-.03-i*.06)/.3); if(b>0&&b<1){ o+=`<circle cx="${500+(rnd(i)-.2)*150*b}" cy="${330-b*150}" r="${(10+12*rnd(i+9))*Math.sin(Math.PI*b)}" fill="${C.sky}"/>`; } } } // hero bottle drops in with a real bounce if(t>=2.3){ const y=lerp(-260,440,bounce((t-2.3)/0.8)); o+=hero(430,y,1.9,lvl,q,sq,'w'); } if(t>=2.9) o+=pouch(pcx,pcy,a); o+=T('One bottle, refilled again and again.',640,92,46,C.ink,{k:pop(t,2.4)}); if(n>=1){ const k=pop(t,3+n,.7); o+=`<circle cx="1030" cy="430" r="${100*k}" fill="${C.yellow}"/>`; o+=T('\u00d7'+n,1030,458,88,C.ink,{k}); o+=T('refills',1030,510,32,C.ink,{k}); } return o; } /* ---------- scene 3: payoff (6-8s) ---------- */ function s3(t){ let o=''; o+=T('Save money. Cut waste.',640,110,70,C.ink,{k:pop(t,6.3)}); for(let i=0;i<6;i++){ const d=6.5+i*.15; if(t<d)continue; o+=coin(300,lerp(-80,598-i*30,bounce((t-d)/.55))); } const kc=pop(t,7.4,.8); o+=`<g transform="translate(300 ${598-6*30-26}) scale(${kc})"><circle r="56" fill="${C.yellowD}"/><circle r="48" fill="${C.yellow}"/></g>`; o+=T('\u00a3',300,598-6*30-6,64,C.ink,{k:kc}); o+=T('Save money',300,682,40,C.ink,{k:pop(t,7.0)}); o+=T('Plastic bottles bought a year',600,250,30,C.ink,{a:'start',k:pop(t,6.6),op:.8}); const w1=560*pop(t,6.7,.8), w2=100*pop(t,7.1,.8); if(w1>1)o+=`<rect x="600" y="285" width="${w1}" height="84" rx="42" fill="${C.plastic}"/>`; o+=T('Dozens',640,339,40,C.cream,{a:'start',k:pop(t,6.9)}); if(w2>1)o+=`<rect x="600" y="405" width="${w2}" height="84" rx="42" fill="${C.green}"/>`; o+=T('1 refillable bottle',600+w2+24,459,36,C.ink,{a:'start',k:pop(t,7.3)}); const kl=pop(t,7.5,.8); o+=`<circle cx="1100" cy="590" r="${72*kl}" fill="${C.green}"/>`; o+=leaf(1100,590,1.5*kl,10,C.lime,C.green); o+=`<circle cx="1210" cy="520" r="${26*pop(t,7.65)}" fill="${C.coral}"/>`; return o; } /* ---------- scene 4: brand card (8-10s) ---------- */ function s4(t){ let o=''; o+=`<circle cx="1130" cy="110" r="${90*pop(t,8.1)}" fill="${C.coral}"/>`; o+=`<circle cx="130" cy="130" r="${50*pop(t,8.2)}" fill="${C.sky}"/>`; o+=`<rect x="${580}" y="${650}" width="120" height="40" rx="20" fill="${C.yellow}" transform="scale(${pop(t,8.3)})" style="transform-origin:640px 670px"/>`; const kk=pop(t,8.15,.9); o+=`<g transform="translate(640 250) rotate(${Math.sin(t*3)*3}) scale(${kk})"><circle r="110" fill="${C.cream}"/>${leaf(0,0,3,0,C.green,C.cream)}</g>`; o+=T('Greenfold',640,480,124,C.cream,{k:pop(t,8.4)}); o+=T('Refill. Repeat.',640,555,58,C.lime,{k:pop(t,8.65)}); o+=T('Refillable cleaning by subscription \u00b7 Bristol',640,615,28,C.cream,{k:pop(t,8.9),op:.9}); [[220,8.6,0],[1060,8.75,.4]].forEach(([x,st,off],i)=>{ const k=pop(t,st,.8); if(k<=0.001)return; let hop=0,sq=0; if(t>=9.0){ const ph=((t-9.0+off)%0.8+0.8)%0.8; hop=-50*Math.sin(Math.PI*clamp(ph/.5)); if(ph>.5){const g=ph-.5; sq=0.09*Math.exp(-9*g)*Math.cos(26*g);} } o+=hero(x,440+hop,1.3*k,1,0,sq,'b'+i,C.leaf); }); return o; } /* ---------- the frame function ---------- */ const svg=document.getElementById('stage'); function renderAt(t){ t=clamp(t,0,DUR); let o=`<rect width="${W}" height="${H}" fill="${C.coral}"/>`; if(t<2.7) o+=s1(t); o+=wipe(t,2.0,C.cream,640,400); if(t>=2.0&&t<6.7) o+=s2(t); o+=wipe(t,6.0,C.lime,1030,430); if(t>=6.0&&t<8.7) o+=s3(t); o+=wipe(t,8.0,C.deep,640,300); if(t>=8.0) o+=s4(t); svg.innerHTML=o; } window.renderAt=renderAt; /* ---------- player (not part of the frame logic) ---------- */ const qs=new URLSearchParams(location.search); let playing=!qs.has('t'), clock=qs.has('t')?+qs.get('t'):0, last=performance.now(); if(qs.has('clean'))document.body.classList.add('clean'); const sc=document.getElementById('sc'),tl=document.getElementById('tl'),pb=document.getElementById('pb'); pb.onclick=()=>{playing=!playing;pb.textContent=playing?'Pause':'Play'}; sc.oninput=()=>{clock=+sc.value;playing=false;pb.textContent='Play'}; function loop(now){ if(playing)clock=(clock+(now-last)/1000)%DUR; last=now; renderAt(clock); sc.value=clock; tl.textContent=clock.toFixed(2)+'s'; requestAnimationFrame(loop); } requestAnimationFrame(loop); </script> </body> </html> ``` ## 4. Audio plan All of it can be made with the Web Audio API or an OfflineAudioContext. The tempo is 120 bpm, so the 2 s, 3 s, 6 s and 8 s cuts land on beats. - **0–2 s, problem:** - A muted, slightly detuned square-wave bass pulse. - A short noise burst through a band-pass filter plus a sine thump (pitch 300→120 Hz) for each bottle landing. Pitch each one a little differently. - A low rising filter sweep into the cut. - **2–3 s, hero:** - A cream-wipe "whoosh" from white noise with a rising band-pass. - A marimba-style drop (sine plus a fast-decaying 2× partial) when the bottle lands. - A bright major chord on a plucked-synth patch. - **3–6 s, loop:** - A bouncy bass: a four-note pattern on beats 1 and 3, using triangle waves with a short pitch glide. - A hi-hat from filtered noise on the off-beats. - A "pssst" noise burst plus rising bubble blips (sine glides) during use. - A cap pop (a 600→900 Hz sine click). - A glug sound during the pour: a low sine with fast vibrato, rising in pitch as the bottle fills. - A coin-style ping at each ×1, ×2 and ×3, one step higher each time (C5, E5, G5). - **6–8 s, payoff:** - A swoosh on the lime wipe. - A coin clink for each coin landing: two high sines (about 2.1 kHz and 3.2 kHz) with a quick decay. - A sparkle arpeggio when the £ coin lands. - A soft whoomp as the bars slide out, then a bright "ding" on the small green bar. - **8–10 s, brand:** - A deep-green swoosh into a big major chord (pad plus pluck). - A rising three-note motif synced to the wordmark and tagline. - A boing at each bottle hop (sine glide 200→400 Hz). - A tail with a 1 s filter-sweep release. ## 5. Review **Review:** Against the style note, the layout, palette, rounded shapes and spring easing hold up. Two weaknesses came out of the first pass: 1. The pour stream crossed the bottle cap, which made the refill read as a glitch. I fixed it by popping the cap off with a bounce and drawing the stream behind the bottle. 2. The circle wipes snapped open too abruptly for the springy feel. I fixed it by easing the wipe's start with smoothstep and then letting it overshoot.

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

Mentioned for

Claude Opus 5.5, Claude Code

Where it came from

Found on GitHub, shared by Vincentwei1021: Vincentwei1021/mg-styles-15.

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

More images and video prompts

Images and video Partly worked
Timed Shot Script for AI Video

You get a clean, timed script where every beat has one shot, one action and one sound. Splitting the clip this way stops the generator blending several actions into a muddle.

Found on GitHub, shared by LearnPrompt
Images and video Worked in our test
Timed Shot-by-Shot Video Prompt Writer

It gives you a ready-to-paste video prompt that sets the look first, then breaks the action into timed shots. Video models cope better with clear timings, camera moves and one action per shot than with a loose paragraph.

Found on GitHub, shared by ZeroLu
Images and video Worked in our test
Break Image Prompts Into Labelled Parts

You get a rough image prompt sorted into labelled parts, with clashes flagged and a tidy rebuilt version. Seeing each phrase's job makes it easier to spot padding and contradictions, such as asking for both watercolour and photorealistic.

Found on GitHub, shared by Moonvy