[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-figma-figma-use-motion":3,"mdc-5fo1s3-key":34,"related-org-figma-figma-use-motion":946,"related-repo-figma-figma-use-motion":1110},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":23,"repoUrl":24,"updatedAt":25,"license":26,"forks":27,"topics":28,"repo":29,"sourceUrl":32,"mdContent":33},"figma-use-motion","animate Figma nodes with motion tools","Motion \u002F animation context for the `use_figma` MCP tool — animating Figma nodes via manual keyframes, animation styles, easing, and timeline duration. Load alongside figma-use whenever a task involves adding, editing, or inspecting animation on a node.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"figma","Figma","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Ffigma.png",[12,16,19,20],{"name":13,"slug":14,"type":15},"MCP","mcp","tag",{"name":17,"slug":18,"type":15},"Animation","animation",{"name":9,"slug":8,"type":15},{"name":21,"slug":22,"type":15},"Design","design",1805,"https:\u002F\u002Fgithub.com\u002Ffigma\u002Fmcp-server-guide","2026-06-25T07:13:12.398176",null,164,[],{"repoUrl":24,"stars":23,"forks":27,"topics":30,"description":31},[],"A guide on how to use the Figma MCP server","https:\u002F\u002Fgithub.com\u002Ffigma\u002Fmcp-server-guide\u002Ftree\u002FHEAD\u002Fskills\u002Ffigma-use-motion","---\nname: figma-use-motion\ndescription: \"Motion \u002F animation context for the `use_figma` MCP tool — animating Figma nodes via manual keyframes, animation styles, easing, and timeline duration. Load alongside figma-use whenever a task involves adding, editing, or inspecting animation on a node.\"\ndisable-model-invocation: false\n---\n\n# use_figma — Figma Plugin API Skill for Motion\n\nMotion context for the `use_figma` MCP tool. [figma-use](..\u002Ffigma-use\u002FSKILL.md) covers the foundational Plugin API rules — load both together.\n\n**Always pass `skillNames: \"figma-use-motion\"` (comma-separated alongside `figma-use`) when calling `use_figma` for motion work.** Logging only.\n\n## Runtime Gating\n\nMotion APIs are gated behind the `metronome` user feature flag. When the calling user doesn't have it, every motion property and helper referenced in this skill throws `\"\u003Cname>\" is not a supported API`.\n\n**Bail out fast on that error.** Do not retry; tell the user motion isn't enabled for them and stop. Otherwise you'll burn calls and confuse the user with repeated identical failures.\n\n## When to use this skill\n\nLoad this skill whenever a `use_figma` task involves:\n\n- Adding, editing, or removing keyframes on a node (`manualKeyframeTracks`, `applyManualKeyframeTrack`, `removeManualKeyframeTrack`).\n- Animating fill or stroke colors over time.\n- Applying, editing, or removing animation styles (`applyAnimationStyle`, `removeAnimationStyle`, `animationStyles`).\n- Reading or writing timeline duration via `node.timelines` \u002F `node.setTimelineDuration(id, seconds)`.\n- Choosing easing for any of the above.\n\nStatic design work (creating shapes, components, variables, layout) goes through [figma-use](..\u002Ffigma-use\u002FSKILL.md) alone — this skill is only for the time dimension.\n\n## Exposed motion API surface\n\n- `node.manualKeyframeTracks` — read\u002Fwrite manual keyframes (including fill, stroke, and effect tracks).\n- `node.applyManualKeyframeTrack(field, track)` \u002F `node.removeManualKeyframeTrack(field)` — add, replace, or remove one manual keyframe track without rewriting the whole object.\n- `node.animationStyles` — read\u002Fwrite animation-style metadata applied to a node.\n- `node.applyAnimationStyle(styleId, presetData?)` \u002F `node.removeAnimationStyle(id)` — apply a discovered style and remove an applied style instance by its returned\u002Fread-back `id`.\n- `node.timelines` — read-only timeline list for the containing top-level frame, with durations in seconds.\n- `node.setTimelineDuration(id, durationSeconds)` — write the containing top-level frame timeline duration.\n- `node.animations` — read-only resolved keyframe data (currently manual tracks only — see [motion-patterns.md](references\u002Fmotion-patterns.md)).\n- `figma.motion.figmaAnimationStyles()` — read-only list of Figma's first-party animation styles.\n\nAuthoring custom `\"figma:motion\"` preset module source code is out of scope. If the user wants a brand-new animation style, say so and stop; don't fabricate one.\n\n## Reference docs\n\nLoad these as needed based on what the task involves:\n\n| Doc | When to load | What it covers |\n|-----|-------------|----------------|\n| [motion-patterns.md](references\u002Fmotion-patterns.md) | Adding\u002Fediting motion animation | Manual keyframes, animated fills\u002Fstrokes, applying animation styles, timeline duration |\n| [motion-easing.md](references\u002Fmotion-easing.md) | Setting animation easing | Keyframe easing objects, custom cubic\u002Fspring, `HOLD`, applying easing inside an animation style |\n\n## Verifying the animation\n\n`get_screenshot` shows only the timeline's **resting state**, never motion. To check motion, `export_video` and sample frames — but it renders server-side and is **slow and expensive (~10s to minutes)**, so make each render count.\n\n**Plan before rendering — cost scales with pixels × frames, so keep both no larger than the frames need:**\n\n1. **Pick the moments first.** You need one frame per *phase* (e.g. per stagger step, or start \u002F mid \u002F settle), not smooth playback — usually 4–6. This count sets your fps.\n2. **Size to what you must read.** Start small — `constraint: { type: 'WIDTH', value: 320 }`, `quality: \"low\"` — but text and small elements blur there, so raise `WIDTH` (768+) when you need to judge fine detail. Omitting `constraint` = full size (1x; server clamps to 10x \u002F 4096px).\n3. **Set fps just high enough to land those frames:** `fps: 5` covers a handful; 10 is an upper bound. Higher just bloats the render.\n\n**Mechanics:** `export_video` works only on a **top-level frame** whose children carry the animation (pass that frame, not the descendant you keyframed). It returns a `jobId` with `status: \"processing\"` — re-invoke with `{ fileKey, jobId }` to poll. Then extract frames locally with `ffmpeg -ss \u003Ct> -i anim.mp4 -frames:v 1 frame_\u003Ct>.png` — extraction is free, so once you've paid for the render, mine it for every frame that tells you something rather than re-exporting. Without a frame extractor like `ffmpeg`, skip the export and reason about the keyframes instead.\n\n**Iterate until it's right.** The export is a diagnostic, not a sign-off: if the frames are wrong (bad order, off timing, a missing element, a mask blanking the composite), fix the keyframes\u002Fstyles and re-export. Read *all* the frames and batch every fix into one pass before re-rendering — every render carries real overhead, so make each one count instead of re-exporting after each small change.\n\nSkip the export entirely for trivial or self-evident changes.\n\n## Pre-flight checklist\n\nIn addition to the [figma-use pre-flight checklist](..\u002Ffigma-use\u002FSKILL.md#8-pre-flight-checklist), verify:\n\n- [ ] Easing uses the public `{ type: 'EASE_OUT', easingFunctionCubicBezier?: …, easingFunctionSpring?: … }` shape — not internal scenegraph names like `OUT_CUBIC`.\n- [ ] Ease-in-out uses the exact public enum `EASE_IN_AND_OUT` (or `EASE_IN_AND_OUT_BACK`); never emit the invalid alias `EASE_IN_OUT`.\n- [ ] The node being animated is not a top-level frame (direct child of a page). Animate descendants instead.\n- [ ] Timeline values are seconds in the public Plugin API. Extend via `setTimelineDuration`; never shorten unless the user asked.\n- [ ] Transform keyframe fields use public names (`TRANSLATION_X`, `TRANSLATION_Y`, `ROTATION`, `SCALE_X`, `SCALE_Y`, `SCALE_XY`), not internal `MOTION_*` scenegraph names.\n- [ ] Manual keyframe fields come from the public allowlist in [motion-patterns.md](references\u002Fmotion-patterns.md#animatable-fields); generated\u002Finternal scenegraph fields intentionally throw.\n- [ ] Mutated node IDs are returned (per `figma-use` Rule 15).\n- [ ] When motion correctness isn't self-evident and a frame extractor (`ffmpeg`) is available, verify via `export_video` + frame sampling — render small, low `fps`, iterate until right (see the Verifying the animation section above). `get_screenshot` shows only the resting state.\n",{"data":35,"body":37},{"name":4,"description":6,"disable-model-invocation":36},false,{"type":38,"children":39},"root",[40,49,73,106,113,134,144,150,162,251,262,268,386,399,405,410,493,499,532,540,621,684,701,706,712,725],{"type":41,"tag":42,"props":43,"children":45},"element","h1",{"id":44},"use_figma-figma-plugin-api-skill-for-motion",[46],{"type":47,"value":48},"text","use_figma — Figma Plugin API Skill for Motion",{"type":41,"tag":50,"props":51,"children":52},"p",{},[53,55,62,64,71],{"type":47,"value":54},"Motion context for the ",{"type":41,"tag":56,"props":57,"children":59},"code",{"className":58},[],[60],{"type":47,"value":61},"use_figma",{"type":47,"value":63}," MCP tool. ",{"type":41,"tag":65,"props":66,"children":68},"a",{"href":67},"..\u002Ffigma-use\u002FSKILL.md",[69],{"type":47,"value":70},"figma-use",{"type":47,"value":72}," covers the foundational Plugin API rules — load both together.",{"type":41,"tag":50,"props":74,"children":75},{},[76,104],{"type":41,"tag":77,"props":78,"children":79},"strong",{},[80,82,88,90,95,97,102],{"type":47,"value":81},"Always pass ",{"type":41,"tag":56,"props":83,"children":85},{"className":84},[],[86],{"type":47,"value":87},"skillNames: \"figma-use-motion\"",{"type":47,"value":89}," (comma-separated alongside ",{"type":41,"tag":56,"props":91,"children":93},{"className":92},[],[94],{"type":47,"value":70},{"type":47,"value":96},") when calling ",{"type":41,"tag":56,"props":98,"children":100},{"className":99},[],[101],{"type":47,"value":61},{"type":47,"value":103}," for motion work.",{"type":47,"value":105}," Logging only.",{"type":41,"tag":107,"props":108,"children":110},"h2",{"id":109},"runtime-gating",[111],{"type":47,"value":112},"Runtime Gating",{"type":41,"tag":50,"props":114,"children":115},{},[116,118,124,126,132],{"type":47,"value":117},"Motion APIs are gated behind the ",{"type":41,"tag":56,"props":119,"children":121},{"className":120},[],[122],{"type":47,"value":123},"metronome",{"type":47,"value":125}," user feature flag. When the calling user doesn't have it, every motion property and helper referenced in this skill throws ",{"type":41,"tag":56,"props":127,"children":129},{"className":128},[],[130],{"type":47,"value":131},"\"\u003Cname>\" is not a supported API",{"type":47,"value":133},".",{"type":41,"tag":50,"props":135,"children":136},{},[137,142],{"type":41,"tag":77,"props":138,"children":139},{},[140],{"type":47,"value":141},"Bail out fast on that error.",{"type":47,"value":143}," Do not retry; tell the user motion isn't enabled for them and stop. Otherwise you'll burn calls and confuse the user with repeated identical failures.",{"type":41,"tag":107,"props":145,"children":147},{"id":146},"when-to-use-this-skill",[148],{"type":47,"value":149},"When to use this skill",{"type":41,"tag":50,"props":151,"children":152},{},[153,155,160],{"type":47,"value":154},"Load this skill whenever a ",{"type":41,"tag":56,"props":156,"children":158},{"className":157},[],[159],{"type":47,"value":61},{"type":47,"value":161}," task involves:",{"type":41,"tag":163,"props":164,"children":165},"ul",{},[166,195,200,226,246],{"type":41,"tag":167,"props":168,"children":169},"li",{},[170,172,178,180,186,187,193],{"type":47,"value":171},"Adding, editing, or removing keyframes on a node (",{"type":41,"tag":56,"props":173,"children":175},{"className":174},[],[176],{"type":47,"value":177},"manualKeyframeTracks",{"type":47,"value":179},", ",{"type":41,"tag":56,"props":181,"children":183},{"className":182},[],[184],{"type":47,"value":185},"applyManualKeyframeTrack",{"type":47,"value":179},{"type":41,"tag":56,"props":188,"children":190},{"className":189},[],[191],{"type":47,"value":192},"removeManualKeyframeTrack",{"type":47,"value":194},").",{"type":41,"tag":167,"props":196,"children":197},{},[198],{"type":47,"value":199},"Animating fill or stroke colors over time.",{"type":41,"tag":167,"props":201,"children":202},{},[203,205,211,212,218,219,225],{"type":47,"value":204},"Applying, editing, or removing animation styles (",{"type":41,"tag":56,"props":206,"children":208},{"className":207},[],[209],{"type":47,"value":210},"applyAnimationStyle",{"type":47,"value":179},{"type":41,"tag":56,"props":213,"children":215},{"className":214},[],[216],{"type":47,"value":217},"removeAnimationStyle",{"type":47,"value":179},{"type":41,"tag":56,"props":220,"children":222},{"className":221},[],[223],{"type":47,"value":224},"animationStyles",{"type":47,"value":194},{"type":41,"tag":167,"props":227,"children":228},{},[229,231,237,239,245],{"type":47,"value":230},"Reading or writing timeline duration via ",{"type":41,"tag":56,"props":232,"children":234},{"className":233},[],[235],{"type":47,"value":236},"node.timelines",{"type":47,"value":238}," \u002F ",{"type":41,"tag":56,"props":240,"children":242},{"className":241},[],[243],{"type":47,"value":244},"node.setTimelineDuration(id, seconds)",{"type":47,"value":133},{"type":41,"tag":167,"props":247,"children":248},{},[249],{"type":47,"value":250},"Choosing easing for any of the above.",{"type":41,"tag":50,"props":252,"children":253},{},[254,256,260],{"type":47,"value":255},"Static design work (creating shapes, components, variables, layout) goes through ",{"type":41,"tag":65,"props":257,"children":258},{"href":67},[259],{"type":47,"value":70},{"type":47,"value":261}," alone — this skill is only for the time dimension.",{"type":41,"tag":107,"props":263,"children":265},{"id":264},"exposed-motion-api-surface",[266],{"type":47,"value":267},"Exposed motion API surface",{"type":41,"tag":163,"props":269,"children":270},{},[271,282,300,311,336,346,357,375],{"type":41,"tag":167,"props":272,"children":273},{},[274,280],{"type":41,"tag":56,"props":275,"children":277},{"className":276},[],[278],{"type":47,"value":279},"node.manualKeyframeTracks",{"type":47,"value":281}," — read\u002Fwrite manual keyframes (including fill, stroke, and effect tracks).",{"type":41,"tag":167,"props":283,"children":284},{},[285,291,292,298],{"type":41,"tag":56,"props":286,"children":288},{"className":287},[],[289],{"type":47,"value":290},"node.applyManualKeyframeTrack(field, track)",{"type":47,"value":238},{"type":41,"tag":56,"props":293,"children":295},{"className":294},[],[296],{"type":47,"value":297},"node.removeManualKeyframeTrack(field)",{"type":47,"value":299}," — add, replace, or remove one manual keyframe track without rewriting the whole object.",{"type":41,"tag":167,"props":301,"children":302},{},[303,309],{"type":41,"tag":56,"props":304,"children":306},{"className":305},[],[307],{"type":47,"value":308},"node.animationStyles",{"type":47,"value":310}," — read\u002Fwrite animation-style metadata applied to a node.",{"type":41,"tag":167,"props":312,"children":313},{},[314,320,321,327,329,335],{"type":41,"tag":56,"props":315,"children":317},{"className":316},[],[318],{"type":47,"value":319},"node.applyAnimationStyle(styleId, presetData?)",{"type":47,"value":238},{"type":41,"tag":56,"props":322,"children":324},{"className":323},[],[325],{"type":47,"value":326},"node.removeAnimationStyle(id)",{"type":47,"value":328}," — apply a discovered style and remove an applied style instance by its returned\u002Fread-back ",{"type":41,"tag":56,"props":330,"children":332},{"className":331},[],[333],{"type":47,"value":334},"id",{"type":47,"value":133},{"type":41,"tag":167,"props":337,"children":338},{},[339,344],{"type":41,"tag":56,"props":340,"children":342},{"className":341},[],[343],{"type":47,"value":236},{"type":47,"value":345}," — read-only timeline list for the containing top-level frame, with durations in seconds.",{"type":41,"tag":167,"props":347,"children":348},{},[349,355],{"type":41,"tag":56,"props":350,"children":352},{"className":351},[],[353],{"type":47,"value":354},"node.setTimelineDuration(id, durationSeconds)",{"type":47,"value":356}," — write the containing top-level frame timeline duration.",{"type":41,"tag":167,"props":358,"children":359},{},[360,366,368,374],{"type":41,"tag":56,"props":361,"children":363},{"className":362},[],[364],{"type":47,"value":365},"node.animations",{"type":47,"value":367}," — read-only resolved keyframe data (currently manual tracks only — see ",{"type":41,"tag":65,"props":369,"children":371},{"href":370},"references\u002Fmotion-patterns.md",[372],{"type":47,"value":373},"motion-patterns.md",{"type":47,"value":194},{"type":41,"tag":167,"props":376,"children":377},{},[378,384],{"type":41,"tag":56,"props":379,"children":381},{"className":380},[],[382],{"type":47,"value":383},"figma.motion.figmaAnimationStyles()",{"type":47,"value":385}," — read-only list of Figma's first-party animation styles.",{"type":41,"tag":50,"props":387,"children":388},{},[389,391,397],{"type":47,"value":390},"Authoring custom ",{"type":41,"tag":56,"props":392,"children":394},{"className":393},[],[395],{"type":47,"value":396},"\"figma:motion\"",{"type":47,"value":398}," preset module source code is out of scope. If the user wants a brand-new animation style, say so and stop; don't fabricate one.",{"type":41,"tag":107,"props":400,"children":402},{"id":401},"reference-docs",[403],{"type":47,"value":404},"Reference docs",{"type":41,"tag":50,"props":406,"children":407},{},[408],{"type":47,"value":409},"Load these as needed based on what the task involves:",{"type":41,"tag":411,"props":412,"children":413},"table",{},[414,438],{"type":41,"tag":415,"props":416,"children":417},"thead",{},[418],{"type":41,"tag":419,"props":420,"children":421},"tr",{},[422,428,433],{"type":41,"tag":423,"props":424,"children":425},"th",{},[426],{"type":47,"value":427},"Doc",{"type":41,"tag":423,"props":429,"children":430},{},[431],{"type":47,"value":432},"When to load",{"type":41,"tag":423,"props":434,"children":435},{},[436],{"type":47,"value":437},"What it covers",{"type":41,"tag":439,"props":440,"children":441},"tbody",{},[442,463],{"type":41,"tag":419,"props":443,"children":444},{},[445,453,458],{"type":41,"tag":446,"props":447,"children":448},"td",{},[449],{"type":41,"tag":65,"props":450,"children":451},{"href":370},[452],{"type":47,"value":373},{"type":41,"tag":446,"props":454,"children":455},{},[456],{"type":47,"value":457},"Adding\u002Fediting motion animation",{"type":41,"tag":446,"props":459,"children":460},{},[461],{"type":47,"value":462},"Manual keyframes, animated fills\u002Fstrokes, applying animation styles, timeline duration",{"type":41,"tag":419,"props":464,"children":465},{},[466,475,480],{"type":41,"tag":446,"props":467,"children":468},{},[469],{"type":41,"tag":65,"props":470,"children":472},{"href":471},"references\u002Fmotion-easing.md",[473],{"type":47,"value":474},"motion-easing.md",{"type":41,"tag":446,"props":476,"children":477},{},[478],{"type":47,"value":479},"Setting animation easing",{"type":41,"tag":446,"props":481,"children":482},{},[483,485,491],{"type":47,"value":484},"Keyframe easing objects, custom cubic\u002Fspring, ",{"type":41,"tag":56,"props":486,"children":488},{"className":487},[],[489],{"type":47,"value":490},"HOLD",{"type":47,"value":492},", applying easing inside an animation style",{"type":41,"tag":107,"props":494,"children":496},{"id":495},"verifying-the-animation",[497],{"type":47,"value":498},"Verifying the animation",{"type":41,"tag":50,"props":500,"children":501},{},[502,508,510,515,517,523,525,530],{"type":41,"tag":56,"props":503,"children":505},{"className":504},[],[506],{"type":47,"value":507},"get_screenshot",{"type":47,"value":509}," shows only the timeline's ",{"type":41,"tag":77,"props":511,"children":512},{},[513],{"type":47,"value":514},"resting state",{"type":47,"value":516},", never motion. To check motion, ",{"type":41,"tag":56,"props":518,"children":520},{"className":519},[],[521],{"type":47,"value":522},"export_video",{"type":47,"value":524}," and sample frames — but it renders server-side and is ",{"type":41,"tag":77,"props":526,"children":527},{},[528],{"type":47,"value":529},"slow and expensive (~10s to minutes)",{"type":47,"value":531},", so make each render count.",{"type":41,"tag":50,"props":533,"children":534},{},[535],{"type":41,"tag":77,"props":536,"children":537},{},[538],{"type":47,"value":539},"Plan before rendering — cost scales with pixels × frames, so keep both no larger than the frames need:",{"type":41,"tag":541,"props":542,"children":543},"ol",{},[544,562,603],{"type":41,"tag":167,"props":545,"children":546},{},[547,552,554,560],{"type":41,"tag":77,"props":548,"children":549},{},[550],{"type":47,"value":551},"Pick the moments first.",{"type":47,"value":553}," You need one frame per ",{"type":41,"tag":555,"props":556,"children":557},"em",{},[558],{"type":47,"value":559},"phase",{"type":47,"value":561}," (e.g. per stagger step, or start \u002F mid \u002F settle), not smooth playback — usually 4–6. This count sets your fps.",{"type":41,"tag":167,"props":563,"children":564},{},[565,570,572,578,579,585,587,593,595,601],{"type":41,"tag":77,"props":566,"children":567},{},[568],{"type":47,"value":569},"Size to what you must read.",{"type":47,"value":571}," Start small — ",{"type":41,"tag":56,"props":573,"children":575},{"className":574},[],[576],{"type":47,"value":577},"constraint: { type: 'WIDTH', value: 320 }",{"type":47,"value":179},{"type":41,"tag":56,"props":580,"children":582},{"className":581},[],[583],{"type":47,"value":584},"quality: \"low\"",{"type":47,"value":586}," — but text and small elements blur there, so raise ",{"type":41,"tag":56,"props":588,"children":590},{"className":589},[],[591],{"type":47,"value":592},"WIDTH",{"type":47,"value":594}," (768+) when you need to judge fine detail. Omitting ",{"type":41,"tag":56,"props":596,"children":598},{"className":597},[],[599],{"type":47,"value":600},"constraint",{"type":47,"value":602}," = full size (1x; server clamps to 10x \u002F 4096px).",{"type":41,"tag":167,"props":604,"children":605},{},[606,611,613,619],{"type":41,"tag":77,"props":607,"children":608},{},[609],{"type":47,"value":610},"Set fps just high enough to land those frames:",{"type":47,"value":612}," ",{"type":41,"tag":56,"props":614,"children":616},{"className":615},[],[617],{"type":47,"value":618},"fps: 5",{"type":47,"value":620}," covers a handful; 10 is an upper bound. Higher just bloats the render.",{"type":41,"tag":50,"props":622,"children":623},{},[624,629,630,635,637,642,644,650,652,658,660,666,668,674,676,682],{"type":41,"tag":77,"props":625,"children":626},{},[627],{"type":47,"value":628},"Mechanics:",{"type":47,"value":612},{"type":41,"tag":56,"props":631,"children":633},{"className":632},[],[634],{"type":47,"value":522},{"type":47,"value":636}," works only on a ",{"type":41,"tag":77,"props":638,"children":639},{},[640],{"type":47,"value":641},"top-level frame",{"type":47,"value":643}," whose children carry the animation (pass that frame, not the descendant you keyframed). It returns a ",{"type":41,"tag":56,"props":645,"children":647},{"className":646},[],[648],{"type":47,"value":649},"jobId",{"type":47,"value":651}," with ",{"type":41,"tag":56,"props":653,"children":655},{"className":654},[],[656],{"type":47,"value":657},"status: \"processing\"",{"type":47,"value":659}," — re-invoke with ",{"type":41,"tag":56,"props":661,"children":663},{"className":662},[],[664],{"type":47,"value":665},"{ fileKey, jobId }",{"type":47,"value":667}," to poll. Then extract frames locally with ",{"type":41,"tag":56,"props":669,"children":671},{"className":670},[],[672],{"type":47,"value":673},"ffmpeg -ss \u003Ct> -i anim.mp4 -frames:v 1 frame_\u003Ct>.png",{"type":47,"value":675}," — extraction is free, so once you've paid for the render, mine it for every frame that tells you something rather than re-exporting. Without a frame extractor like ",{"type":41,"tag":56,"props":677,"children":679},{"className":678},[],[680],{"type":47,"value":681},"ffmpeg",{"type":47,"value":683},", skip the export and reason about the keyframes instead.",{"type":41,"tag":50,"props":685,"children":686},{},[687,692,694,699],{"type":41,"tag":77,"props":688,"children":689},{},[690],{"type":47,"value":691},"Iterate until it's right.",{"type":47,"value":693}," The export is a diagnostic, not a sign-off: if the frames are wrong (bad order, off timing, a missing element, a mask blanking the composite), fix the keyframes\u002Fstyles and re-export. Read ",{"type":41,"tag":555,"props":695,"children":696},{},[697],{"type":47,"value":698},"all",{"type":47,"value":700}," the frames and batch every fix into one pass before re-rendering — every render carries real overhead, so make each one count instead of re-exporting after each small change.",{"type":41,"tag":50,"props":702,"children":703},{},[704],{"type":47,"value":705},"Skip the export entirely for trivial or self-evident changes.",{"type":41,"tag":107,"props":707,"children":709},{"id":708},"pre-flight-checklist",[710],{"type":47,"value":711},"Pre-flight checklist",{"type":41,"tag":50,"props":713,"children":714},{},[715,717,723],{"type":47,"value":716},"In addition to the ",{"type":41,"tag":65,"props":718,"children":720},{"href":719},"..\u002Ffigma-use\u002FSKILL.md#8-pre-flight-checklist",[721],{"type":47,"value":722},"figma-use pre-flight checklist",{"type":47,"value":724},", verify:",{"type":41,"tag":163,"props":726,"children":729},{"className":727},[728],"contains-task-list",[730,758,790,799,816,876,892,908],{"type":41,"tag":167,"props":731,"children":734},{"className":732},[733],"task-list-item",[735,741,743,749,751,757],{"type":41,"tag":736,"props":737,"children":740},"input",{"disabled":738,"type":739},true,"checkbox",[],{"type":47,"value":742}," Easing uses the public ",{"type":41,"tag":56,"props":744,"children":746},{"className":745},[],[747],{"type":47,"value":748},"{ type: 'EASE_OUT', easingFunctionCubicBezier?: …, easingFunctionSpring?: … }",{"type":47,"value":750}," shape — not internal scenegraph names like ",{"type":41,"tag":56,"props":752,"children":754},{"className":753},[],[755],{"type":47,"value":756},"OUT_CUBIC",{"type":47,"value":133},{"type":41,"tag":167,"props":759,"children":761},{"className":760},[733],[762,765,767,773,775,781,783,789],{"type":41,"tag":736,"props":763,"children":764},{"disabled":738,"type":739},[],{"type":47,"value":766}," Ease-in-out uses the exact public enum ",{"type":41,"tag":56,"props":768,"children":770},{"className":769},[],[771],{"type":47,"value":772},"EASE_IN_AND_OUT",{"type":47,"value":774}," (or ",{"type":41,"tag":56,"props":776,"children":778},{"className":777},[],[779],{"type":47,"value":780},"EASE_IN_AND_OUT_BACK",{"type":47,"value":782},"); never emit the invalid alias ",{"type":41,"tag":56,"props":784,"children":786},{"className":785},[],[787],{"type":47,"value":788},"EASE_IN_OUT",{"type":47,"value":133},{"type":41,"tag":167,"props":791,"children":793},{"className":792},[733],[794,797],{"type":41,"tag":736,"props":795,"children":796},{"disabled":738,"type":739},[],{"type":47,"value":798}," The node being animated is not a top-level frame (direct child of a page). Animate descendants instead.",{"type":41,"tag":167,"props":800,"children":802},{"className":801},[733],[803,806,808,814],{"type":41,"tag":736,"props":804,"children":805},{"disabled":738,"type":739},[],{"type":47,"value":807}," Timeline values are seconds in the public Plugin API. Extend via ",{"type":41,"tag":56,"props":809,"children":811},{"className":810},[],[812],{"type":47,"value":813},"setTimelineDuration",{"type":47,"value":815},"; never shorten unless the user asked.",{"type":41,"tag":167,"props":817,"children":819},{"className":818},[733],[820,823,825,831,832,838,839,845,846,852,853,859,860,866,868,874],{"type":41,"tag":736,"props":821,"children":822},{"disabled":738,"type":739},[],{"type":47,"value":824}," Transform keyframe fields use public names (",{"type":41,"tag":56,"props":826,"children":828},{"className":827},[],[829],{"type":47,"value":830},"TRANSLATION_X",{"type":47,"value":179},{"type":41,"tag":56,"props":833,"children":835},{"className":834},[],[836],{"type":47,"value":837},"TRANSLATION_Y",{"type":47,"value":179},{"type":41,"tag":56,"props":840,"children":842},{"className":841},[],[843],{"type":47,"value":844},"ROTATION",{"type":47,"value":179},{"type":41,"tag":56,"props":847,"children":849},{"className":848},[],[850],{"type":47,"value":851},"SCALE_X",{"type":47,"value":179},{"type":41,"tag":56,"props":854,"children":856},{"className":855},[],[857],{"type":47,"value":858},"SCALE_Y",{"type":47,"value":179},{"type":41,"tag":56,"props":861,"children":863},{"className":862},[],[864],{"type":47,"value":865},"SCALE_XY",{"type":47,"value":867},"), not internal ",{"type":41,"tag":56,"props":869,"children":871},{"className":870},[],[872],{"type":47,"value":873},"MOTION_*",{"type":47,"value":875}," scenegraph names.",{"type":41,"tag":167,"props":877,"children":879},{"className":878},[733],[880,883,885,890],{"type":41,"tag":736,"props":881,"children":882},{"disabled":738,"type":739},[],{"type":47,"value":884}," Manual keyframe fields come from the public allowlist in ",{"type":41,"tag":65,"props":886,"children":888},{"href":887},"references\u002Fmotion-patterns.md#animatable-fields",[889],{"type":47,"value":373},{"type":47,"value":891},"; generated\u002Finternal scenegraph fields intentionally throw.",{"type":41,"tag":167,"props":893,"children":895},{"className":894},[733],[896,899,901,906],{"type":41,"tag":736,"props":897,"children":898},{"disabled":738,"type":739},[],{"type":47,"value":900}," Mutated node IDs are returned (per ",{"type":41,"tag":56,"props":902,"children":904},{"className":903},[],[905],{"type":47,"value":70},{"type":47,"value":907}," Rule 15).",{"type":41,"tag":167,"props":909,"children":911},{"className":910},[733],[912,915,917,922,924,929,931,937,939,944],{"type":41,"tag":736,"props":913,"children":914},{"disabled":738,"type":739},[],{"type":47,"value":916}," When motion correctness isn't self-evident and a frame extractor (",{"type":41,"tag":56,"props":918,"children":920},{"className":919},[],[921],{"type":47,"value":681},{"type":47,"value":923},") is available, verify via ",{"type":41,"tag":56,"props":925,"children":927},{"className":926},[],[928],{"type":47,"value":522},{"type":47,"value":930}," + frame sampling — render small, low ",{"type":41,"tag":56,"props":932,"children":934},{"className":933},[],[935],{"type":47,"value":936},"fps",{"type":47,"value":938},", iterate until right (see the Verifying the animation section above). ",{"type":41,"tag":56,"props":940,"children":942},{"className":941},[],[943],{"type":47,"value":507},{"type":47,"value":945}," shows only the resting state.",{"items":947,"total":1109},[948,966,979,990,1001,1017,1031,1042,1064,1073,1089,1096],{"slug":949,"name":949,"fn":950,"description":951,"org":952,"tags":953,"stars":23,"repoUrl":24,"updatedAt":965},"figma-code-connect","map Figma components to code snippets","Creates and maintains Figma Code Connect template files that map Figma components to code snippets. Use when the user mentions Code Connect, Figma component mapping, design-to-code translation, or asks to create\u002Fupdate .figma.ts or .figma.js files.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[954,955,958,959,962],{"name":21,"slug":22,"type":15},{"name":956,"slug":957,"type":15},"Design System","design-system",{"name":9,"slug":8,"type":15},{"name":960,"slug":961,"type":15},"Frontend","frontend",{"name":963,"slug":964,"type":15},"UI Components","ui-components","2026-07-31T05:52:30.590302",{"slug":967,"name":967,"fn":968,"description":969,"org":970,"tags":971,"stars":23,"repoUrl":24,"updatedAt":978},"figma-create-new-file","create new Figma or FigJam files","**MANDATORY prerequisite** — you MUST invoke this skill BEFORE every `create_new_file` tool call. NEVER call `create_new_file` directly without loading this skill first. Trigger whenever the user wants a new blank Figma file — a new design, FigJam, or Slides file — or when you need a fresh file before calling `use_figma`. Usage — \u002Ffigma-create-new-file [editorType] [fileName] (e.g. \u002Ffigma-create-new-file figjam My Whiteboard, \u002Ffigma-create-new-file slides Q3 Review)",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[972,973,974,977],{"name":21,"slug":22,"type":15},{"name":9,"slug":8,"type":15},{"name":975,"slug":976,"type":15},"Ideation","ideation",{"name":13,"slug":14,"type":15},"2026-04-06T18:11:46.464282",{"slug":980,"name":980,"fn":981,"description":982,"org":983,"tags":984,"stars":23,"repoUrl":24,"updatedAt":989},"figma-design-to-code","implement Figma designs as code","**MANDATORY prerequisite** — you MUST invoke this skill BEFORE calling the `get_design_context` Figma MCP tool. You MUST trigger this skill whenever the user wants to implement, build, port, or code up a Figma design as code. Example prompts (not exhaustive) are 'implement this Figma design', 'build this screen from Figma', 'turn this Figma into code', 'design to code'. This skill provides critical instructions and steps to the agent on how to correctly implement Figma designs in code and must NOT be skipped.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[985,986,987,988],{"name":21,"slug":22,"type":15},{"name":9,"slug":8,"type":15},{"name":960,"slug":961,"type":15},{"name":963,"slug":964,"type":15},"2026-07-10T06:43:51.122606",{"slug":991,"name":991,"fn":992,"description":993,"org":994,"tags":995,"stars":23,"repoUrl":24,"updatedAt":1000},"figma-generate-design","translate code layouts into Figma","Use this skill alongside figma-use when the task involves translating an application page, view, or multi-section layout into Figma. Triggers: 'write to Figma', 'create in Figma from code', 'push page to Figma', 'take this app\u002Fpage and build it in Figma', 'create a screen', 'build a landing page in Figma', 'update the Figma screen to match code', 'convert this modal\u002Fdialog\u002Fdrawer\u002Fpanel to Figma'. This is the preferred workflow skill whenever the user wants to build or update a full page, modal, dialog, drawer, sidebar, panel, or any composed multi-section view in Figma from code or a description. Discovers design system components, variables, and styles from Code Connect files, existing screens, and library search, then imports them and assembles views incrementally section-by-section using design system tokens instead of hardcoded values.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[996,997,998,999],{"name":21,"slug":22,"type":15},{"name":9,"slug":8,"type":15},{"name":960,"slug":961,"type":15},{"name":963,"slug":964,"type":15},"2026-04-06T18:11:48.952023",{"slug":1002,"name":1002,"fn":1003,"description":1004,"org":1005,"tags":1006,"stars":23,"repoUrl":24,"updatedAt":1016},"figma-generate-diagram","generate flowcharts and architecture diagrams in Figma","MANDATORY prerequisite — load this skill BEFORE every `generate_diagram` tool call. NEVER call `generate_diagram` directly without loading this skill first. Trigger whenever the user asks to create, generate, draw, render, sketch, or build a diagram — flowchart, architecture diagram, sequence diagram, ERD or entity-relationship diagram, state diagram or state machine, gantt chart, or timeline. Also trigger when the user mentions Mermaid syntax or wants a system architecture, decision tree, dependency graph, API call flow, auth handshake, schema, or pipeline visualized in FigJam. Routes to type-specific guidance, sets universal Mermaid constraints, and tells you when to use a different diagram type or skip the tool entirely (mindmaps, pie charts, class diagrams, etc.).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1007,1010,1011,1014,1015],{"name":1008,"slug":1009,"type":15},"Architecture","architecture",{"name":21,"slug":22,"type":15},{"name":1012,"slug":1013,"type":15},"Diagrams","diagrams",{"name":9,"slug":8,"type":15},{"name":13,"slug":14,"type":15},"2026-04-28T05:43:52.834484",{"slug":1018,"name":1018,"fn":1019,"description":1020,"org":1021,"tags":1022,"stars":23,"repoUrl":24,"updatedAt":1030},"figma-generate-library","build Figma design systems from code","Build or update a professional-grade design system in Figma from a codebase. Use when the user wants to create variables\u002Ftokens, build component libraries, create individual components with proper variant sets and variable bindings, set up theming (light\u002Fdark modes), document foundations, or reconcile gaps between code and Figma. Also use when the user asks to create or generate any component in Figma — even a single one — since components require proper variable foundations, variant states, and design token bindings to be production-quality. This skill teaches WHAT to build and in WHAT ORDER — it complements the `figma-use` skill which teaches HOW to call the Plugin API. Both skills should be loaded together.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1023,1024,1025,1028,1029],{"name":21,"slug":22,"type":15},{"name":956,"slug":957,"type":15},{"name":1026,"slug":1027,"type":15},"Documentation","documentation",{"name":9,"slug":8,"type":15},{"name":963,"slug":964,"type":15},"2026-07-31T05:52:28.587088",{"slug":1032,"name":1032,"fn":1033,"description":1034,"org":1035,"tags":1036,"stars":23,"repoUrl":24,"updatedAt":1041},"figma-implement-motion","implement Figma animations in production code","Translates Figma motion and animations into production-ready application code. Use when implementing animation\u002Fmotion from a Figma design — user mentions \"implement this motion\", \"add animation from Figma\", \"animate this component\", provides a Figma URL whose node is animated, or when `get_design_context` returns motion data or instructs you to call `get_motion_context`.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1037,1038,1039,1040],{"name":17,"slug":18,"type":15},{"name":21,"slug":22,"type":15},{"name":9,"slug":8,"type":15},{"name":960,"slug":961,"type":15},"2026-06-25T07:13:13.645254",{"slug":1043,"name":1043,"fn":1044,"description":1045,"org":1046,"tags":1047,"stars":23,"repoUrl":24,"updatedAt":1063},"figma-swiftui","translate between Figma designs and SwiftUI code","SwiftUI ↔ Figma translation. Use whenever the user mentions Swift, SwiftUI, iOS, iPhone, or iPad — in EITHER direction — translating a Figma design into SwiftUI (design → code), or pushing SwiftUI views \u002F screens \u002F tokens back into a Figma file (code → design). Triggers on phrases like 'implement this Figma design in SwiftUI', 'build this screen in Swift', 'push this SwiftUI view to Figma', 'mirror my Swift code in a Figma file', or whenever a Figma URL appears alongside `.swift` files \u002F an `.xcodeproj`. Routes to a direction-specific reference doc; loads alongside `figma-use` for the code → design path.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1048,1049,1050,1051,1054,1057,1060],{"name":21,"slug":22,"type":15},{"name":9,"slug":8,"type":15},{"name":960,"slug":961,"type":15},{"name":1052,"slug":1053,"type":15},"iOS","ios",{"name":1055,"slug":1056,"type":15},"Mobile","mobile",{"name":1058,"slug":1059,"type":15},"SwiftUI","swiftui",{"name":1061,"slug":1062,"type":15},"Visual Design","visual-design","2026-06-09T07:16:28.204756",{"slug":70,"name":70,"fn":1065,"description":1066,"org":1067,"tags":1068,"stars":23,"repoUrl":24,"updatedAt":1072},"initialize Figma tool usage","**MANDATORY prerequisite** — you MUST invoke this skill BEFORE every `use_figma` tool call. NEVER call `use_figma` directly without loading this skill first. Skipping it causes common, hard-to-debug failures. Trigger whenever the user wants to perform a write action or a unique read action that requires JavaScript execution in the Figma file context — e.g. create\u002Fedit\u002Fdelete nodes, set up variables or tokens, build components and variants, modify auto-layout or fills, bind variables to properties, or inspect file structure programmatically.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1069,1070,1071],{"name":21,"slug":22,"type":15},{"name":9,"slug":8,"type":15},{"name":13,"slug":14,"type":15},"2026-07-31T05:52:29.57808",{"slug":1074,"name":1074,"fn":1075,"description":1076,"org":1077,"tags":1078,"stars":23,"repoUrl":24,"updatedAt":1088},"figma-use-figjam","use Figma tools in FigJam context","This skill helps agents use Figma's use_figma MCP tool in the FigJam context. Can be used alongside figma-use which has foundational context for using the use_figma tool.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1079,1082,1083,1086,1087],{"name":1080,"slug":1081,"type":15},"Collaboration","collaboration",{"name":21,"slug":22,"type":15},{"name":1084,"slug":1085,"type":15},"FigJam","figjam",{"name":9,"slug":8,"type":15},{"name":13,"slug":14,"type":15},"2026-04-28T05:43:51.600727",{"slug":4,"name":4,"fn":5,"description":6,"org":1090,"tags":1091,"stars":23,"repoUrl":24,"updatedAt":25},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1092,1093,1094,1095],{"name":17,"slug":18,"type":15},{"name":21,"slug":22,"type":15},{"name":9,"slug":8,"type":15},{"name":13,"slug":14,"type":15},{"slug":1097,"name":1097,"fn":1098,"description":1099,"org":1100,"tags":1101,"stars":23,"repoUrl":24,"updatedAt":1108},"figma-use-slides","use Figma tools in Slides context","This skill helps agents use Figma's use_figma MCP tool in the Slides context. Can be used alongside figma-use which has foundational context for using the use_figma tool.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1102,1103,1104,1105],{"name":21,"slug":22,"type":15},{"name":9,"slug":8,"type":15},{"name":13,"slug":14,"type":15},{"name":1106,"slug":1107,"type":15},"Presentations","presentations","2026-05-14T06:09:42.171824",14,{"items":1111,"total":1109},[1112,1120,1127,1134,1141,1149,1157],{"slug":949,"name":949,"fn":950,"description":951,"org":1113,"tags":1114,"stars":23,"repoUrl":24,"updatedAt":965},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1115,1116,1117,1118,1119],{"name":21,"slug":22,"type":15},{"name":956,"slug":957,"type":15},{"name":9,"slug":8,"type":15},{"name":960,"slug":961,"type":15},{"name":963,"slug":964,"type":15},{"slug":967,"name":967,"fn":968,"description":969,"org":1121,"tags":1122,"stars":23,"repoUrl":24,"updatedAt":978},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1123,1124,1125,1126],{"name":21,"slug":22,"type":15},{"name":9,"slug":8,"type":15},{"name":975,"slug":976,"type":15},{"name":13,"slug":14,"type":15},{"slug":980,"name":980,"fn":981,"description":982,"org":1128,"tags":1129,"stars":23,"repoUrl":24,"updatedAt":989},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1130,1131,1132,1133],{"name":21,"slug":22,"type":15},{"name":9,"slug":8,"type":15},{"name":960,"slug":961,"type":15},{"name":963,"slug":964,"type":15},{"slug":991,"name":991,"fn":992,"description":993,"org":1135,"tags":1136,"stars":23,"repoUrl":24,"updatedAt":1000},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1137,1138,1139,1140],{"name":21,"slug":22,"type":15},{"name":9,"slug":8,"type":15},{"name":960,"slug":961,"type":15},{"name":963,"slug":964,"type":15},{"slug":1002,"name":1002,"fn":1003,"description":1004,"org":1142,"tags":1143,"stars":23,"repoUrl":24,"updatedAt":1016},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1144,1145,1146,1147,1148],{"name":1008,"slug":1009,"type":15},{"name":21,"slug":22,"type":15},{"name":1012,"slug":1013,"type":15},{"name":9,"slug":8,"type":15},{"name":13,"slug":14,"type":15},{"slug":1018,"name":1018,"fn":1019,"description":1020,"org":1150,"tags":1151,"stars":23,"repoUrl":24,"updatedAt":1030},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1152,1153,1154,1155,1156],{"name":21,"slug":22,"type":15},{"name":956,"slug":957,"type":15},{"name":1026,"slug":1027,"type":15},{"name":9,"slug":8,"type":15},{"name":963,"slug":964,"type":15},{"slug":1032,"name":1032,"fn":1033,"description":1034,"org":1158,"tags":1159,"stars":23,"repoUrl":24,"updatedAt":1041},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1160,1161,1162,1163],{"name":17,"slug":18,"type":15},{"name":21,"slug":22,"type":15},{"name":9,"slug":8,"type":15},{"name":960,"slug":961,"type":15}]