[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M751DR2P7V4D68S2ESNVGVB2":3,"skill-same:01M751DR2P7V4D68S2ESNVGVB2":49},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":26,"commitSha":27,"skillDirectory":28,"forksCount":29,"repositoryHtmlUrl":30,"repositoryHomepageUrl":31,"ownerHtmlUrl":32,"ownerBlogUrl":31,"ownerDescription":33,"updatedAt":34,"install":35,"resources":48},"01M751DR2P7V4D68S2ESNVGVB2","product-demo-director",null,"Direct the craft of putting a real software UI on screen - cursor choreography, zoom\u002Fpan\u002Fcallout language, screen-recording vs recreated UI, and making state changes legible with highlights, focus pulls, and slow-downs. Use when filming or recreating an app for a product demo, feature walkthrough, onboarding clip, or release reel and asking \"how do I show this click\", \"where should the camera zoom\", \"should I screen-record or rebuild the UI\", \"why does my demo feel confusing\", \"how do I make the state change readable\", or \"how do I move the cursor\". Do NOT use for easing and timing (use motion-design-principles), the beat plan (use video-storyboard), animated words (use kinetic-typography), highlight color and glow (use motion-color-and-light), sound (use sound-and-music-sync), reframing to 9:16 or 1:1 (use social-video-formatter), or building it in code (use remotion-compose and remotion-render).","SkillMedev\u002Fskills","SkillMedev","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F298078254?v=4","01M74ZSGTQ918CB0VXW4EG3RMX","SkillMe","01M74ZSGVBT497NA95CBT8JTY4",25,"MIT","https:\u002F\u002Fgithub.com\u002FSkillMedev\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fproduct-demo-director\u002FSKILL.md",[],[],"2026-11-11 18:13:29",false,"---\nname: product-demo-director\ndescription: \"Direct the craft of putting a real software UI on screen - cursor choreography, zoom\u002Fpan\u002Fcallout language, screen-recording vs recreated UI, and making state changes legible with highlights, focus pulls, and slow-downs. Use when filming or recreating an app for a product demo, feature walkthrough, onboarding clip, or release reel and asking \\\"how do I show this click\\\", \\\"where should the camera zoom\\\", \\\"should I screen-record or rebuild the UI\\\", \\\"why does my demo feel confusing\\\", \\\"how do I make the state change readable\\\", or \\\"how do I move the cursor\\\". Do NOT use for easing and timing (use motion-design-principles), the beat plan (use video-storyboard), animated words (use kinetic-typography), highlight color and glow (use motion-color-and-light), sound (use sound-and-music-sync), reframing to 9:16 or 1:1 (use social-video-formatter), or building it in code (use remotion-compose and remotion-render).\"\nmetadata:\n  title: \"Product Demo Director\"\n---\n\n# Product Demo Director\n\nYou direct the single hardest shot in software marketing: a real UI doing a real thing, in a way a stranger can follow on the first watch. The default failure is a raw screen recording at human speed - the cursor teleports, three things change at once, and the viewer never knows where to look. Your job is to choreograph attention: one change at a time, the camera pointed at it, held long enough to read.\n\nThis is the taste layer. The grammar of *how* things move (easing curves, anticipation, the 12 principles) lives in motion-design-principles; the beat list lives in video-storyboard; word animation lives in kinetic-typography. You decide *what the camera and cursor do over the UI* and hand the result down to those skills and to the build pack (remotion-compose, remotion-render).\n\nWork one example throughout: a 12-second clip showing a user turn on a feature flag in a settings dashboard and watch a metric tile light up.\n\n## Workflow\n\nRun these in order. Do not start choreographing the cursor before you have decided record-vs-rebuild - the decision changes everything downstream.\n\n### Step 1 - Decide: screen-record or recreate the UI\n\nThis is the fork. Pick before any other work.\n\n- **Screen-record** when the UI is real, stable, and the demo's credibility depends on \"this is the actual product.\" Fastest to capture; you trade away control. You cannot fix a janky cursor, a slow network spinner, real customer data, or a font that anti-aliases badly at zoom. Record at 2x the final resolution so you have room to push in without mush.\n- **Recreate the UI** (rebuild the relevant screens as components) when you need a clean cursor path, deterministic timing, fake-but-honest data, partial-product states that do not exist yet, or pixel-perfect zoom. More work; total control. This is the path that hands to remotion-compose, where each screen becomes a component and the cursor becomes an animated layer.\n- **Hybrid** (common and underused): screen-record the *texture* (real scrolling, real video playing inside the app), then composite recreated callouts, cursors, and highlights *on top* so the choreography is still authored. Use when the product is real but the raw recording is too messy to direct.\n\nWrite the decision down with its reason. See references\u002Frecord-vs-recreate for the full tradeoff table.\n\n### Step 2 - Reduce to one change per beat\n\nA demo is legible only if exactly one thing changes at a time and the viewer is looking at it when it does. List every state change in the flow (focus moves, a field fills, a toggle flips, a tile updates, a toast appears). If two happen on the same frame, you must either separate them in time or subordinate one (dim it, push it out of the zoom). \"Turn on the flag\" is not one beat - it is: cursor arrives at toggle → toggle flips → metric tile recomputes → confirmation toast. Four beats, four held reads.\n\n### Step 3 - Choreograph the cursor\n\nThe cursor is the narrator. Treat it like an actor, not a mouse log.\n\n1. **Move with intent, arc slightly.** Never teleport, never jitter. The cursor accelerates out of rest and decelerates into the target (ease-in-out - borrow the curve from motion-design-principles). A faint arc reads as more deliberate than a ruler-straight line.\n2. **Settle before acting.** Arrive, pause ~6-10 frames, *then* click. The pause is the \"I am about to do this\" beat the eye needs.\n3. **Show the click.** A real click is invisible. Add a visible affordance: a quick scale-down\u002Fup on the cursor, a radial ripple at the click point, or a brief press state on the target. One of these, not all three.\n4. **One cursor, one path.** If the flow needs the cursor in two places, cut - do not whip it across the frame. A hard cut reads cleaner than a 4-frame dash.\n5. **Retire the cursor when it is not the subject.** When a tile is updating and the cursor is just parked, fade it out or move it off the zoom. A static cursor competing with the real subject splits attention.\n\n### Step 4 - Direct the camera: zoom, pan, callout\n\nThe frame is a camera over the UI. Use a consistent move vocabulary so the viewer learns your language:\n\n- **Push in (zoom)** to commit to a region before the change happens - arrive at the toggle *before* it flips. The push is anticipation; the change is the payoff.\n- **Pan\u002Ftrack** to follow the cursor between two regions that are too far apart to hold in one frame. Keep pans slow and motivated by the cursor - the camera follows the actor.\n- **Pull out (zoom out)** to re-establish context after a detailed beat, so the viewer re-anchors before the next region.\n- **Callouts** (a highlight ring, a label, a connector line, a spotlight that dims everything else) point at the thing words would otherwise have to name. Prefer a callout over narration when the UI element is on screen.\n\nRule: the camera should already be looking at the element *before* it changes. If the toggle flips and *then* you zoom to it, you missed the moment.\n\n### Step 5 - Make the state change legible\n\nThe whole demo exists for the state changes. Each one gets deliberate treatment:\n\n- **Slow the world down on the key change.** Hold a normal pace through navigation, then stretch the actual flip\u002Fupdate to ~1.3-1.6x its real duration so the eye registers cause→effect. Speed-ramp back up after.\n- **Highlight the before\u002Fafter delta.** Pulse the changed element (a glow, a brief color wash, a scale bump). For a number changing, count it up rather than hard-cutting the value - the motion *is* the message.\n- **Pull focus.** When the metric tile updates, dim or blur everything else for ~10 frames so the tile is unambiguously the subject, then bring the room back.\n- **Sequence cause and effect with a beat between them.** Toggle flips (hold), *then* tile updates (hold). If they fire on the same frame the viewer cannot tell the toggle *caused* the tile.\n\n### Step 6 - Lint the shot list, then hand off\n\nRun the linter (below) on your beat list to catch the classic legibility failures - overlapping changes, missing holds, cursor teleports, a camera that arrives late. Fix every flag. Then hand the directed shot list down: timing\u002Feasing specifics to motion-design-principles, the beat ordering to video-storyboard, and the actual implementation (cursor layer, zoom transforms, component screens) to remotion-compose for build and remotion-render for the iterate loop.\n\n## Quality bar\n\nThe demo is A+ only when all hold:\n\n- The record-vs-recreate decision is written down with its reason, and the production honors it (no janky raw recording smuggled into a \"clean\" rebuild).\n- Exactly one change is the subject per beat; any simultaneous change is deliberately subordinated (dimmed or out of frame), never accidental.\n- Every click shows a visible affordance, and the cursor settles before it acts - no teleports, no jitter, no whip-pans.\n- The camera is already framed on each element *before* that element changes.\n- Every state change gets at least one legibility treatment (slow-down, highlight, focus pull, or count-up) and a held read after it.\n- The shot list passes the linter with zero flags.\n\n## Do NOT\n\n- Do not ship a raw, real-time screen recording as the demo - direct it, or it is footage, not a demo.\n- Do not let two state changes land on the same frame; the viewer cannot assign cause and effect.\n- Do not teleport, jitter, or whip-pan the cursor; if it must be in two places, cut.\n- Do not zoom to an element *after* it changes - the camera arrives first, always.\n- Do not narrate what a callout could point at on screen.\n- Do not specify exact easing curves or frame-by-frame timing here - that is motion-design-principles; do not write the beat order from scratch - that is video-storyboard; do not animate on-screen words here - that is kinetic-typography; do not write the React\u002FRemotion code or render - that is remotion-compose and remotion-render.\n\n## Linter\n\nSelf-contained Node script. Save as `demo_lint.js` and run with `node demo_lint.js`. No dependencies. Describe your demo as an ordered list of beats; the linter flags the classic legibility failures from the workflow. Edit the `beats` array for your demo.\n\n```javascript\n\u002F\u002F Product-demo shot-list linter. Run: node demo_lint.js\n\u002F\u002F Each beat is one moment on the timeline. Fields:\n\u002F\u002F   t          start time in seconds (ordered, ascending)\n\u002F\u002F   dur        how long the beat is held, in seconds\n\u002F\u002F   changes    UI state changes that happen on this beat (0, 1, or more)\n\u002F\u002F   camera     'push' | 'pan' | 'pull' | 'hold'  (camera move into this beat)\n\u002F\u002F   framedOn   the element the camera is pointed at when the beat starts\n\u002F\u002F   cursorTo   where the cursor moves this beat (null = stays \u002F not the subject)\n\u002F\u002F   click      true if a click happens this beat\n\u002F\u002F   clickAffordance  true if the click is made visible (ripple\u002Fpress\u002Fscale)\n\u002F\u002F   legibility 'slowdown' | 'highlight' | 'focuspull' | 'countup' | null\nconst beats = [\n  { t: 0.0, dur: 1.2, changes: [],               camera: 'push', framedOn: 'settings-panel', cursorTo: 'toggle',     click: false, clickAffordance: false, legibility: null },\n  { t: 1.2, dur: 0.5, changes: [],               camera: 'hold', framedOn: 'toggle',         cursorTo: null,         click: true,  clickAffordance: true,  legibility: null },\n  { t: 1.7, dur: 1.0, changes: ['toggle-on'],    camera: 'hold', framedOn: 'toggle',         cursorTo: null,         click: false, clickAffordance: false, legibility: 'slowdown' },\n  { t: 2.7, dur: 1.4, changes: ['tile-update'],  camera: 'pan',  framedOn: 'metric-tile',    cursorTo: null,         click: false, clickAffordance: false, legibility: 'countup' },\n  { t: 4.1, dur: 0.8, changes: ['toast','badge'],camera: 'hold', framedOn: 'metric-tile',    cursorTo: 'export-btn', click: false, clickAffordance: false, legibility: null },\n]\n\nconst HOLD_MIN = 0.4 \u002F\u002F a state change needs at least this long to read\nconst flags = []\nfor (let i = 0; i \u003C beats.length; i++) {\n  const b = beats[i]\n  const id = `beat ${i + 1} (t=${b.t}s)`\n  \u002F\u002F 1. One change per beat.\n  if (b.changes.length > 1)\n    flags.push(`${id}: ${b.changes.length} changes at once (${b.changes.join(', ')}) - split or subordinate all but one`)\n  \u002F\u002F 2. Every change gets a held read.\n  if (b.changes.length === 1 && b.dur \u003C HOLD_MIN)\n    flags.push(`${id}: change \"${b.changes[0]}\" held only ${b.dur}s - hold >= ${HOLD_MIN}s so it reads`)\n  \u002F\u002F 3. Every change gets a legibility treatment.\n  if (b.changes.length >= 1 && !b.legibility)\n    flags.push(`${id}: change \"${b.changes[0]}\" has no legibility treatment (slowdown\u002Fhighlight\u002Ffocuspull\u002Fcountup)`)\n  \u002F\u002F 4. Clicks must be visible.\n  if (b.click && !b.clickAffordance)\n    flags.push(`${id}: click has no visible affordance - add a ripple\u002Fpress\u002Fscale`)\n  \u002F\u002F 5. Camera frames the element BEFORE it changes, not on the change beat.\n  if (b.changes.length >= 1 && (b.camera === 'push' || b.camera === 'pan'))\n    flags.push(`${id}: camera moves (${b.camera}) on the same beat the change happens - arrive first, change second`)\n  \u002F\u002F 6. No cursor teleport: a click beat whose cursor just arrived has no settle.\n  if (b.click && b.cursorTo)\n    flags.push(`${id}: cursor moves AND clicks on the same beat - settle (~6-10 frames) before clicking`)\n}\n\nif (flags.length === 0) console.log('PASS - shot list is legible.')\nelse {\n  console.log(`${flags.length} flag(s):`)\n  for (const f of flags) console.log('  - ' + f)\n}\n```\n\n### Worked example output\n\nWith the beats above the script prints:\n\n```\n3 flag(s):\n  - beat 4 (t=2.7s): camera moves (pan) on the same beat the change happens - arrive first, change second\n  - beat 5 (t=4.1s): 2 changes at once (toast, badge) - split or subordinate all but one\n  - beat 5 (t=4.1s): change \"toast\" has no legibility treatment (slowdown\u002Fhighlight\u002Ffocuspull\u002Fcountup)\n```\n\nRead it: the toggle click (beats 2-3) is clean - the cursor settles, the click has a ripple, the flip is slowed down and held. But beat 4 pans to the metric tile *while* it updates, so the camera arrives late on the payoff; fix it by panning during beat 3's hold so the tile is framed before it recomputes. And beat 5 is doing two wrong things at once: it fires a toast *and* a badge on the same frame, and the toast has no legibility treatment. Subordinate the badge (dim it, or push it outside the zoom) so the toast is the single subject, and give the toast a highlight or hold. Fix all three and the linter passes.\n\n## Template: demo-shot-card\n\nCopy this, fill the FILL fields, and feed the result to the linter, then down to the sibling skills.\n\n```\nPRODUCT DEMO SHOT CARD. [FILL: feature name] - [FILL: length]s\n\nPRODUCTION DECISION\n  Record \u002F Recreate \u002F Hybrid:   [FILL]\n  Reason:                       [FILL: why this path]\n  Capture resolution:           [FILL: 2x final if recording]\n\nSUBJECT OF THE CLIP (one sentence the viewer should take away)\n  [FILL]\n\nBEAT SHEET (one change per row; camera arrives before the change)\n  #  TIME   CAMERA   FRAMED ON        CURSOR          CHANGE            LEGIBILITY        HOLD\n  1  [FILL] [push]   [FILL]           [moves to FILL] -                 -                 [FILL]s\n  2  [FILL] [hold]   [FILL]           [settles+click] -                 -                 [FILL]s\n  3  [FILL] [hold]   [FILL]           [parked\u002Ffade]   [FILL: the flip]  [slowdown]        [FILL]s\n  4  [FILL] [pan]    [FILL]           [off-frame]     [FILL: the effect][countup\u002Fglow]    [FILL]s\n  (add rows; never two changes in one row)\n\nCALLOUT LANGUAGE (kept consistent across the clip)\n  Highlight style:              [FILL: ring \u002F spotlight-dim \u002F connector]\n  Click affordance:             [FILL: ripple \u002F press \u002F cursor-scale]\n  Focus-pull treatment:         [FILL: dim others \u002F blur others]\n\nHANDOFF\n  Easing + timing detail ->     motion-design-principles\n  Beat order \u002F story arc ->     video-storyboard\n  On-screen words ->            kinetic-typography\n  Color + light of highlights ->motion-color-and-light\n  Sound design \u002F hit on click ->sound-and-music-sync\n  Reframe for 9:16 \u002F 1:1 ->     social-video-formatter\n  Build (screens, cursor, zoom)->remotion-compose, then remotion-render\n```\n\n## references\u002Frecord-vs-recreate\n\n| Dimension | Screen-record | Recreate the UI |\n|---|---|---|\n| Setup cost | Low - capture the real app | High - rebuild screens as components |\n| Cursor control | None (real mouse path) | Total (animated cursor layer) |\n| Timing control | None (real latency, spinners) | Deterministic per-frame |\n| Data | Real (may need redaction) | Fake-but-honest, fully chosen |\n| Zoom quality | Limited by capture res | Pixel-perfect at any zoom |\n| Credibility | \"This is the real product\" | Needs to look real to be honest |\n| States you don't have yet | Impossible | Easy (mock the future state) |\n| Best for | Stable, shippable, credibility-critical | Pre-launch, messy UI, control-critical |\n\nThe honesty line: a recreated UI must represent behavior the product actually has (or will have at ship). Never recreate a state the product cannot reach - that is a fabricated demo, not a directed one. When in doubt, hybrid: record the real texture, author the choreography on top.\n\n## references\u002Flegibility-toolkit\n\nThe five moves that make a state change readable, fastest to reach for first:\n\n1. **Hold.** Do nothing but keep the camera on the change for a beat. The cheapest legibility tool and the most skipped.\n2. **Slow-down.** Stretch the key transition to ~1.3-1.6x real duration; speed-ramp the boring parts to compensate so total length holds.\n3. **Focus pull.** Dim or blur everything that is not the subject for ~10 frames. Forces the eye; relax it back so the viewer re-anchors.\n4. **Highlight the delta.** Pulse\u002Fglow the changed element, or count a number up instead of cutting it. Animate the *difference*, not just the end state.\n5. **Cause→effect spacing.** Put a beat between the trigger and its result so the viewer can attribute one to the other. Simultaneous = ambiguous.\n\nLayer at most two of these on any single change. More than two competes with itself and the change stops reading - the exact problem you were solving.\n","# Product Demo Director\n\nYou direct the single hardest shot in software marketing: a real UI doing a real thing, in a way a stranger can follow on the first watch. The default failure is a raw screen recording at human speed - the cursor teleports, three things change at once, and the viewer never knows where to look. Your job is to choreograph attention: one change at a time, the camera pointed at it, held long enough to read.\n\nThis is the taste layer. The grammar of *how* things move (easing curves, anticipation, the 12 principles) lives in motion-design-principles; the beat list lives in video-storyboard; word animation lives in kinetic-typography. You decide *what the camera and cursor do over the UI* and hand the result down to those skills and to the build pack (remotion-compose, remotion-render).\n\nWork one example throughout: a 12-second clip showing a user turn on a feature flag in a settings dashboard and watch a metric tile light up.\n\n## Workflow\n\nRun these in order. Do not start choreographing the cursor before you have decided record-vs-rebuild - the decision changes everything downstream.\n\n### Step 1 - Decide: screen-record or recreate the UI\n\nThis is the fork. Pick before any other work.\n\n- **Screen-record** when the UI is real, stable, and the demo's credibility depends on \"this is the actual product.\" Fastest to capture; you trade away control. You cannot fix a janky cursor, a slow network spinner, real customer data, or a font that anti-aliases badly at zoom. Record at 2x the final resolution so you have room to push in without mush.\n- **Recreate the UI** (rebuild the relevant screens as components) when you need a clean cursor path, deterministic timing, fake-but-honest data, partial-product states that do not exist yet, or pixel-perfect zoom. More work; total control. This is the path that hands to remotion-compose, where each screen becomes a component and the cursor becomes an animated layer.\n- **Hybrid** (common and underused): screen-record the *texture* (real scrolling, real video playing inside the app), then composite recreated callouts, cursors, and highlights *on top* so the choreography is still authored. Use when the product is real but the raw recording is too messy to direct.\n\nWrite the decision down with its reason. See references\u002Frecord-vs-recreate for the full tradeoff table.\n\n### Step 2 - Reduce to one change per beat\n\nA demo is legible only if exactly one thing changes at a time and the viewer is looking at it when it does. List every state change in the flow (focus moves, a field fills, a toggle flips, a tile updates, a toast appears). If two happen on the same frame, you must either separate them in time or subordinate one (dim it, push it out of the zoom). \"Turn on the flag\" is not one beat - it is: cursor arrives at toggle → toggle flips → metric tile recomputes → confirmation toast. Four beats, four held reads.\n\n### Step 3 - Choreograph the cursor\n\nThe cursor is the narrator. Treat it like an actor, not a mouse log.\n\n1. **Move with intent, arc slightly.** Never teleport, never jitter. The cursor accelerates out of rest and decelerates into the target (ease-in-out - borrow the curve from motion-design-principles). A faint arc reads as more deliberate than a ruler-straight line.\n2. **Settle before acting.** Arrive, pause ~6-10 frames, *then* click. The pause is the \"I am about to do this\" beat the eye needs.\n3. **Show the click.** A real click is invisible. Add a visible affordance: a quick scale-down\u002Fup on the cursor, a radial ripple at the click point, or a brief press state on the target. One of these, not all three.\n4. **One cursor, one path.** If the flow needs the cursor in two places, cut - do not whip it across the frame. A hard cut reads cleaner than a 4-frame dash.\n5. **Retire the cursor when it is not the subject.** When a tile is updating and the cursor is just parked, fade it out or move it off the zoom. A static cursor competing with the real subject splits attention.\n\n### Step 4 - Direct the camera: zoom, pan, callout\n\nThe frame is a camera over the UI. Use a consistent move vocabulary so the viewer learns your language:\n\n- **Push in (zoom)** to commit to a region before the change happens - arrive at the toggle *before* it flips. The push is anticipation; the change is the payoff.\n- **Pan\u002Ftrack** to follow the cursor between two regions that are too far apart to hold in one frame. Keep pans slow and motivated by the cursor - the camera follows the actor.\n- **Pull out (zoom out)** to re-establish context after a detailed beat, so the viewer re-anchors before the next region.\n- **Callouts** (a highlight ring, a label, a connector line, a spotlight that dims everything else) point at the thing words would otherwise have to name. Prefer a callout over narration when the UI element is on screen.\n\nRule: the camera should already be looking at the element *before* it changes. If the toggle flips and *then* you zoom to it, you missed the moment.\n\n### Step 5 - Make the state change legible\n\nThe whole demo exists for the state changes. Each one gets deliberate treatment:\n\n- **Slow the world down on the key change.** Hold a normal pace through navigation, then stretch the actual flip\u002Fupdate to ~1.3-1.6x its real duration so the eye registers cause→effect. Speed-ramp back up after.\n- **Highlight the before\u002Fafter delta.** Pulse the changed element (a glow, a brief color wash, a scale bump). For a number changing, count it up rather than hard-cutting the value - the motion *is* the message.\n- **Pull focus.** When the metric tile updates, dim or blur everything else for ~10 frames so the tile is unambiguously the subject, then bring the room back.\n- **Sequence cause and effect with a beat between them.** Toggle flips (hold), *then* tile updates (hold). If they fire on the same frame the viewer cannot tell the toggle *caused* the tile.\n\n### Step 6 - Lint the shot list, then hand off\n\nRun the linter (below) on your beat list to catch the classic legibility failures - overlapping changes, missing holds, cursor teleports, a camera that arrives late. Fix every flag. Then hand the directed shot list down: timing\u002Feasing specifics to motion-design-principles, the beat ordering to video-storyboard, and the actual implementation (cursor layer, zoom transforms, component screens) to remotion-compose for build and remotion-render for the iterate loop.\n\n## Quality bar\n\nThe demo is A+ only when all hold:\n\n- The record-vs-recreate decision is written down with its reason, and the production honors it (no janky raw recording smuggled into a \"clean\" rebuild).\n- Exactly one change is the subject per beat; any simultaneous change is deliberately subordinated (dimmed or out of frame), never accidental.\n- Every click shows a visible affordance, and the cursor settles before it acts - no teleports, no jitter, no whip-pans.\n- The camera is already framed on each element *before* that element changes.\n- Every state change gets at least one legibility treatment (slow-down, highlight, focus pull, or count-up) and a held read after it.\n- The shot list passes the linter with zero flags.\n\n## Do NOT\n\n- Do not ship a raw, real-time screen recording as the demo - direct it, or it is footage, not a demo.\n- Do not let two state changes land on the same frame; the viewer cannot assign cause and effect.\n- Do not teleport, jitter, or whip-pan the cursor; if it must be in two places, cut.\n- Do not zoom to an element *after* it changes - the camera arrives first, always.\n- Do not narrate what a callout could point at on screen.\n- Do not specify exact easing curves or frame-by-frame timing here - that is motion-design-principles; do not write the beat order from scratch - that is video-storyboard; do not animate on-screen words here - that is kinetic-typography; do not write the React\u002FRemotion code or render - that is remotion-compose and remotion-render.\n\n## Linter\n\nSelf-contained Node script. Save as `demo_lint.js` and run with `node demo_lint.js`. No dependencies. Describe your demo as an ordered list of beats; the linter flags the classic legibility failures from the workflow. Edit the `beats` array for your demo.\n\n```javascript\n\u002F\u002F Product-demo shot-list linter. Run: node demo_lint.js\n\u002F\u002F Each beat is one moment on the timeline. Fields:\n\u002F\u002F   t          start time in seconds (ordered, ascending)\n\u002F\u002F   dur        how long the beat is held, in seconds\n\u002F\u002F   changes    UI state changes that happen on this beat (0, 1, or more)\n\u002F\u002F   camera     'push' | 'pan' | 'pull' | 'hold'  (camera move into this beat)\n\u002F\u002F   framedOn   the element the camera is pointed at when the beat starts\n\u002F\u002F   cursorTo   where the cursor moves this beat (null = stays \u002F not the subject)\n\u002F\u002F   click      true if a click happens this beat\n\u002F\u002F   clickAffordance  true if the click is made visible (ripple\u002Fpress\u002Fscale)\n\u002F\u002F   legibility 'slowdown' | 'highlight' | 'focuspull' | 'countup' | null\nconst beats = [\n  { t: 0.0, dur: 1.2, changes: [],               camera: 'push', framedOn: 'settings-panel', cursorTo: 'toggle',     click: false, clickAffordance: false, legibility: null },\n  { t: 1.2, dur: 0.5, changes: [],               camera: 'hold', framedOn: 'toggle',         cursorTo: null,         click: true,  clickAffordance: true,  legibility: null },\n  { t: 1.7, dur: 1.0, changes: ['toggle-on'],    camera: 'hold', framedOn: 'toggle',         cursorTo: null,         click: false, clickAffordance: false, legibility: 'slowdown' },\n  { t: 2.7, dur: 1.4, changes: ['tile-update'],  camera: 'pan',  framedOn: 'metric-tile',    cursorTo: null,         click: false, clickAffordance: false, legibility: 'countup' },\n  { t: 4.1, dur: 0.8, changes: ['toast','badge'],camera: 'hold', framedOn: 'metric-tile',    cursorTo: 'export-btn', click: false, clickAffordance: false, legibility: null },\n]\n\nconst HOLD_MIN = 0.4 \u002F\u002F a state change needs at least this long to read\nconst flags = []\nfor (let i = 0; i \u003C beats.length; i++) {\n  const b = beats[i]\n  const id = `beat ${i + 1} (t=${b.t}s)`\n  \u002F\u002F 1. One change per beat.\n  if (b.changes.length > 1)\n    flags.push(`${id}: ${b.changes.length} changes at once (${b.changes.join(', ')}) - split or subordinate all but one`)\n  \u002F\u002F 2. Every change gets a held read.\n  if (b.changes.length === 1 && b.dur \u003C HOLD_MIN)\n    flags.push(`${id}: change \"${b.changes[0]}\" held only ${b.dur}s - hold >= ${HOLD_MIN}s so it reads`)\n  \u002F\u002F 3. Every change gets a legibility treatment.\n  if (b.changes.length >= 1 && !b.legibility)\n    flags.push(`${id}: change \"${b.changes[0]}\" has no legibility treatment (slowdown\u002Fhighlight\u002Ffocuspull\u002Fcountup)`)\n  \u002F\u002F 4. Clicks must be visible.\n  if (b.click && !b.clickAffordance)\n    flags.push(`${id}: click has no visible affordance - add a ripple\u002Fpress\u002Fscale`)\n  \u002F\u002F 5. Camera frames the element BEFORE it changes, not on the change beat.\n  if (b.changes.length >= 1 && (b.camera === 'push' || b.camera === 'pan'))\n    flags.push(`${id}: camera moves (${b.camera}) on the same beat the change happens - arrive first, change second`)\n  \u002F\u002F 6. No cursor teleport: a click beat whose cursor just arrived has no settle.\n  if (b.click && b.cursorTo)\n    flags.push(`${id}: cursor moves AND clicks on the same beat - settle (~6-10 frames) before clicking`)\n}\n\nif (flags.length === 0) console.log('PASS - shot list is legible.')\nelse {\n  console.log(`${flags.length} flag(s):`)\n  for (const f of flags) console.log('  - ' + f)\n}\n```\n\n### Worked example output\n\nWith the beats above the script prints:\n\n```\n3 flag(s):\n  - beat 4 (t=2.7s): camera moves (pan) on the same beat the change happens - arrive first, change second\n  - beat 5 (t=4.1s): 2 changes at once (toast, badge) - split or subordinate all but one\n  - beat 5 (t=4.1s): change \"toast\" has no legibility treatment (slowdown\u002Fhighlight\u002Ffocuspull\u002Fcountup)\n```\n\nRead it: the toggle click (beats 2-3) is clean - the cursor settles, the click has a ripple, the flip is slowed down and held. But beat 4 pans to the metric tile *while* it updates, so the camera arrives late on the payoff; fix it by panning during beat 3's hold so the tile is framed before it recomputes. And beat 5 is doing two wrong things at once: it fires a toast *and* a badge on the same frame, and the toast has no legibility treatment. Subordinate the badge (dim it, or push it outside the zoom) so the toast is the single subject, and give the toast a highlight or hold. Fix all three and the linter passes.\n\n## Template: demo-shot-card\n\nCopy this, fill the FILL fields, and feed the result to the linter, then down to the sibling skills.\n\n```\nPRODUCT DEMO SHOT CARD. [FILL: feature name] - [FILL: length]s\n\nPRODUCTION DECISION\n  Record \u002F Recreate \u002F Hybrid:   [FILL]\n  Reason:                       [FILL: why this path]\n  Capture resolution:           [FILL: 2x final if recording]\n\nSUBJECT OF THE CLIP (one sentence the viewer should take away)\n  [FILL]\n\nBEAT SHEET (one change per row; camera arrives before the change)\n  #  TIME   CAMERA   FRAMED ON        CURSOR          CHANGE            LEGIBILITY        HOLD\n  1  [FILL] [push]   [FILL]           [moves to FILL] -                 -                 [FILL]s\n  2  [FILL] [hold]   [FILL]           [settles+click] -                 -                 [FILL]s\n  3  [FILL] [hold]   [FILL]           [parked\u002Ffade]   [FILL: the flip]  [slowdown]        [FILL]s\n  4  [FILL] [pan]    [FILL]           [off-frame]     [FILL: the effect][countup\u002Fglow]    [FILL]s\n  (add rows; never two changes in one row)\n\nCALLOUT LANGUAGE (kept consistent across the clip)\n  Highlight style:              [FILL: ring \u002F spotlight-dim \u002F connector]\n  Click affordance:             [FILL: ripple \u002F press \u002F cursor-scale]\n  Focus-pull treatment:         [FILL: dim others \u002F blur others]\n\nHANDOFF\n  Easing + timing detail ->     motion-design-principles\n  Beat order \u002F story arc ->     video-storyboard\n  On-screen words ->            kinetic-typography\n  Color + light of highlights ->motion-color-and-light\n  Sound design \u002F hit on click ->sound-and-music-sync\n  Reframe for 9:16 \u002F 1:1 ->     social-video-formatter\n  Build (screens, cursor, zoom)->remotion-compose, then remotion-render\n```\n\n## references\u002Frecord-vs-recreate\n\n| Dimension | Screen-record | Recreate the UI |\n|---|---|---|\n| Setup cost | Low - capture the real app | High - rebuild screens as components |\n| Cursor control | None (real mouse path) | Total (animated cursor layer) |\n| Timing control | None (real latency, spinners) | Deterministic per-frame |\n| Data | Real (may need redaction) | Fake-but-honest, fully chosen |\n| Zoom quality | Limited by capture res | Pixel-perfect at any zoom |\n| Credibility | \"This is the real product\" | Needs to look real to be honest |\n| States you don't have yet | Impossible | Easy (mock the future state) |\n| Best for | Stable, shippable, credibility-critical | Pre-launch, messy UI, control-critical |\n\nThe honesty line: a recreated UI must represent behavior the product actually has (or will have at ship). Never recreate a state the product cannot reach - that is a fabricated demo, not a directed one. When in doubt, hybrid: record the real texture, author the choreography on top.\n\n## references\u002Flegibility-toolkit\n\nThe five moves that make a state change readable, fastest to reach for first:\n\n1. **Hold.** Do nothing but keep the camera on the change for a beat. The cheapest legibility tool and the most skipped.\n2. **Slow-down.** Stretch the key transition to ~1.3-1.6x real duration; speed-ramp the boring parts to compensate so total length holds.\n3. **Focus pull.** Dim or blur everything that is not the subject for ~10 frames. Forces the eye; relax it back so the viewer re-anchors.\n4. **Highlight the delta.** Pulse\u002Fglow the changed element, or count a number up instead of cutting it. Animate the *difference*, not just the end state.\n5. **Cause→effect spacing.** Put a beat between the trigger and its result so the viewer can attribute one to the other. Simultaneous = ambiguous.\n\nLayer at most two of these on any single change. More than two competes with itself and the change stops reading - the exact problem you were solving.\n",{"name":5,"metadata":24,"description":7},{"title":25},"Product Demo Director","main","97a13607d669157a4a16d5ba79b77f208319f7b9","skills\u002Fproduct-demo-director",3,"https:\u002F\u002Fgithub.com\u002FSkillMedev\u002Fskills","https:\u002F\u002Fskillme.dev","https:\u002F\u002Fgithub.com\u002FSkillMedev","MCP-native catalog of Claude Agent Skills. Browse, recommend, install, and auto-apply skills in chat. Open source, every skill free and clonable on GitHub.","2026-10-14 03:19:31",{"source":8,"skillName":5,"commands":36,"prompt":46,"zipAvailable":47},[37,40,43],{"tool":38,"command":39},"npx","npx skills add SkillMedev\u002Fskills --skill product-demo-director",{"tool":41,"command":42},"bunx","bunx skills add SkillMedev\u002Fskills --skill product-demo-director",{"tool":44,"command":45},"pnpm","pnpm dlx skills add SkillMedev\u002Fskills --skill product-demo-director","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FSkillMedev\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fproduct-demo-director\u002FSKILL.md",true,[],[50,58,65,72,79,86],{"skillNo":51,"name":52,"nameZh":6,"description":53,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":54,"categories":55,"keywords":56,"publishedAt":57},"01M75271B256DF3FX2VG5VRYEE","zone-2-cardio-plan","Use when someone asks to build a steady-state cardio plan, train an aerobic base or Zone 2, structure easy or endurance weekly cardio, train by heart-rate zones, or improve resting heart rate, VO2, or endurance. Builds a heart-rate-zone aerobic training block with session structure, modality choice, and progression. General fitness guidance, not medical advice. Do NOT use to design a strength or lifting program (use Strength Training Plan), high-intensity interval conditioning, HIIT, or circuits (use Conditioning & HIIT Program), or a mobility\u002Fflexibility routine (use Mobility Routine).","https:\u002F\u002Fgithub.com\u002FSkillMedev\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzone-2-cardio-plan\u002FSKILL.md",[],[],"2026-11-11 18:27:18",{"skillNo":59,"name":60,"nameZh":6,"description":61,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":62,"categories":63,"keywords":64,"publishedAt":57},"01M7526VP1QBBKYBE17S1WR86Y","youtube-script-writer","Writes retention-engineered long-form YouTube scripts on a hook\u002Fbody\u002Fpayoff architecture - a first-30-seconds hook that survives the retention cliff, a beat-sheet body with mini-hooks and bridges, timed pattern interrupts, and a payoff that over-delivers - with B-roll and editing cues marked inline. Use when someone says \"script my next video\", \"my retention graph dies at the start\", \"tighten this draft\", or \"outline a video on X\". Do NOT use for the 3-second opener of TikTok, Reels, or Shorts - use video-hook-writer instead; do NOT use for spoken voiceover synced to on-screen tutorial actions - use narration-script instead; do NOT use for a sales demo built on a buyer's discovery notes - use demo-script instead; do NOT use to design the thumbnail and title - use thumbnail-concept instead.","https:\u002F\u002Fgithub.com\u002FSkillMedev\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fyoutube-script-writer\u002FSKILL.md",[],[],{"skillNo":66,"name":67,"nameZh":6,"description":68,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":69,"categories":70,"keywords":71,"publishedAt":57},"01M7526P2T0WKMHDXS4Q58237T","win-back-campaign","Designs segmented win-back email sequences for dormant users - dormancy tiers, a three-beat sequence with a single proportional incentive, and a suppression rule - and measures success by re-activation, not opens. Use when someone says \"our users went quiet\", \"design a win-back campaign\", \"how do I re-engage lapsed customers\", \"should we email people who haven't logged in for months\", or lifecycle messaging has stopped landing with a lapsed segment. Do NOT use for recovering an unfinished checkout - use abandoned-cart-sequence instead. Do NOT use for diagnosing and fixing why active customers cancel - use churn-reduction instead. Do NOT use for building always-on onboarding or nurture flows - use email-drip-builder instead.","https:\u002F\u002Fgithub.com\u002FSkillMedev\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fwin-back-campaign\u002FSKILL.md",[],[],{"skillNo":73,"name":74,"nameZh":6,"description":75,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":76,"categories":77,"keywords":78,"publishedAt":57},"01M7526HF2RCDJ50P93WRZRHVV","wikipedia-style","Writes neutral, verifiable, encyclopedic prose following Wikipedia's core content policies and manual of style - NPOV, inline citations, notability-backed claims, and a strict ban on promotional language. Use when someone asks \"write this like a Wikipedia article\", \"draft a Wikipedia page for this company or person\", \"make this neutral and encyclopedic\", or \"why does my article draft keep getting rejected\". Do NOT use for persuasive or opinion writing - use op-ed-writer instead; for thesis-driven academic papers, use academic-essay; for verifying claims in existing text, use fact-checker.","https:\u002F\u002Fgithub.com\u002FSkillMedev\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fwikipedia-style\u002FSKILL.md",[],[],{"skillNo":80,"name":81,"nameZh":6,"description":82,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":83,"categories":84,"keywords":85,"publishedAt":57},"01M7526D43CTGRKGKNQ2GB0KVX","whitepapers","Structures and writes authoritative B2B whitepapers - a standalone executive summary, a data-sized problem statement, methodology, evidence-driven findings, recommendations, and a soft call to action - flagging every claim that needs a real citation. Use when a marketer asks \"write a whitepaper on this topic\", \"turn our research into a lead-gen asset\", \"make this credible enough for executives\", or a draft reads like a product pitch instead of analysis. Do NOT use for customer-story-driven proof - use case-study-builder instead; for policy audiences, use policy-brief.","https:\u002F\u002Fgithub.com\u002FSkillMedev\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fwhitepapers\u002FSKILL.md",[],[],{"skillNo":87,"name":88,"nameZh":6,"description":89,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":90,"categories":91,"keywords":92,"publishedAt":57},"01M75268423Y3K50SY5WC2NX2G","white-space-analysis","Finds unmet market gaps by ranking jobs-to-be-done on importance versus satisfaction, overlaying them against current solutions and workarounds, and validating that each gap is real, winnable, and worth winning. Use when someone asks \"where are the gaps in this market\", \"what's underserved here\", \"where should we play next\", or is hunting for product, feature, or market-entry opportunities. Do NOT use for profiling competitors and building battle cards - use competitive-intelligence instead; for putting a dollar figure on an identified opportunity - use market-sizing instead; for extracting jobs-to-be-done from raw customer interviews - use jtbd-extractor instead.","https:\u002F\u002Fgithub.com\u002FSkillMedev\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fwhite-space-analysis\u002FSKILL.md",[],[]]