Create animated product vignettes — short, cinematic HTML demos that showcase a product feature or workflow using GSAP animations. Use this skill when asked to build a vignette, product theater animation, animated demo, product walkthrough, cinematic UI demo, or GSAP-based product showcase. Also use when asked to animate a UI scene, create a camera-driven demo, or build a beat-scripted animation sequence.
Build self-contained, single-file HTML vignettes that tell a visual story about a product feature using GSAP-powered camera moves, typing effects, and UI state transitions.
A vignette is a single HTML file containing:
The viewport is a fixed window (typically 1280×800) looking into an oversized scene. The animation zooms and pans the scene to draw attention to different areas.
┌─────────────────────────────────────────────┐
│ viewport (1280×800, overflow: hidden) │
│ ┌────────────────────────────────────────┐ │
│ │ scene (oversized, e.g. 1800×1100) │ │
│ │ ┌──────┬──────────┬────────┐ │ │
│ │ │ left │ center │ right │ │ │
│ │ │panel │ panel │ panel │ │ │
│ │ └──────┴──────────┴────────┘ │ │
│ └────────────────────────────────────────┘ │
│ caption bar (overlay at bottom) │
└─────────────────────────────────────────────┘
The scene uses CSS Grid for panel layout. GSAP animates x, y, and scale on the
scene element to create camera movements. At scale S, the viewport shows
(viewportWidth/S) × (viewportHeight/S) pixels of the scene.
Each vignette is a single self-contained HTML file. For complex vignettes, the animation script can be separated:
my-vignette/
├── brief.md # What the vignette shows (input from user)
├── demo.html # The vignette (HTML + CSS + JS in one file)
└── script.js # Optional: separated beat script (for data-driven approach)
Present the brief template from brief-template.md to the user and collaborate to fill it in. Each beat should capture:
The FRAME/ACTION/FEEL structure gives enough context to calculate camera positions and timing. Without it, camera movements will be guesswork. Ask the user to provide reference images for any beat where the visual content matters.
Build the static HTML/CSS scene first. The scene should look like a realistic product UI.
Key principles:
Use async/await with GSAP for the animation sequence. Core helpers:
// Camera move — animates scene transform
function cam(x, y, scale, dur = 1, ease = "power2.inOut") {
return new Promise(resolve => {
gsap.to("#scene", {
x: -x, y: -y, scale,
duration: dur, ease, transformOrigin: "top left",
onComplete: resolve
});
});
}
// Typewriter effect
function typeText(el, text, dur = 1.4) {
const chars = text.split("");
let i = 0;
el.textContent = "";
return new Promise(resolve => {
const interval = setInterval(() => {
el.textContent += chars[i++];
if (i >= chars.length) { clearInterval(interval); resolve(); }
}, (dur * 1000) / chars.length);
});
}
// Caption overlay
function caption(text) {
const bar = document.querySelector("#caption-bar");
const txt = document.querySelector("#caption-text");
if (!text) { bar.classList.remove("visible"); return; }
txt.textContent = text;
bar.classList.add("visible");
}
Camera position (x, y) is the top-left corner of what's visible in the viewport.
At scale S, the viewport shows (viewportW / S) × (viewportH / S) of the scene.
To show a specific region:
x = targetX - (viewportW / S) / 2 to center horizontally on targetXx = sceneWidth - viewportW / SviewportW / S ≥ sceneWidthDocument key positions as comments in the animation script.
Common animation beats:
| Beat | Pattern |
|---|---|
| Establish | cam(0, 0, fitScale) — show full scene |
| Focus | cam(panelX, panelY, 1.2-1.5) — zoom to area of interest |
| Type input | typeText(el, "user message", 2.0) then clear + send |
| Agent response | Show typing dots → replace with message bubble |
| State change | Toggle CSS classes, swap visible panels |
| Highlight | gsap.fromTo(el, { boxShadow: "0 0 0 0px rgba(...)" }, { boxShadow: "0 0 0 10px rgba(...,0)", repeat: 2 }) |
| Reveal | gsap.to(el, { opacity: 1, duration: 0.4 }) |
caption("") to dismissFor GSAP API details, eases, timeline positioning, and ScrollTrigger: see gsap-cheatsheet.md
Vignettes use the Sailwind design system for all visual decisions. The tokens file is the single source of truth — do not hardcode colors, fonts, spacing, or gradients.
Fetch the DTCG tokens file at the start of every vignette build: