
Turns a video file into a single-page site with a scroll-driven hero, the kind Apple uses for product launches. You scroll, the video scrubs forward frame by frame instead of playing on a timeline. It extracts 40 to 160 frames via ffmpeg depending on duration, builds a sticky canvas with a JavaScript scroll listener, and drops in headline sections and a CTA below. If you're working on a YUV.AI project it locks to Neon mode with pink and cyan; otherwise it picks a palette from the video itself. Output is one folder with an index.html and a frames directory, ready to drop on any static host. No build step, no dependencies, just scroll physics and a lot of JPEGs.
$ npx -y skills add hoodini/ai-agents-skills --skill video-to-landing-page --agent claude-codeInstalls into .claude/skills of the current project.
Build a cinematic landing page where the hero is a video playing on scroll instead of time — like Apple product pages or the GitHub Copilot landing. Frames are extracted from the source video and swapped as the user scrolls; below the sticky hero, normal-scroll sections carry copy and CTA.
Default: ~/Documents/yuv-projects/landings/<slug>/ — always save landing pages here so you can find them again. Create the parent directory if missing.
mkdir -p ~/Documents/yuv-projects/landings
cd ~/Documents/yuv-projects/landings
# Build <slug>/ here.
Final path: ~/Documents/yuv-projects/landings/<slug>/. Tell the user where the landing lives at the end of every build.
ffprobe for duration, fps, dimensions, audio.80. Floor 40 (choppy if lower), ceiling 160 (heavy page). Choose by duration: ≤10s → 50, 10–30s → 80, 30–60s → 120, >60s → 160.~/Documents/yuv-projects/landings/<slug>/. The <slug> is short, derived from the video name or the topic. Override only on explicit request.references/extract-frames.py <source-video> <output-dir> [count]. Outputs output-dir/frames/f_0001.jpg… with consistent JPG quality 82 and a max-width of 1920 (downscaled if source is larger).references/landing-template.html into output-dir/index.html:
__FRAMES__ placeholder with <img> tags for each frame (the build script does this for you when you pass --build-html).__HEADLINE__, __TAGLINE__, __CTA_TEXT__, __CTA_HREF__, sections.<html lang="he" dir="rtl"> and swap fonts to Rubik/Assistant (see references/design-notes.md).python -m http.server inside the output directory and open http://localhost:8000. Scroll feels buttery on a decent machine..scroll-stage height set in viewport units (default 600vh = scroll 5 screens to traverse all frames).position: sticky; top: 0; height: 100vh containing all frames absolutely positioned and hidden except the active one.progress = scrolledIntoStage / scrollableHeight clamped 0–1.idx = floor(progress * (N - 1)) — swap the .active class to that frame.requestAnimationFrame to keep 60fps.yuv-design-system and lock it to a mode by medium —
#FF1464) + neon cyan (#00E5FF) + white or rich black canvas. Anton + Inter (English) / Rubik + Assistant (Hebrew). 0px or 999px radii.#fff.border-radius: 999px) — pink fill in Neon mode, brand-appropriate color otherwise.| File | Purpose |
|---|---|
references/extract-frames.py | ffmpeg-based frame extractor; optionally builds the full HTML in one go |
references/landing-template.html | Self-contained landing-page skeleton with the scroll mechanic |
references/design-notes.md | Typography, palette, and motion defaults |
Sponsors