--- name: duo description: > Composite any two HTML screens into a locked photo plate of hands holding an open foldable phone — a 1448×1086 still with two blank 495×849 / 498×849 screen slots (left and right) — to make side-by-side meme and comparison videos: TikTok vs Reels, ChatGPT vs Claude, "me vs my friend", before/after, two apps racing. Trigger on: "foldable phone meme", "put X on the left screen and Y on the right", "two-screen comparison video", "the dual-screen phone meme", or any request that names two apps/feeds/chats to show at once. The plate, geometry, and camera are finished — the agent only authors what plays INSIDE the two screens and renders. --- # Duo One fixed 1448×1086 @ 30fps composition: a photo of two hands holding an open foldable, with both screens blanked. You fill the two screen slots with HTML (live video, a mock chat, a scrolling feed, anything HyperFrames renders) and the rig masks it to the phone's true rounded-corner geometry. ![plate](assets/plate-preview.jpg) **The phone and hands are a photograph, not something you build.** `assets/plate.png` IS the device. Never recreate, redraw, or CSS-model the foldable, its bezel, the hinge, or the hands, and never substitute a different image. `build.mjs` copies the plate into every project; if it is missing, stop and reinstall the skill rather than improvising a phone. **Do not edit the rig.** The two `.screen` rects, their corner radii and the hinge divider were measured from that photo pixel by pixel. Every visual change you make happens inside `#screen-left .content` and `#screen-right .content`, plus the one shared GSAP timeline. ## When to use / when not to - Use for any "two things side by side on a phone" beat: app vs app, feed vs feed, two chats answering the same prompt, two versions of a product. - Do not use when the user wants a single phone, a laptop, or a real device bezel they supply — this skill is one specific photo. For a different device plate you would re-measure geometry the same way (see `references/screen-geometry.md`) rather than stretch this one. ## Requirements - Node 18+ and the HyperFrames CLI via `npx hyperframes@latest` (`@latest` is mutable; pin a version for byte-identical re-renders). - Load your motion doctrine first if your workspace has one. The rig's only built-in motion is one slow camera push; everything inside the screens must perform (scrolls, swipes, typing, taps), never idle-wobble. ## Network and side effects (complete list) - `registry.npmjs.org` — the HyperFrames CLI itself, via `npx`. - `cdn.jsdelivr.net` — the composition loads GSAP (pinned `3.14.2`) at preview/render time. Rendering is not fully offline. - Anything YOU add to the screens (video clips, avatars, fonts) is your side effect: fetching a site, downloading media, or scraping UI happens only if the user's request calls for real content, and only from sources they are entitled to use. `references/sourcing-real-ui.md` documents how, and the rights caveat. No credentials, no paid operations, no telemetry. `build.mjs` writes only inside `--out` and refuses to write through symlinks. ## Flow `` is this skill's installed directory (e.g. `~/.claude/skills/duo`). 1. **Scaffold** a project: ```bash node /scripts/build.mjs --out ./foldable-meme --duration 10 --icons tiktok,instagram ``` `--icons` is optional; it copies the real TikTok / Instagram glyph sheets (`assets/icons-*.svg`, extracted from the live mobile sites) into the project. 2. **Decide what each screen does** for the length of the clip, in writing, before touching HTML. The pause test: at any second, something inside at least one screen must be mid-motion (a swipe landing, a video playing, text arriving). Two static screenshots is not a video. 3. **Author the screens.** Inside each `.content` you have a normal DOM viewport: left `495×849`, right `498×849`. Position against those, never the root. Patterns (full-screen snap feed, drag→fling swipe, like-tap, chat typing) are in `references/feed-recipes.md`. Rules: - `