Produce a Photo-Grid promo card — a silent, music-optional feed-placement video where a scrolling 2×N tile grid (product photos + short brand video clips + big-type offer tiles + a promo-code tile) animates under a centered wordmark, headline, sub, and outline feature chips. 9:16 or 4:5, ~10s, $0 HTML-hyperframe pipeline (no T2V, no VO). Recreates the Meta "photo-grid mosaic" template (e.g. "Our New Band 2.0 / LAUNCH30"). Validated on Hume Health (Father's Day promo, 2026-06-03). Use when the brand wants a clean editorial feed card that works muted; NOT for kinetic-BG vignette (use create-vignette-ad), UGC, or VO-driven ads.
Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.
Quelldateien prüfen
Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
Produce a Photo-Grid promo card — a silent, music-optional feed-placement video where a scrolling 2×N tile grid (product photos + short brand video clips + big-type offer tiles + a promo-code tile) animates under a centered wordmark, headline, sub, and outline feature chips. 9:16 or 4:5, ~10s, $0 HTML-hyperframe pipeline (no T2V, no VO). Recreates the Meta "photo-grid mosaic" template (e.g. "Our New Band 2.0 / LAUNCH30"). Validated on Hume Health (Father's Day promo, 2026-06-03). Use when the brand wants a clean editorial feed card that works muted; NOT for kinetic-BG vignette (use create-vignette-ad), UGC, or VO-driven ads.
status
ACTIVE — validated on Hume Health (pick-05 Father's Day promo card, 2026-06-03)
create-photo-grid-ad
Photo-Grid format = a continuously-scrolling tile grid (product photos + short brand
video clips + big-type offer + promo-code tiles) under a wordmark + headline + chips.
Silent, music-optional, sub-12s, loopable. A single HTML hyperframe rendered frame-by-frame
via Playwright + ffmpeg — $0 spend, ~30s compute. This is the cheap, editorial sibling
of create-vignette-ad (which lays product cutouts over a paid T2V kinetic background).
Purpose
Produce a short-form (8–12s) vertical or 4:5 Photo-Grid promo card for a brand by:
Gathering brand assets (clean product PNGs, logo SVG, brand palette, and short clips
harvested from the brand's own existing ad corpus — HD source preferred over Pexels).
Authoring ONE HTML hyperframe: centered wordmark, big headline + sub, a 2×N tile grid that
scrolls horizontally for the whole duration behind an edge-fade mask, and outline feature chips.
Filling the grid with a rhythm of tile kinds — product photos, short looping brand video clips,
big-type offer tiles (e.g. "25%" / "OFF" in a display serif), and one dark promo-code tile.
Rendering it frame-stepped (Playwright screenshot per frame, videos played in real time) and
encoding to MP4 with ffmpeg.
Optionally laying an instrumental music bed under it (EBU R128 loudness-normalized) — the base
master is silent and works muted.
Use when:
The brand has clean product photography AND/OR an existing ad/video corpus to harvest tiles from.
The aesthetic target is an editorial, premium feed card that reads instantly while muted.
A promo/offer (discount + code) or a seasonal hook ("For dad, by Hume.") drives the card.
Budget is ~$0 and turnaround is minutes.
Do NOT use for:
Kinetic-background atmospheric ads with product cutouts → use create-vignette-ad (paid T2V BG).
UGC creator / talking-head ads → use skills/molecules/ugc-ad/*.
VO-driven explainers or demos → use a VO-anchored beat-video molecule.
Long-form (>15s) → the format's read breaks past ~12s.
Inputs
Required:
brand_url — e.g. https://humehealth.com (for product PNGs, logo, palette).
headline — 2–4 words, 1–2 lines, e.g. "For dad, by Hume.".
offer — discount + code, e.g. 25% OFF + DAD25 (or a non-promo hook if the card is brand-led).
Optional (with autonomous defaults):
aspect_ratio — 9:16 (default, 1080×1920) or 4:5 (1080×1350).
duration_s — default 10.0 (range 8–12).
sub — one line under the headline, e.g. "The longevity band, gift-wrapped.".
chips — 0–3 outline feature pills, e.g. ["14 DAY BATTERY", "NEW PATENTED STRAP"].
palette — { ink, ink_soft, bg, bg_tile, bg_band, accent } hex; default derived from the brand homepage CSS (top frequencies) + the brand accent.
fonts — one display sans + one display serif (default Cabinet Grotesk + Zodiak via Fontshare).
music_brief — free-text; when set, an instrumental bed is generated and muxed. Default: silent.
source_clips — brand ad-corpus clips to extract video tiles from (default: scan the brand's
existing-ads corpus for sustained-shot HD moments; fall back to Pexels portrait stock).
Prerequisites:
Playwright Chromium + ffmpeg/ffprobe on the machine.
librsvg (rsvg-convert) if the logo is an SVG that needs rasterizing.
PEXELS_API_KEY (optional) only if the brand has no usable corpus and stock tiles are needed.
For a music bed: the Gooseworks ElevenLabs proxy (bills the user's credits) or a stored asset.
Composed Atoms
source-brand-assets — scrape product PNGs from the brand Shopify/CDN, brand palette hex from the homepage CSS, and the logo SVG from the footer.
create-motion-graphics-hyperframes — author + frame-step render the HTML hyperframe (wordmark + headline + sub + scrolling grid + chips) via Playwright; the renderer scaffold (initRenderer, tw/easeOut/clamp01) drives per-frame opacity/transform.
stitch-videos-ffmpeg — extract sustained-shot tile clips from the brand corpus (scale→crop→scale for low-bitrate sources), apply setpts slowdown so no tile loops within the window, and encode the frame sequence to MP4.
create-music-elevenlabs — optional instrumental bed via the ElevenLabs music endpoint (generate ~2s longer than the card, trim).
add-music-track — EBU R128 loudness-normalize the bed (loudnorm I=-18:TP=-2:LRA=9) and mux it as a SEPARATE ffmpeg pass with explicit -map 0:v:0 -map 1:a:0.
watch — /watch:watch for end-to-end QC on the rendered master.
Workflow
Phase 0 — Brand asset gathering (autonomous)
Scrape clean product PNGs from the brand PDP (highest-res available). Promote the best PDP
shots into the shared brand-assets/reference-photos/ namespace so later cards reuse them.
Scrape brand palette + logo — top hex frequencies from the homepage CSS; logo SVG from the
footer/theme assets. Derive { ink, ink_soft, bg, bg_tile, bg_band, accent }.
Harvest tile video clips — scan the brand's existing-ads corpus for HD, sustained-shot
moments (product macro, app screen-record, a clean lifestyle beat). Probe existing-ads/*.mp4
for resolution BEFORE reaching for any meta-library/*.mp4 — meta-library is 360p delivery and
reads blurry upscaled; existing-ads is the HD pool. Avoid Pexels when the brand has its own corpus.
Audit clip captions for compliance — brand ad b-roll sometimes carries on-screen claims
(e.g. health-risk overlays). Skip any clip whose caption makes a sensitive claim.
Output:brief.md with the chosen tiles (product photos + clip windows), palette swatches,
headline/sub/offer/chips copy, and aspect/duration.
Phase 1 — Author the hyperframe (autonomous)
Author one HTML file at the target canvas (1080×1920 for 9:16). Load the display sans + serif
from Fontshare. Lay out: centered wordmark (top), headline (big extrabold, ≤2 lines), sub, a
grid-viewport with an edge-fade mask-image, a grid-track of repeat(tiles-per-row, W)
columns × N rows, and outline chips near the bottom.
Fill the tiles with a rhythm — product-photo tiles (object-fit: contain on a band background),
video-clip tiles (<video autoplay muted loop playsinline>, object-fit: cover), big-type
offer tiles (display serif, e.g. "25%" / "OFF"), and one dark promo-code tile (label + value with
an accent-colored prefix, e.g. DAD in accent + 25 in white).
Drive motion in initRenderer(duration, t => …): wordmark fade-in (0–0.4s), headline drop+fade
(0.1–0.7s), sub fade (0.5–0.9s), then a continuous linear translateX scroll of the track across
its full overflow for the whole duration (with a soft eased entry), and chips fade-up (1.5–1.9s).
All asset paths must be RELATIVE to the HTML file — Playwright renders blank for file://
absolute paths.
Phase 2 — Render + optional music (autonomous)
Frame-step render: launch Chromium with --autoplay-policy=no-user-gesture-required, wait for
fonts + every <video>'s canplay + play(), then for each of duration×fps frames call
renderAt(t), double-requestAnimationFrame, screenshot, and sleep to keep real-time video
playback. Encode the PNG sequence to MP4 (h264, yuv420p, +faststart, 25fps) → silent master.
Tile clip prep: for each corpus clip, setpts=N*PTS where N = duration / clip_len so the
tile never loops within the window (2–4× slowdown also reads as premium slow-mo).
Optional music: when music_brief is set, generate an instrumental bed, loudness-normalize,
and mux as a separate pass (-map 0:v:0 -map 1:a:0 -shortest). Verify audio bit_rate ≈ 192k.
Self-QC via /watch:watch: scroll is smooth and continuous; headline + chips legible; type
tiles don't bleed; no video tile visibly loops; promo code readable; duration ≈ target.
Decision Rules
One HTML, one render script — skip the full beat-video pipeline. When the brief is a static/
scrolling photo grid or feed promo card, do NOT bring in VO, Whisper, beat manifests, concat, or
captions. Author one hyperframe + one render pass. (~30s compute, $0.)
Grounded brand corpus beats Pexels for tile content. The brand's own ads carry authentic
color grade, lighting, and product fidelity stock can't match. Reach for Pexels only when the
brand has no usable corpus.
HD source only — probe existing-ads/ before meta-library/. Meta-library ads are 360p
delivery; upscaled into a 1080-wide tile they read obviously stock-y.
grid-template-columns: repeat(N, W) is tiles-PER-ROW, not total tiles. Setting it to the
total tile count packs everything into row 1 and leaves later rows empty.
setpts slowdown, never <video loop> with short clips. One visible loop-restart makes the
whole tile read as cheap stock. Slow each clip to fill the window (or ping-pong).
Edge-fade the grid viewport with a horizontal mask-image gradient so scroll tiles appear/
disappear softly instead of popping at the edges.
Pair one display sans with one display serif when the card mixes photo tiles and big-type
tiles — the serif (offer/price) adds rhythm and an editorial "sales-print" weight.
Serif display digits run ~20–30% wider than geometric sans — budget type-tile width at ~65%
of nominal and re-check fit after any aspect change.
Aspect change cascades into every type size. Converting 4:5 ↔ 9:16 isn't free real estate —
re-audit headline, tile, type-in-tile, and chip sizes against the new bounds.
The base master is SILENT and must work muted. Music is an optional bed, never load-bearing —
feed placements autoplay muted. When a bed is used, keep it instrumental and loudness-normalized.
ffmpeg mux: explicit -map 0:v:0 -map 1:a:0 + a SEPARATE pass from the frame encode. Default
mapping silently produces ~1 kbps garbage audio.
Style tokens pass a taste gate — website palette/type is a candidate, not law. Background must
clear a legibility gate vs the headline/offer ink (≥ 4.5:1); when the brand color fails, use
near-white (#F4F8FB/white) with dark ink, or a dark brand-neutral with light ink. Use the brand
font ONLY if it's a loadable webface (Google Fonts/Fontshare); else the house faces (Cabinet
Grotesk + Zodiak). Never author type below the muted-feed floors (1080-wide 9:16): headline ≥
132px, sub ≥ 32px, offer/price ≥ 140px, code value ≥ 88px, code label ≥ 22px, chips ≥ 26px.
(pick-05 ships / and 154 / 38 / 156 / 104 / 26 / 30.)
Output
<project>/
├── brief.md
├── hyperframes/
│ ├── hyperframe.html # the card layout + initRenderer motion
│ └── _shared.js # initRenderer / tw / easeOut / clamp01 scaffold
├── assets/
│ ├── grounded/ # HD tile clips extracted from the brand corpus
│ └── music/ # optional bed (raw + loudnorm)
├── render.py # Playwright frame-step + ffmpeg encode
└── finals/
└── master-<aspect>.mp4 # silent master (+ -music-<variant>.mp4 when a bed is muxed)
The shipped master is the silent master-<aspect>.mp4; music variants are siblings.
sample-input.md — Hume Health Father's Day promo card worked example.
expected-output.md — what a successful render produces.
human-test.md — manual acceptance criteria (watch the card muted).
verifier.md — ffmpeg/ffprobe assertions.
Related
Reference build: Hume Health pick-05 Father's Day promo card — HOW_TO_MAKE_THIS_VIDEO.md +
LEARNINGS.md (18 load-bearing learnings; $0, 9:16, 10-tile scroll with HD corpus video tiles).
Remix wrapper: remix-photo-grid-ad-from-sample —
the app's Photo-Grid format tab calls this to remix a published card for a new brand.
Sibling format: create-vignette-ad — product cutouts over a
paid T2V kinetic background (the atmospheric, not editorial, silent format).
Registry entry: formats.json → "photo-grid".
#E6EEF3
#0E1B22
Photo tiles are REAL product/brand photos only. Source ≥ 720px short-edge; never a favicon or
logo as a photo tile (logos go in the wordmark slot only); never upscale a source past ~1.5×. If
there aren't enough good photos, shrink the grid or mark the slot a pending NB2 generation — never
pad with junk or stock-y filler.