Motion Ad
Overview
Section titled “Overview”Turns a landing page into a paid-traffic-ready video spot. The skill researches the destination page, pulls the product’s real imagery, animates a single paused GSAP timeline in one HTML page, and renders it frame by frame into an H.264 MP4.
The renderer does not screen-record: it seeks the timeline on every frame, so the output is deterministic and two renders of the same index.html are identical. That’s what makes iteration drift-free.
The bundled template (assets/template.html) is not a scaffold — it’s a complete 15s 4:5 ad in five beats:
hook + phone → before/after scan reveal → 3D wall of outputs→ showcase carousel + social proof → CTA end cardAll brand and product content lives in a single CONFIG object at the top of the script. The intended workflow is to rewrite the beats from that CONFIG, not to build a timeline from scratch.
When to Use
Section titled “When to Use”- Produce a video ad, promo video, or animated ad for Meta, TikTok, or Reels
- Create video creative whose on-screen claims are anchored to the landing page
- Cut a 9:16 version of an existing 4:5 spot
- Re-render an earlier ad with a different hook, hero, or CTA
- Any request for a “video ad”, even when the person never says “motion graphics”
When Not to Use
Section titled “When Not to Use”This skill is narrow, and a scope mistake here costs a full render:
| Request | Right skill |
|---|---|
| Animating a button, hover, parallax, or scroll in a site/app | animate, transitions-dev |
| Static feed artwork (1080×1350, carousel covers) | image |
| Long-form video with an on-camera presenter or voiceover | video |
| Ad copy (headlines, RSA, primary text) | ad-creative |
Installation
Section titled “Installation”npx skills add https://github.com/fabricioctelles/skills -s motion-adRequirements
Section titled “Requirements”The skill needs a local toolchain — the agent alone is not enough:
node -v # 18+ffmpeg -version # mandatorypython3 -c 'import PIL' # Pillow
cd <skill>/scripts && npm install # gsap + playwright-coregoogle-chrome --version # or: npx playwright install chromiumWithout ffmpeg there is no MP4. Without Chrome (or Playwright’s chromium) there is no render. npm install must run inside the skill folder, because the scripts resolve their own dependencies.
How It Works
Section titled “How It Works”| Step | What happens | Completion criterion |
|---|---|---|
| 1. Research | Reads the landing page: promise, prices, ratings, what’s free | A claim list, each one traceable to a page |
| 2. Assets | Downloads the site’s real imagery, builds the contact sheet | Logo + before/after pair + ≥12 output images |
| 3. Storyboard | Sets copy and beats, 4–5 blocks across 15s | Final copy on every beat |
| 4. CONFIG | Fills brand, colors, copy, and image paths | Test stills with no Acme and no Benefit one |
| 5. Stills review | Renders 9 frames and tiles them into a contact sheet | No placeholders, no overlaps, readable at thumbnail size |
| 6. Render + deliver | Full MP4, ffprobe, versioned delivery |
File in ~/Downloads/ with correct duration and nb_frames |
Between step 4 and step 5 sits references/template-map.md — the template anatomy with the
render contract, every CONFIG field, DOM ids, geometry constants, and the recipes for
cutting/adding a beat and re-laying out.
Ad Structure
Section titled “Ad Structure”| Time | Beat | CONFIG fields |
|---|---|---|
| 0–2.2s | Hook, phone scrolls a screen capture, finger taps the input | hook, screen, screenScroll, tap |
| 2.2–5.4s | Tapped card grows into the hero; scan beam reveals before → after; benefit pills | reveal, before, after, beforeLabel, afterLabel, benefits |
| 5.5–8.7s | Hero shrinks into a tilted 3D wall of outputs | scale, scaleChip, gallery |
| 8.7–11.8s | Showcase carousel (3 cards) + proof row | proofHl, showcase, showChip, proof |
| 11.8–15s | Brand-color circle wipe → logo, headline, chip, button tap | cta.headline, cta.chip, cta.button, cta.foot |
If a beat doesn’t fit the product, cut it in the timeline instead of forcing it — a desktop tool should open on the hero card, not on a phone.
Formats
Section titled “Formats”| Format | Change needed |
|---|---|
| 4:5 (default) | Already the template. Render with --size 1080x1350 |
| 9:16 (reels/stories) | html,body,#stage → 1080×1920, re-space the vertical positions, --size 1080x1920 |
| 1:1 (square feed) | The tight one: the phone is 520×1100 and won’t fit 1080×1080. Needs a rescale or a different opening beat — not just re-spacing |
Non-Negotiables
Section titled “Non-Negotiables”The skill separates four rules from the rest because each one’s failure is invisible in the output file — the MP4 renders either way:
- Every on-screen claim must exist on the destination page. Prices, counts, speeds, guarantees, and “free” get checked by the ad platform and by users. If the client asks for copy that contradicts the page, write it — but flag the conflict once, clearly.
- Real assets only. The client’s own images, or ones pulled from the live site. Never invent customers, reviews, ratings, or results. With no real number for the proof row,
proof: null— the row disappears. - Never fabricate a person. If a beat needs more shots of someone than exist, crop or mirror real ones and say so.
- The brand beats the template. Colors, font, logo, and tone come from the product. No hype, no exclamation marks, no emoji unless the brand uses them.
Gotchas That Save a Render
Section titled “Gotchas That Save a Render”The ones that cost the most time, because the failure only shows up in the final MP4:
- The timeline is absolute. Every
tl.*()call takes a hard-coded second. Cutting the phone beat without re-timing leaves the video frozen on a still frame until the next beat. - A wrong image path is not an error.
setImgswaps in a labelled placeholder ononerror— the render “passes” and comes out full of gradients. Check the contact sheet every time. - Fewer than ~12 images repeats visibly in the 3D wall. The 7×7 grid picks cells by modulo over
gallery, so neighbouring tiles land on the same image. --sizedoes not give you 2×. The CSS is hard-coded to 1080×1350 anddeviceScaleFactoris 1. For a 2× master, scale#stagein CSS.- A long headline doesn’t shrink, it collides. The box is pinned at a fixed
topand the extra line grows downward into whatever sits below it. tapandscreenScrollare the same gesture. The finger point is fixed; if the scroll moves the target away, the tap lands on empty white.
Skill Quality
Section titled “Skill Quality”Evaluated with skill-evaluation — the same rubric used by
Agent Plugin Eval:
| Criterion | Before | After |
|---|---|---|
| Overall score | 65 (B) | 88 (A) |
| Completion criteria | 20 | 90 |
| Gotchas | 55 | 95 |
| Grounded in expertise | 60 | 95 |
| Progressive disclosure | 35 | 90 |
| Setup / Preflight | 45 | 88 |
Trigger eval across 10 prompts: 5/5 hit rate on requests that should fire, 0/5 leak rate on near-misses (React hover pop, static 1080×1350 cover, 8-minute video, scroll animation, logo gif).
License
Section titled “License”The copy in this repository adds standard metadata, portable skill-path resolution, a preflight
check, and references/template-map.md.
Reference
Section titled “Reference”- Full documentation on GitHub
- Template map — render contract,
CONFIGfields, geometry, recipes - Original skill at danny.md