$npx -y skills add gooseworks-ai/goose-skills --skill render-photo-grid-cardRender a 'photo-grid promo card' video from a config — a real-DOM card with a FIXED header/footer and a CONTINUOUSLY SCROLLING 2-row grid of MIXED tiles (video clips, product/lifestyle stills, big-serif %-OFF, dark promo-code or CTA) + feature chips, frame-stepped via Playwright
| 1 | # render-photo-grid-card |
| 2 | |
| 3 | Render the 'photo-grid promo card' format from a config. The signature of this format is a |
| 4 | **continuously scrolling 2-row grid** (NOT a static card) under a fixed header (brand |
| 5 | wordmark + big headline + sub) and fixed feature chips. The grid-viewport scrolls left |
| 6 | across the whole ~10s, edge-faded with a CSS mask, and its tiles are **mixed media**: |
| 7 | `video` clips playing inside tiles, `band-product`/`photo` stills, big-serif `pct`/`off` |
| 8 | type tiles, and a dark `code` (promo code) or `cta` tile. |
| 9 | |
| 10 | The renderer itself is FREE/deterministic (Playwright frame-step + FFmpeg). The paid inputs |
| 11 | are separate capabilities: the tile **clips** come from `create-video-fal` (i2v of the |
| 12 | product heroes, or clips extracted from the brand's own ad corpus) and the **music** from |
| 13 | `create-music-elevenlabs`. Text (wordmark, %, code) is real DOM — never AI-rendered. |
| 14 | |
| 15 | ## Run |
| 16 | build_card.py --config config.json --out hyperframe.html ; render.py --config config.json --html hyperframe.html --out master-silent.mp4 — 1080x1920, scrolling grid, deterministic, $0. |
| 17 | |
| 18 | Clip tiles are driven by FRAME-SWAP, not `<video>`: `render.py` pre-extracts each clip to |
| 19 | PNG frames with ffmpeg, preloads them, and swaps each `<img class="vidframe">`'s src per |
| 20 | output frame. This is because Playwright's bundled Chromium can't decode `<video>` H.264 |
| 21 | over file:// (open-source build, no proprietary codecs) — it hangs on `canplay`. Letting |
| 22 | ffmpeg decode makes it codec-independent AND deterministic. Provide clips longer than the |
| 23 | master (or the swap just loops them); a subtle `setpts`-slow reads as cinematic. |
| 24 | |
| 25 | ## Contract |
| 26 | - Deterministic + FREE (Playwright frame-step + FFmpeg); no paid calls in this capability. |
| 27 | - Tiles-per-row = grid columns (`cols`), NOT total tiles; the grid fills row-major. |
| 28 | - The template recipe (DB) supplies the config; clips + music are separate capabilities. |