[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-openai-figma-implement-motion":3,"mdc--wwlglh-key":36,"related-repo-openai-figma-implement-motion":2365,"related-org-openai-figma-implement-motion":2484},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":25,"repoUrl":26,"updatedAt":27,"license":28,"forks":29,"topics":30,"repo":31,"sourceUrl":34,"mdContent":35},"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},"openai","OpenAI","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fopenai.png",[12,16,19,22],{"name":13,"slug":14,"type":15},"Animation","animation","tag",{"name":17,"slug":18,"type":15},"Frontend","frontend",{"name":20,"slug":21,"type":15},"Figma","figma",{"name":23,"slug":24,"type":15},"Design","design",3992,"https:\u002F\u002Fgithub.com\u002Fopenai\u002Fplugins","2026-06-25T07:26:14.096989",null,465,[],{"repoUrl":26,"stars":25,"forks":29,"topics":32,"description":33},[],"OpenAI Plugins","https:\u002F\u002Fgithub.com\u002Fopenai\u002Fplugins\u002Ftree\u002FHEAD\u002Fplugins\u002Ffigma\u002Fskills\u002Ffigma-implement-motion","---\nname: figma-implement-motion\ndescription: 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`.\ndisable-model-invocation: false\n---\n\n# Implement Motion\n\n## Overview\n\nThis skill guides translation of Figma animations and transitions into runnable code (motion.dev, CSS keyframes, or framework-specific libraries).\n\nFigma exposes motion through two tools:\n\n- `get_motion_context` — authoritative motion tool. Returns the complete animated-node inventory, precomputed code snippets (CSS `@keyframes` + motion.dev), fallback keyframe bindings when snippets are unavailable, and recursive timeline coordination hints (`timelineCohorts`). **Source of truth for animation data and which node IDs animate.**\n- `get_design_context` — the design's **structure**: layout, sizing, assets, styling, Code Connect hints, screenshot context, and sometimes **motion placement markers** on animated elements (`data-node-id`, and on split nodes `data-motion-keys` \u002F `data-motion-wrapper-for` \u002F `data-motion-transform-template`). It may render an animated node as a plain element (`div`, `p`, `span`, etc.) or a motion element (`motion.div`); it does not inline the animation values.\n\n**The two are linked by node id, and that's the whole workflow.** `get_motion_context` tells you which nodes animate and gives the keyframe values, easing, timing, and snippets. `get_design_context` tells you what those nodes look like and where they sit. For every node in `get_motion_context.nodes`, find the matching `data-node-id` in design context and merge the motion into that structure — adding or wrapping a `motion.{tag}` when the structural element is plain. When design context has reused a Figma component, the motion node may also include `fallbackNodeId`; use it only as a fallback after trying the exact `nodeId`.\n\n## Skill Boundaries\n\n- Use this skill when the deliverable is motion code in the user's repository.\n- If the user asks to create\u002Fedit animations inside Figma itself, switch to [figma-use](..\u002Ffigma-use\u002FSKILL.md) and follow that skill instead.\n- This skill currently covers **animations** as emitted by `get_motion_context` (snippets plus fallback keyframe tracks, including preset-authored motion resolved into those forms). Broader interactive variant flows may still need product-specific state handling in code.\n\n## Prerequisites\n\n- Figma MCP server connected and accessible.\n- Node ID parsed from the Figma URL the user provides. URL format: `https:\u002F\u002Ffigma.com\u002Fdesign\u002F:fileKey\u002F:fileName?node-id=1-2` — extract `fileKey` (the segment after `\u002Fdesign\u002F`) and `nodeId` (the value of the `node-id` query parameter, e.g. `42-15`).\n- Target codebase. Motion output format adapts to stack (see [Framework Recommendations](#framework-recommendations)).\n\n## Tool Choice\n\nFor motion implementation, use both tools with distinct roles:\n\n| Situation | Tool | Why |\n|---|---|---|\n| Understanding static structure, assets, styles, Code Connect, or visual layout | `get_design_context` | Gives the component\u002Fpage code reference and asset URLs you need to place animated nodes correctly. |\n| Fetching animation data for any node | `get_motion_context` | Purpose-built for motion and the source of truth for timing, easing, snippets, and keyframes. |\n| A node has motion markers (`data-motion-keys`, `data-motion-wrapper-for`) | Markers for split *placement*, `get_motion_context` for *values* | Split markers tell you which tracks go on which element; the keyframes\u002Feasing\u002Ftiming and animated-node inventory come from `get_motion_context`. |\n\n`get_motion_context` accepts `recursive: true` (capped at 500 nodes) when you need descendants' motion in one call.\n\n## Required Workflow\n\n### Step 1: Confirm static design context is available\n\n```\nget_design_context(fileKey=\":fileKey\", nodeId=\"\u003Cnode-id>\")\n```\n\nIf `get_design_context` has already been called for this node, reuse that output. If not, call it normally now.\n\nUse it as the **structure of record** — hierarchy, sizing, styling, assets, Code Connect hints, screenshot context, and any motion placement markers it happens to include (Step 3). The animated-node inventory and animation values come from `get_motion_context` (Step 2).\n\n### Step 2: Fetch authoritative motion data\n\n```\nget_motion_context(fileKey=\":fileKey\", nodeId=\"\u003Cnode-id>\", recursive=true)\n```\n\nResponse shape (one entry per animated node):\n\n- `codeSnippets` — pre-generated CSS `@keyframes` and motion.dev strings. **Use these directly.** Do not regenerate them from fallback track data.\n- `keyframeBindings` — bound keyframe tracks, including preset-derived motion resolved into track data, included only as fallback data when both snippet formats are missing.\n- `motionSummary` — one-line-per-field natural-language description of the animation. Present **only when there's no snippet** (keyframe-bindings-only motion codegen couldn't express as CSS\u002Fmotion.dev). Build from it when present; ignore it whenever a snippet exists.\n- `fallbackNodeId` — optional fallback id for matching componentized design context. If `nodeId` is an instance-qualified id such as `I4005:6111;30:8005`, D2R may render the reusable component body with the backing component id instead, such as `4002:3957`. In that case, `fallbackNodeId` is the `data-node-id` to look for if exact `nodeId` lookup fails.\n\nRecursive responses also include `timelineCohorts` — a **top-level** array (not per-node) of nodes sharing one timeline: `{ rootNodeId, durationMs, loopMode: 'once' | 'loop' | 'boomerang', memberNodeIds[] }`. For coordinated multi-node motion, drive all `memberNodeIds` from one shared lifecycle using `durationMs` (÷1000 for seconds) and `loopMode` — don't infer timing from sibling order.\n\nImplementation details that matter for LLMs:\n\n- When a snippet exists, `motionSummary`, `timelineDurationMs`, and `transformOrigin` may be omitted to shrink the payload — the snippet already carries duration + transform-origin (motion.dev `duration` \u002F `style={{ transformOrigin }}`, or CSS `animation` \u002F `transform-origin`) and the cohort carries `durationMs`. A missing field never means \"no animation.\"\n- Recursive responses dedupe exact duplicate snippets. A snippet may be replaced with a comment pointing to the first node with identical motion; reuse the same component, variant, class, or constants instead of writing a second animation.\n- The MCP server infers CSS vs motion.dev snippets from `clientFrameworks`; if the response only contains one snippet format, adapt that format to the user's stack rather than assuming the other format failed.\n\n### Step 3: Merge static and motion context\n\n- Start from `get_motion_context.nodes`, not from visible `motion.*` tags in the static JSX. **Every returned node is animated.** Match each motion node back to `get_design_context` by exact `nodeId` \u002F `data-node-id` first. If and only if there is no exact match, try `fallbackNodeId` \u002F `data-node-id`. Fall back to node name\u002Ftype and screenshot position only after both ids fail.\n- **Exact id match wins over `fallbackNodeId`.** `fallbackNodeId` points at the backing component id that D2R may emit inside a reusable component. It is shared by every instance of that component. If the exact `nodeId` exists in design context, apply motion there and ignore the fallback. This is critical for root-instance animation: one instance can rotate or move differently from another instance of the same component, and applying that motion to the shared component body would animate all instances incorrectly.\n- **Apply each motion node to the matching design-context structure, keyed by `data-node-id`.** The matching `data-node-id` is the structural anchor, not always the final DOM element that receives motion. Use the snippet shape and placement markers to decide whether motion goes on that exact element, a wrapper, an inner element, or an inlined SVG path. `get_design_context` may already emit `motion.{tag}` with values stripped, or it may emit a plain structural element (`div`, `p`, `span`, component root, etc.). If it is plain and the snippet targets the element itself, convert it to the appropriate `motion.{tag}` or add a motion wrapper while preserving the node's text, children, classes\u002Fstyles, attributes, and `data-node-id`. Load [references\u002Fexamples-and-anti-examples.md](references\u002Fexamples-and-anti-examples.md) to see examples of this merging step.\n- **Componentized child motion usually matches by fallback.** When design context extracts a Figma instance into a reusable React component, children inside that component body often have backing component ids (`4002:3957`) while motion context reports live instance ids (`I4005:6111;30:8005`). In this case, use `fallbackNodeId` to find the component-body `data-node-id`, but keep the motion scoped to the rendered instance you are implementing. If there are multiple instances and only one has different root motion, exact id matching keeps that per-instance motion separate.\n- Split nodes carry a `data-motion-keys` \u002F `data-motion-wrapper-for` marker — see _Handling interleaved transforms_ below.\n- **Preserve `display: contents` wrappers — unless the group itself animates.** Layout-transparent group wrappers come through as `contents` (Tailwind `contents`), usually alongside a dead `absolute`\u002F`inset-[…]` (those do nothing on a `contents` box). For a _static_ group, keep `display: contents` and let the children position against the nearest real ancestor — converting the wrapper's `inset` into a positioned box reparents the children to a smaller box, so they render too small \u002F shifted inward. For an _animated_ group (the group node itself has motion), `display: contents` can't carry a transform — replace it with a real positioned wrapper and apply the group motion there. Load [references\u002Fgotchas.md](references\u002Fgotchas.md) before implementing this case.\n- **`get_motion_context` is the complete animated-node inventory.** Some animated nodes render as plain (non-`motion`) elements — component instance roots (plain positioning `\u003Cdiv>`), text (`\u003Cp>`), masks — that still carry a `data-node-id`. Walk every node in the motion response and apply its motion to the element with the matching `data-node-id`, wrapping or converting as needed. If an animated node has no element at all in the output (e.g. an animated mask flattened into a static `mask-image`), don't drop it silently — leave a `\u002F\u002F TODO: \u003CnodeId> motion unsupported` comment and call it out in your summary.\n- If a node appears in motion context but not in the static JSX, add the element needed to represent it — design-context code is a reference, not a complete animation inventory.\n- On conflict between design and motion context (timing\u002Feasing\u002Fanimated values), prefer `get_motion_context`.\n- **Path-level SVG motion: inline the SVG and animate the real `\u003Cpath>`.** When `get_motion_context` targets a vector's path (`PATH_TRIM`, `motion.path`, `stroke-dasharray`) but design context renders it as an `\u003Cimg>`, inline the SVG and apply the snippet to the `\u003Cpath>`, keeping the layout wrapper. Load [references\u002Fsvg-and-path-motion.md](references\u002Fsvg-and-path-motion.md) for the full how-to for this case (motion.path, `pathLength=\"1\"`, wrapper+path layering, CSS path-trim).\n\n#### Handling interleaved transforms\n\nA node with **both** a static base transform and animated transforms is split across nested elements so the two compose correctly instead of fighting: an id-less `motion.div` carrying `data-motion-wrapper-for=\"\u003CnodeId>\"` (the OUTER wrapper) wraps a static-transform div (e.g. `rotate-45` + `hypot()` sizing — or the wrapper itself carries `data-motion-transform-template=\"\u003Ccss>\"`) which wraps the INNER node (`data-node-id`). Keep the `wrapper > static-transform div > inner` nesting — collapsing it breaks sizing and the base transform.\n\n- **Place tracks by `data-motion-keys`.** The wrapper's `data-motion-keys` (transform tracks — `x`\u002F`y`\u002F`rotate`\u002F`scaleX`\u002F`scaleY`\u002F`skewX`) go on the OUTER wrapper; the inner element's `data-motion-keys` go on the INNER element.\n- **Re-apply a `data-motion-transform-template`.** If the wrapper carries one, set `transformTemplate={(_, generated) => \"\u003Ccss> \" + generated}` so the animated transform composes on top of that static layout transform.\n- **Offset the animated transform by the static base (avoid double rotation).** `get_motion_context` gives the node's _absolute_ transform, which already includes whatever static base those divs apply. A `rotate` snippet of `[45, 125, 125]` over a `rotate-45` base means the wrapper animates the **offset** `[0, 80, 80]` (= absolute − 45), not the absolute — else the 45° applies twice and the element sits at 90° at rest. Tracks with no static base (e.g. `x`\u002F`y` starting at 0) pass through unchanged. See the interleaved-transform example.\n- **Keep layout transforms separate from Motion transforms.** For every `motion.*` element that animates `rotate`, `scale`, or `skew`, verify it does not also rely on Tailwind layout transforms such as `-translate-x-1\u002F2` or `-translate-y-1\u002F2` for centering\u002Fpositioning. Those utilities share the CSS `transform` property that Motion.dev writes inline, so Motion's transform can erase the layout translate. If both are needed, split the element into a static layout wrapper carrying the centering\u002Fpositioning transform and an inner `motion.*` element carrying animated rotate\u002Fscale\u002Fopacity, or encode the layout offset in Motion itself (`x: \"-50%\"`) and keep it present for every keyframe.\n\n### Step 4: Apply the motion in code\n\n- **motion.dev present in snippets?** Use the motion.dev code verbatim for React targets. Import from `motion\u002Freact` — unless the codebase already uses another motion library (Framer Motion, React Spring, GSAP), in which case adapt the snippet to it. Load [references\u002Fframework-recommendations.md](references\u002Fframework-recommendations.md) when adapting to another stack or choosing a library.\n- **CSS keyframes present?** Use for vanilla\u002Fnon-React targets, or when the codebase has no React motion library.\n- **No snippets (keyframe-bindings-only)?** Build equivalent motion.dev\u002FCSS from `keyframeBindings` + `motionSummary`, taking loop timing from the cohort's `durationMs` \u002F `loopMode` and reading `transformOrigin` \u002F duration from the structured fields. Rare — snippets are normally present, including for SwiftUI\u002FiOS (which get the CSS format).\n\n### Step 5: Validate\n\n- Read the component's existing motion imports\u002Fconventions before adding new ones. If the user already uses Framer Motion \u002F React Spring \u002F anime.js, adapt rather than forcing motion.dev.\n- Spot-check one animation runs end-to-end (reload, observe, iterate) before batching changes across many nodes.\n- Load [references\u002Fgotchas.md](references\u002Fgotchas.md), which covers specific bugs and edge cases seen in Figma motion output, and correct any such cases in the generated code.\n\n## Critical Rules\n\nThese are the general principles. Specific gotchas (rotation pivots, HOLD semantics, color interpolation, etc.) live in the categorized [references](#references). When a linked reference is mentioned in this skill text and the situation applies, load that file before continuing.\n\n1. **Respect the tool's output's *values*, not its layout.** Preserve the exact timing, easing, keyframe values, and `transformOrigin` from `codeSnippets` — don't regenerate them from `keyframeBindings` or the structured fields when snippets exist (regenerating loses fidelity on custom bezier easings, spring approximations, and overshoot values). `transformOrigin` is **per element**: apply each scaling\u002Frotating node's own — including nested scalers, not just the outer wrapper — or the element pivots from the default center and grows\u002Fspins from the wrong corner (see the per-element-`transformOrigin` example). But the snippet is one node's data, not a copy-paste template: when many nodes share it, factor it per Rule 7 instead of pasting the block N times.\n2. **Match the user's existing motion stack.** Read the component's imports and any sibling animations before adding dependencies. If the user already has Framer Motion, React Spring, anime.js, GSAP — adapt the output to their stack rather than forcing motion.dev.\n3. **Honor `prefers-reduced-motion`.** Any motion added must soften or disable under `@media (prefers-reduced-motion: reduce)` — typically skip the `animate` (render the initial\u002Fresting state) or cut the duration to near-zero. This is an accessibility default, not an opt-in.\n4. **Validate one animation end-to-end before batching.** Build, reload, and watch one full timeline loop — confirm each animated node appears at the time its keyframe track says it should. \"Renders without error\" is not \"renders correctly.\" Motion failures compound when you batch — a wrong easing on one node is easy to spot; the same bug across twenty nodes is hours of untangling.\n5. **Don't fabricate motion.** If a node has no motion data in the response, leave it static. Do not borrow easing\u002Fduration defaults from elsewhere in the design, and do not auto-animate \"because the rest of the component is animated.\"\n6. **Don't download an asset just to `Read` it.** `get_design_context` \u002F `get_motion_context` return assets as URLs (`\u002Fapi\u002Fmcp\u002Fasset\u002F...`), often SVG. Reference the URL directly where the consumer fetches it (an `\u003Cimg src>`, CSS `background-image`, an asset import), or `curl` one to inline its contents (e.g. inline the SVG and render via `NSImage(data:)` on SwiftUI). The important exception is path-level SVG motion: if the motion snippet targets a path inside an SVG asset, inline the SVG and animate the real path instead of leaving it behind an `\u003Cimg>`. Don't download an asset and feed the file to the `Read` tool: SVG isn't a Read-able image format, so the read is rejected and wasted — and a file tool that doesn't detect SVG-as-image can stall the loop on it.\n7. **Factor out repeated motion — never copy-paste the snippet per element.** Many nodes usually share the *same* animation differing only by a stagger delay, offset, or target value. Implement the shared motion **once** — a reusable animated component or a `variants` object parameterized by the values that vary — render from a mapped array (`items.map(...)`), and pull repeated literals (durations, easing arrays, offsets) into named constants. The animation's *values* stay verbatim from the snippet (Rule 1); the *code* stays DRY. The same transition object pasted 15+ times (800 lines that should be 150) is a low-quality result — fidelity and maintainability are both graded.\n\n## Framework Recommendations\n\nRule 2 covers the general posture: prefer the user's existing stack. When none exists, defaults:\n\n- **React**: [motion.dev](https:\u002F\u002Fmotion.dev) (the `motion` package). The tool returns motion.dev code directly — use it.\n- **Vanilla \u002F non-React web**: CSS `@keyframes` with `animation` shorthand, returned directly by the tool.\n- **SwiftUI**: Native `.animation(...)` modifiers, translated from the **CSS** snippet (`get_motion_context` emits no SwiftUI code, but SwiftUI\u002FiOS clients still get the CSS format; fall back to `keyframeBindings` \u002F `motionSummary` \u002F cohort only when snippet-less). **Use only real SwiftUI APIs** — no modifier takes a Figma\u002FCSS easing directly, so load [references\u002Fframework-recommendations.md](references\u002Fframework-recommendations.md#swiftui-translation), map the easing to its SwiftUI equivalent, and verify rather than invent. This path is evolving; confirm with the user if unsure.\n\n**For established effect classes, prefer a library over hand-rolled CSS.** Effects like glass\u002Fglassmorphism, confetti, particle systems, physics-based interactions, and scroll-linked motion have battle-tested library implementations that handle cross-browser quirks, accessibility, and performance far better than generated keyframes. Load [references\u002Fframework-recommendations.md](references\u002Fframework-recommendations.md) for the full library-by-effect-class table. Surface these as recommendations, not mandates — the user decides.\n\n## Examples\n\nLoad [references\u002Fexamples-and-anti-examples.md](references\u002Fexamples-and-anti-examples.md) when you need worked examples or failure patterns. It covers the simple merge flow, plain text elements that need `motion.*` added, interleaved static+animated transforms, SVG path-level motion, and anti-examples for DOM rebuilding, node-id\u002Fposition drift, and missing per-element `transformOrigin`.\n\n## References\n\nSix deep dives, fetched on demand. General frontend concerns (performance, units, accessibility mechanics) are handled by the critical rules above — these references focus on Figma-specific signal only. If this skill names one of these files in an inline instruction, load that file before continuing with that part of the task.\n\n- [references\u002Fexamples-and-anti-examples.md](references\u002Fexamples-and-anti-examples.md) — worked examples and failure patterns. Load when applying the merge workflow, handling interleaved transforms, or checking whether a generated implementation has rebuilt the DOM, swapped node positions, or dropped `transformOrigin`.\n- [references\u002Fgotchas.md](references\u002Fgotchas.md) — Figma-specific motion bugs and their fixes. Rotation\u002Fscale origin on nested groups, HOLD easing semantics, CUSTOM_SPRING preservation, independent axis scaling ambiguity, color interpolation. Load when troubleshooting unexpected runtime behavior. **Always load [references\u002Fmotion-lint-rules.md](references\u002Fmotion-lint-rules.md) alongside this file** — gotcha entries reference specific lint rules that must be surfaced to the user.\n- [references\u002Fsvg-and-path-motion.md](references\u002Fsvg-and-path-motion.md) — implementing motion that targets an SVG vector path (inline the asset, `motion.path`, `pathLength=\"1\"`, wrapper+path layering, CSS path-trim). Load when a vector's snippet targets the path, not a wrapper transform.\n- [references\u002Fframework-recommendations.md](references\u002Fframework-recommendations.md) — motion.dev, CSS keyframes, SwiftUI defaults, library-by-effect-class table (glass, confetti, particles, physics, scroll-linked). Load before hand-rolling an effect.\n- [references\u002Funsupported-and-fallbacks.md](references\u002Funsupported-and-fallbacks.md) — Figma motion features that don't export cleanly today (text animations, path animations, masks\u002Fbooleans, variants\u002Ftransitions). Includes video\u002Flottie fallback guidance. Load when the tool response seems incomplete. **Always load [references\u002Fmotion-lint-rules.md](references\u002Fmotion-lint-rules.md) alongside this file** — unsupported entries reference specific lint rules that must be surfaced to the user.\n- [references\u002Fmotion-lint-rules.md](references\u002Fmotion-lint-rules.md) — Linting rules: known export limitations (errors and warnings) that must be surfaced to the user. Load when generating motion code to check whether any active limitations apply.\n",{"data":37,"body":39},{"name":4,"description":6,"disable-model-invocation":38},false,{"type":40,"children":41},"root",[42,51,58,64,69,194,257,263,304,310,382,388,393,524,542,548,555,567,579,598,604,613,618,729,780,785,869,875,1367,1373,1439,1688,1694,1775,1781,1805,1811,1824,2085,2090,2095,2208,2224,2230,2253,2258,2263],{"type":43,"tag":44,"props":45,"children":47},"element","h1",{"id":46},"implement-motion",[48],{"type":49,"value":50},"text","Implement Motion",{"type":43,"tag":52,"props":53,"children":55},"h2",{"id":54},"overview",[56],{"type":49,"value":57},"Overview",{"type":43,"tag":59,"props":60,"children":61},"p",{},[62],{"type":49,"value":63},"This skill guides translation of Figma animations and transitions into runnable code (motion.dev, CSS keyframes, or framework-specific libraries).",{"type":43,"tag":59,"props":65,"children":66},{},[67],{"type":49,"value":68},"Figma exposes motion through two tools:",{"type":43,"tag":70,"props":71,"children":72},"ul",{},[73,108],{"type":43,"tag":74,"props":75,"children":76},"li",{},[77,84,86,92,94,100,102],{"type":43,"tag":78,"props":79,"children":81},"code",{"className":80},[],[82],{"type":49,"value":83},"get_motion_context",{"type":49,"value":85}," — authoritative motion tool. Returns the complete animated-node inventory, precomputed code snippets (CSS ",{"type":43,"tag":78,"props":87,"children":89},{"className":88},[],[90],{"type":49,"value":91},"@keyframes",{"type":49,"value":93}," + motion.dev), fallback keyframe bindings when snippets are unavailable, and recursive timeline coordination hints (",{"type":43,"tag":78,"props":95,"children":97},{"className":96},[],[98],{"type":49,"value":99},"timelineCohorts",{"type":49,"value":101},"). ",{"type":43,"tag":103,"props":104,"children":105},"strong",{},[106],{"type":49,"value":107},"Source of truth for animation data and which node IDs animate.",{"type":43,"tag":74,"props":109,"children":110},{},[111,117,119,124,126,131,133,139,141,147,149,155,156,162,164,170,172,177,178,184,186,192],{"type":43,"tag":78,"props":112,"children":114},{"className":113},[],[115],{"type":49,"value":116},"get_design_context",{"type":49,"value":118}," — the design's ",{"type":43,"tag":103,"props":120,"children":121},{},[122],{"type":49,"value":123},"structure",{"type":49,"value":125},": layout, sizing, assets, styling, Code Connect hints, screenshot context, and sometimes ",{"type":43,"tag":103,"props":127,"children":128},{},[129],{"type":49,"value":130},"motion placement markers",{"type":49,"value":132}," on animated elements (",{"type":43,"tag":78,"props":134,"children":136},{"className":135},[],[137],{"type":49,"value":138},"data-node-id",{"type":49,"value":140},", and on split nodes ",{"type":43,"tag":78,"props":142,"children":144},{"className":143},[],[145],{"type":49,"value":146},"data-motion-keys",{"type":49,"value":148}," \u002F ",{"type":43,"tag":78,"props":150,"children":152},{"className":151},[],[153],{"type":49,"value":154},"data-motion-wrapper-for",{"type":49,"value":148},{"type":43,"tag":78,"props":157,"children":159},{"className":158},[],[160],{"type":49,"value":161},"data-motion-transform-template",{"type":49,"value":163},"). It may render an animated node as a plain element (",{"type":43,"tag":78,"props":165,"children":167},{"className":166},[],[168],{"type":49,"value":169},"div",{"type":49,"value":171},", ",{"type":43,"tag":78,"props":173,"children":175},{"className":174},[],[176],{"type":49,"value":59},{"type":49,"value":171},{"type":43,"tag":78,"props":179,"children":181},{"className":180},[],[182],{"type":49,"value":183},"span",{"type":49,"value":185},", etc.) or a motion element (",{"type":43,"tag":78,"props":187,"children":189},{"className":188},[],[190],{"type":49,"value":191},"motion.div",{"type":49,"value":193},"); it does not inline the animation values.",{"type":43,"tag":59,"props":195,"children":196},{},[197,202,204,209,211,216,218,224,226,231,233,239,241,247,249,255],{"type":43,"tag":103,"props":198,"children":199},{},[200],{"type":49,"value":201},"The two are linked by node id, and that's the whole workflow.",{"type":49,"value":203}," ",{"type":43,"tag":78,"props":205,"children":207},{"className":206},[],[208],{"type":49,"value":83},{"type":49,"value":210}," tells you which nodes animate and gives the keyframe values, easing, timing, and snippets. ",{"type":43,"tag":78,"props":212,"children":214},{"className":213},[],[215],{"type":49,"value":116},{"type":49,"value":217}," tells you what those nodes look like and where they sit. For every node in ",{"type":43,"tag":78,"props":219,"children":221},{"className":220},[],[222],{"type":49,"value":223},"get_motion_context.nodes",{"type":49,"value":225},", find the matching ",{"type":43,"tag":78,"props":227,"children":229},{"className":228},[],[230],{"type":49,"value":138},{"type":49,"value":232}," in design context and merge the motion into that structure — adding or wrapping a ",{"type":43,"tag":78,"props":234,"children":236},{"className":235},[],[237],{"type":49,"value":238},"motion.{tag}",{"type":49,"value":240}," when the structural element is plain. When design context has reused a Figma component, the motion node may also include ",{"type":43,"tag":78,"props":242,"children":244},{"className":243},[],[245],{"type":49,"value":246},"fallbackNodeId",{"type":49,"value":248},"; use it only as a fallback after trying the exact ",{"type":43,"tag":78,"props":250,"children":252},{"className":251},[],[253],{"type":49,"value":254},"nodeId",{"type":49,"value":256},".",{"type":43,"tag":52,"props":258,"children":260},{"id":259},"skill-boundaries",[261],{"type":49,"value":262},"Skill Boundaries",{"type":43,"tag":70,"props":264,"children":265},{},[266,271,285],{"type":43,"tag":74,"props":267,"children":268},{},[269],{"type":49,"value":270},"Use this skill when the deliverable is motion code in the user's repository.",{"type":43,"tag":74,"props":272,"children":273},{},[274,276,283],{"type":49,"value":275},"If the user asks to create\u002Fedit animations inside Figma itself, switch to ",{"type":43,"tag":277,"props":278,"children":280},"a",{"href":279},"..\u002Ffigma-use\u002FSKILL.md",[281],{"type":49,"value":282},"figma-use",{"type":49,"value":284}," and follow that skill instead.",{"type":43,"tag":74,"props":286,"children":287},{},[288,290,295,297,302],{"type":49,"value":289},"This skill currently covers ",{"type":43,"tag":103,"props":291,"children":292},{},[293],{"type":49,"value":294},"animations",{"type":49,"value":296}," as emitted by ",{"type":43,"tag":78,"props":298,"children":300},{"className":299},[],[301],{"type":49,"value":83},{"type":49,"value":303}," (snippets plus fallback keyframe tracks, including preset-authored motion resolved into those forms). Broader interactive variant flows may still need product-specific state handling in code.",{"type":43,"tag":52,"props":305,"children":307},{"id":306},"prerequisites",[308],{"type":49,"value":309},"Prerequisites",{"type":43,"tag":70,"props":311,"children":312},{},[313,318,370],{"type":43,"tag":74,"props":314,"children":315},{},[316],{"type":49,"value":317},"Figma MCP server connected and accessible.",{"type":43,"tag":74,"props":319,"children":320},{},[321,323,329,331,337,339,345,347,352,354,360,362,368],{"type":49,"value":322},"Node ID parsed from the Figma URL the user provides. URL format: ",{"type":43,"tag":78,"props":324,"children":326},{"className":325},[],[327],{"type":49,"value":328},"https:\u002F\u002Ffigma.com\u002Fdesign\u002F:fileKey\u002F:fileName?node-id=1-2",{"type":49,"value":330}," — extract ",{"type":43,"tag":78,"props":332,"children":334},{"className":333},[],[335],{"type":49,"value":336},"fileKey",{"type":49,"value":338}," (the segment after ",{"type":43,"tag":78,"props":340,"children":342},{"className":341},[],[343],{"type":49,"value":344},"\u002Fdesign\u002F",{"type":49,"value":346},") and ",{"type":43,"tag":78,"props":348,"children":350},{"className":349},[],[351],{"type":49,"value":254},{"type":49,"value":353}," (the value of the ",{"type":43,"tag":78,"props":355,"children":357},{"className":356},[],[358],{"type":49,"value":359},"node-id",{"type":49,"value":361}," query parameter, e.g. ",{"type":43,"tag":78,"props":363,"children":365},{"className":364},[],[366],{"type":49,"value":367},"42-15",{"type":49,"value":369},").",{"type":43,"tag":74,"props":371,"children":372},{},[373,375,381],{"type":49,"value":374},"Target codebase. Motion output format adapts to stack (see ",{"type":43,"tag":277,"props":376,"children":378},{"href":377},"#framework-recommendations",[379],{"type":49,"value":380},"Framework Recommendations",{"type":49,"value":369},{"type":43,"tag":52,"props":383,"children":385},{"id":384},"tool-choice",[386],{"type":49,"value":387},"Tool Choice",{"type":43,"tag":59,"props":389,"children":390},{},[391],{"type":49,"value":392},"For motion implementation, use both tools with distinct roles:",{"type":43,"tag":394,"props":395,"children":396},"table",{},[397,421],{"type":43,"tag":398,"props":399,"children":400},"thead",{},[401],{"type":43,"tag":402,"props":403,"children":404},"tr",{},[405,411,416],{"type":43,"tag":406,"props":407,"children":408},"th",{},[409],{"type":49,"value":410},"Situation",{"type":43,"tag":406,"props":412,"children":413},{},[414],{"type":49,"value":415},"Tool",{"type":43,"tag":406,"props":417,"children":418},{},[419],{"type":49,"value":420},"Why",{"type":43,"tag":422,"props":423,"children":424},"tbody",{},[425,447,468],{"type":43,"tag":402,"props":426,"children":427},{},[428,434,442],{"type":43,"tag":429,"props":430,"children":431},"td",{},[432],{"type":49,"value":433},"Understanding static structure, assets, styles, Code Connect, or visual layout",{"type":43,"tag":429,"props":435,"children":436},{},[437],{"type":43,"tag":78,"props":438,"children":440},{"className":439},[],[441],{"type":49,"value":116},{"type":43,"tag":429,"props":443,"children":444},{},[445],{"type":49,"value":446},"Gives the component\u002Fpage code reference and asset URLs you need to place animated nodes correctly.",{"type":43,"tag":402,"props":448,"children":449},{},[450,455,463],{"type":43,"tag":429,"props":451,"children":452},{},[453],{"type":49,"value":454},"Fetching animation data for any node",{"type":43,"tag":429,"props":456,"children":457},{},[458],{"type":43,"tag":78,"props":459,"children":461},{"className":460},[],[462],{"type":49,"value":83},{"type":43,"tag":429,"props":464,"children":465},{},[466],{"type":49,"value":467},"Purpose-built for motion and the source of truth for timing, easing, snippets, and keyframes.",{"type":43,"tag":402,"props":469,"children":470},{},[471,489,513],{"type":43,"tag":429,"props":472,"children":473},{},[474,476,481,482,487],{"type":49,"value":475},"A node has motion markers (",{"type":43,"tag":78,"props":477,"children":479},{"className":478},[],[480],{"type":49,"value":146},{"type":49,"value":171},{"type":43,"tag":78,"props":483,"children":485},{"className":484},[],[486],{"type":49,"value":154},{"type":49,"value":488},")",{"type":43,"tag":429,"props":490,"children":491},{},[492,494,500,501,506,508],{"type":49,"value":493},"Markers for split ",{"type":43,"tag":495,"props":496,"children":497},"em",{},[498],{"type":49,"value":499},"placement",{"type":49,"value":171},{"type":43,"tag":78,"props":502,"children":504},{"className":503},[],[505],{"type":49,"value":83},{"type":49,"value":507}," for ",{"type":43,"tag":495,"props":509,"children":510},{},[511],{"type":49,"value":512},"values",{"type":43,"tag":429,"props":514,"children":515},{},[516,518,523],{"type":49,"value":517},"Split markers tell you which tracks go on which element; the keyframes\u002Feasing\u002Ftiming and animated-node inventory come from ",{"type":43,"tag":78,"props":519,"children":521},{"className":520},[],[522],{"type":49,"value":83},{"type":49,"value":256},{"type":43,"tag":59,"props":525,"children":526},{},[527,532,534,540],{"type":43,"tag":78,"props":528,"children":530},{"className":529},[],[531],{"type":49,"value":83},{"type":49,"value":533}," accepts ",{"type":43,"tag":78,"props":535,"children":537},{"className":536},[],[538],{"type":49,"value":539},"recursive: true",{"type":49,"value":541}," (capped at 500 nodes) when you need descendants' motion in one call.",{"type":43,"tag":52,"props":543,"children":545},{"id":544},"required-workflow",[546],{"type":49,"value":547},"Required Workflow",{"type":43,"tag":549,"props":550,"children":552},"h3",{"id":551},"step-1-confirm-static-design-context-is-available",[553],{"type":49,"value":554},"Step 1: Confirm static design context is available",{"type":43,"tag":556,"props":557,"children":561},"pre",{"className":558,"code":560,"language":49},[559],"language-text","get_design_context(fileKey=\":fileKey\", nodeId=\"\u003Cnode-id>\")\n",[562],{"type":43,"tag":78,"props":563,"children":565},{"__ignoreMap":564},"",[566],{"type":49,"value":560},{"type":43,"tag":59,"props":568,"children":569},{},[570,572,577],{"type":49,"value":571},"If ",{"type":43,"tag":78,"props":573,"children":575},{"className":574},[],[576],{"type":49,"value":116},{"type":49,"value":578}," has already been called for this node, reuse that output. If not, call it normally now.",{"type":43,"tag":59,"props":580,"children":581},{},[582,584,589,591,596],{"type":49,"value":583},"Use it as the ",{"type":43,"tag":103,"props":585,"children":586},{},[587],{"type":49,"value":588},"structure of record",{"type":49,"value":590}," — hierarchy, sizing, styling, assets, Code Connect hints, screenshot context, and any motion placement markers it happens to include (Step 3). The animated-node inventory and animation values come from ",{"type":43,"tag":78,"props":592,"children":594},{"className":593},[],[595],{"type":49,"value":83},{"type":49,"value":597}," (Step 2).",{"type":43,"tag":549,"props":599,"children":601},{"id":600},"step-2-fetch-authoritative-motion-data",[602],{"type":49,"value":603},"Step 2: Fetch authoritative motion data",{"type":43,"tag":556,"props":605,"children":608},{"className":606,"code":607,"language":49},[559],"get_motion_context(fileKey=\":fileKey\", nodeId=\"\u003Cnode-id>\", recursive=true)\n",[609],{"type":43,"tag":78,"props":610,"children":611},{"__ignoreMap":564},[612],{"type":49,"value":607},{"type":43,"tag":59,"props":614,"children":615},{},[616],{"type":49,"value":617},"Response shape (one entry per animated node):",{"type":43,"tag":70,"props":619,"children":620},{},[621,646,657,675],{"type":43,"tag":74,"props":622,"children":623},{},[624,630,632,637,639,644],{"type":43,"tag":78,"props":625,"children":627},{"className":626},[],[628],{"type":49,"value":629},"codeSnippets",{"type":49,"value":631}," — pre-generated CSS ",{"type":43,"tag":78,"props":633,"children":635},{"className":634},[],[636],{"type":49,"value":91},{"type":49,"value":638}," and motion.dev strings. ",{"type":43,"tag":103,"props":640,"children":641},{},[642],{"type":49,"value":643},"Use these directly.",{"type":49,"value":645}," Do not regenerate them from fallback track data.",{"type":43,"tag":74,"props":647,"children":648},{},[649,655],{"type":43,"tag":78,"props":650,"children":652},{"className":651},[],[653],{"type":49,"value":654},"keyframeBindings",{"type":49,"value":656}," — bound keyframe tracks, including preset-derived motion resolved into track data, included only as fallback data when both snippet formats are missing.",{"type":43,"tag":74,"props":658,"children":659},{},[660,666,668,673],{"type":43,"tag":78,"props":661,"children":663},{"className":662},[],[664],{"type":49,"value":665},"motionSummary",{"type":49,"value":667}," — one-line-per-field natural-language description of the animation. Present ",{"type":43,"tag":103,"props":669,"children":670},{},[671],{"type":49,"value":672},"only when there's no snippet",{"type":49,"value":674}," (keyframe-bindings-only motion codegen couldn't express as CSS\u002Fmotion.dev). Build from it when present; ignore it whenever a snippet exists.",{"type":43,"tag":74,"props":676,"children":677},{},[678,683,685,690,692,698,700,706,708,713,715,720,722,727],{"type":43,"tag":78,"props":679,"children":681},{"className":680},[],[682],{"type":49,"value":246},{"type":49,"value":684}," — optional fallback id for matching componentized design context. If ",{"type":43,"tag":78,"props":686,"children":688},{"className":687},[],[689],{"type":49,"value":254},{"type":49,"value":691}," is an instance-qualified id such as ",{"type":43,"tag":78,"props":693,"children":695},{"className":694},[],[696],{"type":49,"value":697},"I4005:6111;30:8005",{"type":49,"value":699},", D2R may render the reusable component body with the backing component id instead, such as ",{"type":43,"tag":78,"props":701,"children":703},{"className":702},[],[704],{"type":49,"value":705},"4002:3957",{"type":49,"value":707},". In that case, ",{"type":43,"tag":78,"props":709,"children":711},{"className":710},[],[712],{"type":49,"value":246},{"type":49,"value":714}," is the ",{"type":43,"tag":78,"props":716,"children":718},{"className":717},[],[719],{"type":49,"value":138},{"type":49,"value":721}," to look for if exact ",{"type":43,"tag":78,"props":723,"children":725},{"className":724},[],[726],{"type":49,"value":254},{"type":49,"value":728}," lookup fails.",{"type":43,"tag":59,"props":730,"children":731},{},[732,734,739,741,746,748,754,756,762,764,770,772,778],{"type":49,"value":733},"Recursive responses also include ",{"type":43,"tag":78,"props":735,"children":737},{"className":736},[],[738],{"type":49,"value":99},{"type":49,"value":740}," — a ",{"type":43,"tag":103,"props":742,"children":743},{},[744],{"type":49,"value":745},"top-level",{"type":49,"value":747}," array (not per-node) of nodes sharing one timeline: ",{"type":43,"tag":78,"props":749,"children":751},{"className":750},[],[752],{"type":49,"value":753},"{ rootNodeId, durationMs, loopMode: 'once' | 'loop' | 'boomerang', memberNodeIds[] }",{"type":49,"value":755},". For coordinated multi-node motion, drive all ",{"type":43,"tag":78,"props":757,"children":759},{"className":758},[],[760],{"type":49,"value":761},"memberNodeIds",{"type":49,"value":763}," from one shared lifecycle using ",{"type":43,"tag":78,"props":765,"children":767},{"className":766},[],[768],{"type":49,"value":769},"durationMs",{"type":49,"value":771}," (÷1000 for seconds) and ",{"type":43,"tag":78,"props":773,"children":775},{"className":774},[],[776],{"type":49,"value":777},"loopMode",{"type":49,"value":779}," — don't infer timing from sibling order.",{"type":43,"tag":59,"props":781,"children":782},{},[783],{"type":49,"value":784},"Implementation details that matter for LLMs:",{"type":43,"tag":70,"props":786,"children":787},{},[788,851,856],{"type":43,"tag":74,"props":789,"children":790},{},[791,793,798,799,805,807,813,815,821,822,828,830,835,836,842,844,849],{"type":49,"value":792},"When a snippet exists, ",{"type":43,"tag":78,"props":794,"children":796},{"className":795},[],[797],{"type":49,"value":665},{"type":49,"value":171},{"type":43,"tag":78,"props":800,"children":802},{"className":801},[],[803],{"type":49,"value":804},"timelineDurationMs",{"type":49,"value":806},", and ",{"type":43,"tag":78,"props":808,"children":810},{"className":809},[],[811],{"type":49,"value":812},"transformOrigin",{"type":49,"value":814}," may be omitted to shrink the payload — the snippet already carries duration + transform-origin (motion.dev ",{"type":43,"tag":78,"props":816,"children":818},{"className":817},[],[819],{"type":49,"value":820},"duration",{"type":49,"value":148},{"type":43,"tag":78,"props":823,"children":825},{"className":824},[],[826],{"type":49,"value":827},"style={{ transformOrigin }}",{"type":49,"value":829},", or CSS ",{"type":43,"tag":78,"props":831,"children":833},{"className":832},[],[834],{"type":49,"value":14},{"type":49,"value":148},{"type":43,"tag":78,"props":837,"children":839},{"className":838},[],[840],{"type":49,"value":841},"transform-origin",{"type":49,"value":843},") and the cohort carries ",{"type":43,"tag":78,"props":845,"children":847},{"className":846},[],[848],{"type":49,"value":769},{"type":49,"value":850},". A missing field never means \"no animation.\"",{"type":43,"tag":74,"props":852,"children":853},{},[854],{"type":49,"value":855},"Recursive responses dedupe exact duplicate snippets. A snippet may be replaced with a comment pointing to the first node with identical motion; reuse the same component, variant, class, or constants instead of writing a second animation.",{"type":43,"tag":74,"props":857,"children":858},{},[859,861,867],{"type":49,"value":860},"The MCP server infers CSS vs motion.dev snippets from ",{"type":43,"tag":78,"props":862,"children":864},{"className":863},[],[865],{"type":49,"value":866},"clientFrameworks",{"type":49,"value":868},"; if the response only contains one snippet format, adapt that format to the user's stack rather than assuming the other format failed.",{"type":43,"tag":549,"props":870,"children":872},{"id":871},"step-3-merge-static-and-motion-context",[873],{"type":49,"value":874},"Step 3: Merge static and motion context",{"type":43,"tag":70,"props":876,"children":877},{},[878,938,967,1044,1082,1107,1206,1275,1280,1291],{"type":43,"tag":74,"props":879,"children":880},{},[881,883,888,890,896,898,903,905,910,912,917,918,923,925,930,931,936],{"type":49,"value":882},"Start from ",{"type":43,"tag":78,"props":884,"children":886},{"className":885},[],[887],{"type":49,"value":223},{"type":49,"value":889},", not from visible ",{"type":43,"tag":78,"props":891,"children":893},{"className":892},[],[894],{"type":49,"value":895},"motion.*",{"type":49,"value":897}," tags in the static JSX. ",{"type":43,"tag":103,"props":899,"children":900},{},[901],{"type":49,"value":902},"Every returned node is animated.",{"type":49,"value":904}," Match each motion node back to ",{"type":43,"tag":78,"props":906,"children":908},{"className":907},[],[909],{"type":49,"value":116},{"type":49,"value":911}," by exact ",{"type":43,"tag":78,"props":913,"children":915},{"className":914},[],[916],{"type":49,"value":254},{"type":49,"value":148},{"type":43,"tag":78,"props":919,"children":921},{"className":920},[],[922],{"type":49,"value":138},{"type":49,"value":924}," first. If and only if there is no exact match, try ",{"type":43,"tag":78,"props":926,"children":928},{"className":927},[],[929],{"type":49,"value":246},{"type":49,"value":148},{"type":43,"tag":78,"props":932,"children":934},{"className":933},[],[935],{"type":49,"value":138},{"type":49,"value":937},". Fall back to node name\u002Ftype and screenshot position only after both ids fail.",{"type":43,"tag":74,"props":939,"children":940},{},[941,952,953,958,960,965],{"type":43,"tag":103,"props":942,"children":943},{},[944,946,951],{"type":49,"value":945},"Exact id match wins over ",{"type":43,"tag":78,"props":947,"children":949},{"className":948},[],[950],{"type":49,"value":246},{"type":49,"value":256},{"type":49,"value":203},{"type":43,"tag":78,"props":954,"children":956},{"className":955},[],[957],{"type":49,"value":246},{"type":49,"value":959}," points at the backing component id that D2R may emit inside a reusable component. It is shared by every instance of that component. If the exact ",{"type":43,"tag":78,"props":961,"children":963},{"className":962},[],[964],{"type":49,"value":254},{"type":49,"value":966}," exists in design context, apply motion there and ignore the fallback. This is critical for root-instance animation: one instance can rotate or move differently from another instance of the same component, and applying that motion to the shared component body would animate all instances incorrectly.",{"type":43,"tag":74,"props":968,"children":969},{},[970,981,983,988,990,995,997,1002,1004,1009,1010,1015,1016,1021,1023,1028,1030,1035,1037,1042],{"type":43,"tag":103,"props":971,"children":972},{},[973,975,980],{"type":49,"value":974},"Apply each motion node to the matching design-context structure, keyed by ",{"type":43,"tag":78,"props":976,"children":978},{"className":977},[],[979],{"type":49,"value":138},{"type":49,"value":256},{"type":49,"value":982}," The matching ",{"type":43,"tag":78,"props":984,"children":986},{"className":985},[],[987],{"type":49,"value":138},{"type":49,"value":989}," is the structural anchor, not always the final DOM element that receives motion. Use the snippet shape and placement markers to decide whether motion goes on that exact element, a wrapper, an inner element, or an inlined SVG path. ",{"type":43,"tag":78,"props":991,"children":993},{"className":992},[],[994],{"type":49,"value":116},{"type":49,"value":996}," may already emit ",{"type":43,"tag":78,"props":998,"children":1000},{"className":999},[],[1001],{"type":49,"value":238},{"type":49,"value":1003}," with values stripped, or it may emit a plain structural element (",{"type":43,"tag":78,"props":1005,"children":1007},{"className":1006},[],[1008],{"type":49,"value":169},{"type":49,"value":171},{"type":43,"tag":78,"props":1011,"children":1013},{"className":1012},[],[1014],{"type":49,"value":59},{"type":49,"value":171},{"type":43,"tag":78,"props":1017,"children":1019},{"className":1018},[],[1020],{"type":49,"value":183},{"type":49,"value":1022},", component root, etc.). If it is plain and the snippet targets the element itself, convert it to the appropriate ",{"type":43,"tag":78,"props":1024,"children":1026},{"className":1025},[],[1027],{"type":49,"value":238},{"type":49,"value":1029}," or add a motion wrapper while preserving the node's text, children, classes\u002Fstyles, attributes, and ",{"type":43,"tag":78,"props":1031,"children":1033},{"className":1032},[],[1034],{"type":49,"value":138},{"type":49,"value":1036},". Load ",{"type":43,"tag":277,"props":1038,"children":1040},{"href":1039},"references\u002Fexamples-and-anti-examples.md",[1041],{"type":49,"value":1039},{"type":49,"value":1043}," to see examples of this merging step.",{"type":43,"tag":74,"props":1045,"children":1046},{},[1047,1052,1054,1059,1061,1066,1068,1073,1075,1080],{"type":43,"tag":103,"props":1048,"children":1049},{},[1050],{"type":49,"value":1051},"Componentized child motion usually matches by fallback.",{"type":49,"value":1053}," When design context extracts a Figma instance into a reusable React component, children inside that component body often have backing component ids (",{"type":43,"tag":78,"props":1055,"children":1057},{"className":1056},[],[1058],{"type":49,"value":705},{"type":49,"value":1060},") while motion context reports live instance ids (",{"type":43,"tag":78,"props":1062,"children":1064},{"className":1063},[],[1065],{"type":49,"value":697},{"type":49,"value":1067},"). In this case, use ",{"type":43,"tag":78,"props":1069,"children":1071},{"className":1070},[],[1072],{"type":49,"value":246},{"type":49,"value":1074}," to find the component-body ",{"type":43,"tag":78,"props":1076,"children":1078},{"className":1077},[],[1079],{"type":49,"value":138},{"type":49,"value":1081},", but keep the motion scoped to the rendered instance you are implementing. If there are multiple instances and only one has different root motion, exact id matching keeps that per-instance motion separate.",{"type":43,"tag":74,"props":1083,"children":1084},{},[1085,1087,1092,1093,1098,1100,1105],{"type":49,"value":1086},"Split nodes carry a ",{"type":43,"tag":78,"props":1088,"children":1090},{"className":1089},[],[1091],{"type":49,"value":146},{"type":49,"value":148},{"type":43,"tag":78,"props":1094,"children":1096},{"className":1095},[],[1097],{"type":49,"value":154},{"type":49,"value":1099}," marker — see ",{"type":43,"tag":495,"props":1101,"children":1102},{},[1103],{"type":49,"value":1104},"Handling interleaved transforms",{"type":49,"value":1106}," below.",{"type":43,"tag":74,"props":1108,"children":1109},{},[1110,1123,1125,1131,1133,1138,1140,1146,1148,1154,1156,1161,1163,1168,1170,1175,1177,1183,1185,1190,1192,1197,1199,1204],{"type":43,"tag":103,"props":1111,"children":1112},{},[1113,1115,1121],{"type":49,"value":1114},"Preserve ",{"type":43,"tag":78,"props":1116,"children":1118},{"className":1117},[],[1119],{"type":49,"value":1120},"display: contents",{"type":49,"value":1122}," wrappers — unless the group itself animates.",{"type":49,"value":1124}," Layout-transparent group wrappers come through as ",{"type":43,"tag":78,"props":1126,"children":1128},{"className":1127},[],[1129],{"type":49,"value":1130},"contents",{"type":49,"value":1132}," (Tailwind ",{"type":43,"tag":78,"props":1134,"children":1136},{"className":1135},[],[1137],{"type":49,"value":1130},{"type":49,"value":1139},"), usually alongside a dead ",{"type":43,"tag":78,"props":1141,"children":1143},{"className":1142},[],[1144],{"type":49,"value":1145},"absolute",{"type":49,"value":1147},"\u002F",{"type":43,"tag":78,"props":1149,"children":1151},{"className":1150},[],[1152],{"type":49,"value":1153},"inset-[…]",{"type":49,"value":1155}," (those do nothing on a ",{"type":43,"tag":78,"props":1157,"children":1159},{"className":1158},[],[1160],{"type":49,"value":1130},{"type":49,"value":1162}," box). For a ",{"type":43,"tag":495,"props":1164,"children":1165},{},[1166],{"type":49,"value":1167},"static",{"type":49,"value":1169}," group, keep ",{"type":43,"tag":78,"props":1171,"children":1173},{"className":1172},[],[1174],{"type":49,"value":1120},{"type":49,"value":1176}," and let the children position against the nearest real ancestor — converting the wrapper's ",{"type":43,"tag":78,"props":1178,"children":1180},{"className":1179},[],[1181],{"type":49,"value":1182},"inset",{"type":49,"value":1184}," into a positioned box reparents the children to a smaller box, so they render too small \u002F shifted inward. For an ",{"type":43,"tag":495,"props":1186,"children":1187},{},[1188],{"type":49,"value":1189},"animated",{"type":49,"value":1191}," group (the group node itself has motion), ",{"type":43,"tag":78,"props":1193,"children":1195},{"className":1194},[],[1196],{"type":49,"value":1120},{"type":49,"value":1198}," can't carry a transform — replace it with a real positioned wrapper and apply the group motion there. Load ",{"type":43,"tag":277,"props":1200,"children":1202},{"href":1201},"references\u002Fgotchas.md",[1203],{"type":49,"value":1201},{"type":49,"value":1205}," before implementing this case.",{"type":43,"tag":74,"props":1207,"children":1208},{},[1209,1219,1221,1227,1229,1235,1237,1243,1245,1250,1252,1257,1259,1265,1267,1273],{"type":43,"tag":103,"props":1210,"children":1211},{},[1212,1217],{"type":43,"tag":78,"props":1213,"children":1215},{"className":1214},[],[1216],{"type":49,"value":83},{"type":49,"value":1218}," is the complete animated-node inventory.",{"type":49,"value":1220}," Some animated nodes render as plain (non-",{"type":43,"tag":78,"props":1222,"children":1224},{"className":1223},[],[1225],{"type":49,"value":1226},"motion",{"type":49,"value":1228},") elements — component instance roots (plain positioning ",{"type":43,"tag":78,"props":1230,"children":1232},{"className":1231},[],[1233],{"type":49,"value":1234},"\u003Cdiv>",{"type":49,"value":1236},"), text (",{"type":43,"tag":78,"props":1238,"children":1240},{"className":1239},[],[1241],{"type":49,"value":1242},"\u003Cp>",{"type":49,"value":1244},"), masks — that still carry a ",{"type":43,"tag":78,"props":1246,"children":1248},{"className":1247},[],[1249],{"type":49,"value":138},{"type":49,"value":1251},". Walk every node in the motion response and apply its motion to the element with the matching ",{"type":43,"tag":78,"props":1253,"children":1255},{"className":1254},[],[1256],{"type":49,"value":138},{"type":49,"value":1258},", wrapping or converting as needed. If an animated node has no element at all in the output (e.g. an animated mask flattened into a static ",{"type":43,"tag":78,"props":1260,"children":1262},{"className":1261},[],[1263],{"type":49,"value":1264},"mask-image",{"type":49,"value":1266},"), don't drop it silently — leave a ",{"type":43,"tag":78,"props":1268,"children":1270},{"className":1269},[],[1271],{"type":49,"value":1272},"\u002F\u002F TODO: \u003CnodeId> motion unsupported",{"type":49,"value":1274}," comment and call it out in your summary.",{"type":43,"tag":74,"props":1276,"children":1277},{},[1278],{"type":49,"value":1279},"If a node appears in motion context but not in the static JSX, add the element needed to represent it — design-context code is a reference, not a complete animation inventory.",{"type":43,"tag":74,"props":1281,"children":1282},{},[1283,1285,1290],{"type":49,"value":1284},"On conflict between design and motion context (timing\u002Feasing\u002Fanimated values), prefer ",{"type":43,"tag":78,"props":1286,"children":1288},{"className":1287},[],[1289],{"type":49,"value":83},{"type":49,"value":256},{"type":43,"tag":74,"props":1292,"children":1293},{},[1294,1306,1308,1313,1315,1321,1322,1328,1329,1335,1337,1343,1345,1350,1352,1357,1359,1365],{"type":43,"tag":103,"props":1295,"children":1296},{},[1297,1299,1305],{"type":49,"value":1298},"Path-level SVG motion: inline the SVG and animate the real ",{"type":43,"tag":78,"props":1300,"children":1302},{"className":1301},[],[1303],{"type":49,"value":1304},"\u003Cpath>",{"type":49,"value":256},{"type":49,"value":1307}," When ",{"type":43,"tag":78,"props":1309,"children":1311},{"className":1310},[],[1312],{"type":49,"value":83},{"type":49,"value":1314}," targets a vector's path (",{"type":43,"tag":78,"props":1316,"children":1318},{"className":1317},[],[1319],{"type":49,"value":1320},"PATH_TRIM",{"type":49,"value":171},{"type":43,"tag":78,"props":1323,"children":1325},{"className":1324},[],[1326],{"type":49,"value":1327},"motion.path",{"type":49,"value":171},{"type":43,"tag":78,"props":1330,"children":1332},{"className":1331},[],[1333],{"type":49,"value":1334},"stroke-dasharray",{"type":49,"value":1336},") but design context renders it as an ",{"type":43,"tag":78,"props":1338,"children":1340},{"className":1339},[],[1341],{"type":49,"value":1342},"\u003Cimg>",{"type":49,"value":1344},", inline the SVG and apply the snippet to the ",{"type":43,"tag":78,"props":1346,"children":1348},{"className":1347},[],[1349],{"type":49,"value":1304},{"type":49,"value":1351},", keeping the layout wrapper. Load ",{"type":43,"tag":277,"props":1353,"children":1355},{"href":1354},"references\u002Fsvg-and-path-motion.md",[1356],{"type":49,"value":1354},{"type":49,"value":1358}," for the full how-to for this case (motion.path, ",{"type":43,"tag":78,"props":1360,"children":1362},{"className":1361},[],[1363],{"type":49,"value":1364},"pathLength=\"1\"",{"type":49,"value":1366},", wrapper+path layering, CSS path-trim).",{"type":43,"tag":1368,"props":1369,"children":1371},"h4",{"id":1370},"handling-interleaved-transforms",[1372],{"type":49,"value":1104},{"type":43,"tag":59,"props":1374,"children":1375},{},[1376,1378,1383,1385,1390,1392,1398,1400,1406,1408,1414,1416,1422,1424,1429,1431,1437],{"type":49,"value":1377},"A node with ",{"type":43,"tag":103,"props":1379,"children":1380},{},[1381],{"type":49,"value":1382},"both",{"type":49,"value":1384}," a static base transform and animated transforms is split across nested elements so the two compose correctly instead of fighting: an id-less ",{"type":43,"tag":78,"props":1386,"children":1388},{"className":1387},[],[1389],{"type":49,"value":191},{"type":49,"value":1391}," carrying ",{"type":43,"tag":78,"props":1393,"children":1395},{"className":1394},[],[1396],{"type":49,"value":1397},"data-motion-wrapper-for=\"\u003CnodeId>\"",{"type":49,"value":1399}," (the OUTER wrapper) wraps a static-transform div (e.g. ",{"type":43,"tag":78,"props":1401,"children":1403},{"className":1402},[],[1404],{"type":49,"value":1405},"rotate-45",{"type":49,"value":1407}," + ",{"type":43,"tag":78,"props":1409,"children":1411},{"className":1410},[],[1412],{"type":49,"value":1413},"hypot()",{"type":49,"value":1415}," sizing — or the wrapper itself carries ",{"type":43,"tag":78,"props":1417,"children":1419},{"className":1418},[],[1420],{"type":49,"value":1421},"data-motion-transform-template=\"\u003Ccss>\"",{"type":49,"value":1423},") which wraps the INNER node (",{"type":43,"tag":78,"props":1425,"children":1427},{"className":1426},[],[1428],{"type":49,"value":138},{"type":49,"value":1430},"). Keep the ",{"type":43,"tag":78,"props":1432,"children":1434},{"className":1433},[],[1435],{"type":49,"value":1436},"wrapper > static-transform div > inner",{"type":49,"value":1438}," nesting — collapsing it breaks sizing and the base transform.",{"type":43,"tag":70,"props":1440,"children":1441},{},[1442,1515,1539,1610],{"type":43,"tag":74,"props":1443,"children":1444},{},[1445,1456,1458,1463,1465,1471,1472,1478,1479,1485,1486,1492,1493,1499,1500,1506,1508,1513],{"type":43,"tag":103,"props":1446,"children":1447},{},[1448,1450,1455],{"type":49,"value":1449},"Place tracks by ",{"type":43,"tag":78,"props":1451,"children":1453},{"className":1452},[],[1454],{"type":49,"value":146},{"type":49,"value":256},{"type":49,"value":1457}," The wrapper's ",{"type":43,"tag":78,"props":1459,"children":1461},{"className":1460},[],[1462],{"type":49,"value":146},{"type":49,"value":1464}," (transform tracks — ",{"type":43,"tag":78,"props":1466,"children":1468},{"className":1467},[],[1469],{"type":49,"value":1470},"x",{"type":49,"value":1147},{"type":43,"tag":78,"props":1473,"children":1475},{"className":1474},[],[1476],{"type":49,"value":1477},"y",{"type":49,"value":1147},{"type":43,"tag":78,"props":1480,"children":1482},{"className":1481},[],[1483],{"type":49,"value":1484},"rotate",{"type":49,"value":1147},{"type":43,"tag":78,"props":1487,"children":1489},{"className":1488},[],[1490],{"type":49,"value":1491},"scaleX",{"type":49,"value":1147},{"type":43,"tag":78,"props":1494,"children":1496},{"className":1495},[],[1497],{"type":49,"value":1498},"scaleY",{"type":49,"value":1147},{"type":43,"tag":78,"props":1501,"children":1503},{"className":1502},[],[1504],{"type":49,"value":1505},"skewX",{"type":49,"value":1507},") go on the OUTER wrapper; the inner element's ",{"type":43,"tag":78,"props":1509,"children":1511},{"className":1510},[],[1512],{"type":49,"value":146},{"type":49,"value":1514}," go on the INNER element.",{"type":43,"tag":74,"props":1516,"children":1517},{},[1518,1529,1531,1537],{"type":43,"tag":103,"props":1519,"children":1520},{},[1521,1523,1528],{"type":49,"value":1522},"Re-apply a ",{"type":43,"tag":78,"props":1524,"children":1526},{"className":1525},[],[1527],{"type":49,"value":161},{"type":49,"value":256},{"type":49,"value":1530}," If the wrapper carries one, set ",{"type":43,"tag":78,"props":1532,"children":1534},{"className":1533},[],[1535],{"type":49,"value":1536},"transformTemplate={(_, generated) => \"\u003Ccss> \" + generated}",{"type":49,"value":1538}," so the animated transform composes on top of that static layout transform.",{"type":43,"tag":74,"props":1540,"children":1541},{},[1542,1547,1548,1553,1555,1559,1561,1566,1568,1574,1576,1581,1583,1588,1589,1595,1597,1602,1603,1608],{"type":43,"tag":103,"props":1543,"children":1544},{},[1545],{"type":49,"value":1546},"Offset the animated transform by the static base (avoid double rotation).",{"type":49,"value":203},{"type":43,"tag":78,"props":1549,"children":1551},{"className":1550},[],[1552],{"type":49,"value":83},{"type":49,"value":1554}," gives the node's ",{"type":43,"tag":495,"props":1556,"children":1557},{},[1558],{"type":49,"value":1145},{"type":49,"value":1560}," transform, which already includes whatever static base those divs apply. A ",{"type":43,"tag":78,"props":1562,"children":1564},{"className":1563},[],[1565],{"type":49,"value":1484},{"type":49,"value":1567}," snippet of ",{"type":43,"tag":78,"props":1569,"children":1571},{"className":1570},[],[1572],{"type":49,"value":1573},"[45, 125, 125]",{"type":49,"value":1575}," over a ",{"type":43,"tag":78,"props":1577,"children":1579},{"className":1578},[],[1580],{"type":49,"value":1405},{"type":49,"value":1582}," base means the wrapper animates the ",{"type":43,"tag":103,"props":1584,"children":1585},{},[1586],{"type":49,"value":1587},"offset",{"type":49,"value":203},{"type":43,"tag":78,"props":1590,"children":1592},{"className":1591},[],[1593],{"type":49,"value":1594},"[0, 80, 80]",{"type":49,"value":1596}," (= absolute − 45), not the absolute — else the 45° applies twice and the element sits at 90° at rest. Tracks with no static base (e.g. ",{"type":43,"tag":78,"props":1598,"children":1600},{"className":1599},[],[1601],{"type":49,"value":1470},{"type":49,"value":1147},{"type":43,"tag":78,"props":1604,"children":1606},{"className":1605},[],[1607],{"type":49,"value":1477},{"type":49,"value":1609}," starting at 0) pass through unchanged. See the interleaved-transform example.",{"type":43,"tag":74,"props":1611,"children":1612},{},[1613,1618,1620,1625,1627,1632,1633,1639,1641,1647,1649,1655,1657,1663,1665,1671,1673,1678,1680,1686],{"type":43,"tag":103,"props":1614,"children":1615},{},[1616],{"type":49,"value":1617},"Keep layout transforms separate from Motion transforms.",{"type":49,"value":1619}," For every ",{"type":43,"tag":78,"props":1621,"children":1623},{"className":1622},[],[1624],{"type":49,"value":895},{"type":49,"value":1626}," element that animates ",{"type":43,"tag":78,"props":1628,"children":1630},{"className":1629},[],[1631],{"type":49,"value":1484},{"type":49,"value":171},{"type":43,"tag":78,"props":1634,"children":1636},{"className":1635},[],[1637],{"type":49,"value":1638},"scale",{"type":49,"value":1640},", or ",{"type":43,"tag":78,"props":1642,"children":1644},{"className":1643},[],[1645],{"type":49,"value":1646},"skew",{"type":49,"value":1648},", verify it does not also rely on Tailwind layout transforms such as ",{"type":43,"tag":78,"props":1650,"children":1652},{"className":1651},[],[1653],{"type":49,"value":1654},"-translate-x-1\u002F2",{"type":49,"value":1656}," or ",{"type":43,"tag":78,"props":1658,"children":1660},{"className":1659},[],[1661],{"type":49,"value":1662},"-translate-y-1\u002F2",{"type":49,"value":1664}," for centering\u002Fpositioning. Those utilities share the CSS ",{"type":43,"tag":78,"props":1666,"children":1668},{"className":1667},[],[1669],{"type":49,"value":1670},"transform",{"type":49,"value":1672}," property that Motion.dev writes inline, so Motion's transform can erase the layout translate. If both are needed, split the element into a static layout wrapper carrying the centering\u002Fpositioning transform and an inner ",{"type":43,"tag":78,"props":1674,"children":1676},{"className":1675},[],[1677],{"type":49,"value":895},{"type":49,"value":1679}," element carrying animated rotate\u002Fscale\u002Fopacity, or encode the layout offset in Motion itself (",{"type":43,"tag":78,"props":1681,"children":1683},{"className":1682},[],[1684],{"type":49,"value":1685},"x: \"-50%\"",{"type":49,"value":1687},") and keep it present for every keyframe.",{"type":43,"tag":549,"props":1689,"children":1691},{"id":1690},"step-4-apply-the-motion-in-code",[1692],{"type":49,"value":1693},"Step 4: Apply the motion in code",{"type":43,"tag":70,"props":1695,"children":1696},{},[1697,1722,1732],{"type":43,"tag":74,"props":1698,"children":1699},{},[1700,1705,1707,1713,1715,1720],{"type":43,"tag":103,"props":1701,"children":1702},{},[1703],{"type":49,"value":1704},"motion.dev present in snippets?",{"type":49,"value":1706}," Use the motion.dev code verbatim for React targets. Import from ",{"type":43,"tag":78,"props":1708,"children":1710},{"className":1709},[],[1711],{"type":49,"value":1712},"motion\u002Freact",{"type":49,"value":1714}," — unless the codebase already uses another motion library (Framer Motion, React Spring, GSAP), in which case adapt the snippet to it. Load ",{"type":43,"tag":277,"props":1716,"children":1718},{"href":1717},"references\u002Fframework-recommendations.md",[1719],{"type":49,"value":1717},{"type":49,"value":1721}," when adapting to another stack or choosing a library.",{"type":43,"tag":74,"props":1723,"children":1724},{},[1725,1730],{"type":43,"tag":103,"props":1726,"children":1727},{},[1728],{"type":49,"value":1729},"CSS keyframes present?",{"type":49,"value":1731}," Use for vanilla\u002Fnon-React targets, or when the codebase has no React motion library.",{"type":43,"tag":74,"props":1733,"children":1734},{},[1735,1740,1742,1747,1748,1753,1755,1760,1761,1766,1768,1773],{"type":43,"tag":103,"props":1736,"children":1737},{},[1738],{"type":49,"value":1739},"No snippets (keyframe-bindings-only)?",{"type":49,"value":1741}," Build equivalent motion.dev\u002FCSS from ",{"type":43,"tag":78,"props":1743,"children":1745},{"className":1744},[],[1746],{"type":49,"value":654},{"type":49,"value":1407},{"type":43,"tag":78,"props":1749,"children":1751},{"className":1750},[],[1752],{"type":49,"value":665},{"type":49,"value":1754},", taking loop timing from the cohort's ",{"type":43,"tag":78,"props":1756,"children":1758},{"className":1757},[],[1759],{"type":49,"value":769},{"type":49,"value":148},{"type":43,"tag":78,"props":1762,"children":1764},{"className":1763},[],[1765],{"type":49,"value":777},{"type":49,"value":1767}," and reading ",{"type":43,"tag":78,"props":1769,"children":1771},{"className":1770},[],[1772],{"type":49,"value":812},{"type":49,"value":1774}," \u002F duration from the structured fields. Rare — snippets are normally present, including for SwiftUI\u002FiOS (which get the CSS format).",{"type":43,"tag":549,"props":1776,"children":1778},{"id":1777},"step-5-validate",[1779],{"type":49,"value":1780},"Step 5: Validate",{"type":43,"tag":70,"props":1782,"children":1783},{},[1784,1789,1794],{"type":43,"tag":74,"props":1785,"children":1786},{},[1787],{"type":49,"value":1788},"Read the component's existing motion imports\u002Fconventions before adding new ones. If the user already uses Framer Motion \u002F React Spring \u002F anime.js, adapt rather than forcing motion.dev.",{"type":43,"tag":74,"props":1790,"children":1791},{},[1792],{"type":49,"value":1793},"Spot-check one animation runs end-to-end (reload, observe, iterate) before batching changes across many nodes.",{"type":43,"tag":74,"props":1795,"children":1796},{},[1797,1799,1803],{"type":49,"value":1798},"Load ",{"type":43,"tag":277,"props":1800,"children":1801},{"href":1201},[1802],{"type":49,"value":1201},{"type":49,"value":1804},", which covers specific bugs and edge cases seen in Figma motion output, and correct any such cases in the generated code.",{"type":43,"tag":52,"props":1806,"children":1808},{"id":1807},"critical-rules",[1809],{"type":49,"value":1810},"Critical Rules",{"type":43,"tag":59,"props":1812,"children":1813},{},[1814,1816,1822],{"type":49,"value":1815},"These are the general principles. Specific gotchas (rotation pivots, HOLD semantics, color interpolation, etc.) live in the categorized ",{"type":43,"tag":277,"props":1817,"children":1819},{"href":1818},"#references",[1820],{"type":49,"value":1821},"references",{"type":49,"value":1823},". When a linked reference is mentioned in this skill text and the situation applies, load that file before continuing.",{"type":43,"tag":1825,"props":1826,"children":1827},"ol",{},[1828,1886,1896,1929,1939,1949,2033],{"type":43,"tag":74,"props":1829,"children":1830},{},[1831,1842,1844,1849,1851,1856,1858,1863,1865,1870,1872,1877,1879,1884],{"type":43,"tag":103,"props":1832,"children":1833},{},[1834,1836,1840],{"type":49,"value":1835},"Respect the tool's output's ",{"type":43,"tag":495,"props":1837,"children":1838},{},[1839],{"type":49,"value":512},{"type":49,"value":1841},", not its layout.",{"type":49,"value":1843}," Preserve the exact timing, easing, keyframe values, and ",{"type":43,"tag":78,"props":1845,"children":1847},{"className":1846},[],[1848],{"type":49,"value":812},{"type":49,"value":1850}," from ",{"type":43,"tag":78,"props":1852,"children":1854},{"className":1853},[],[1855],{"type":49,"value":629},{"type":49,"value":1857}," — don't regenerate them from ",{"type":43,"tag":78,"props":1859,"children":1861},{"className":1860},[],[1862],{"type":49,"value":654},{"type":49,"value":1864}," or the structured fields when snippets exist (regenerating loses fidelity on custom bezier easings, spring approximations, and overshoot values). ",{"type":43,"tag":78,"props":1866,"children":1868},{"className":1867},[],[1869],{"type":49,"value":812},{"type":49,"value":1871}," is ",{"type":43,"tag":103,"props":1873,"children":1874},{},[1875],{"type":49,"value":1876},"per element",{"type":49,"value":1878},": apply each scaling\u002Frotating node's own — including nested scalers, not just the outer wrapper — or the element pivots from the default center and grows\u002Fspins from the wrong corner (see the per-element-",{"type":43,"tag":78,"props":1880,"children":1882},{"className":1881},[],[1883],{"type":49,"value":812},{"type":49,"value":1885}," example). But the snippet is one node's data, not a copy-paste template: when many nodes share it, factor it per Rule 7 instead of pasting the block N times.",{"type":43,"tag":74,"props":1887,"children":1888},{},[1889,1894],{"type":43,"tag":103,"props":1890,"children":1891},{},[1892],{"type":49,"value":1893},"Match the user's existing motion stack.",{"type":49,"value":1895}," Read the component's imports and any sibling animations before adding dependencies. If the user already has Framer Motion, React Spring, anime.js, GSAP — adapt the output to their stack rather than forcing motion.dev.",{"type":43,"tag":74,"props":1897,"children":1898},{},[1899,1911,1913,1919,1921,1927],{"type":43,"tag":103,"props":1900,"children":1901},{},[1902,1904,1910],{"type":49,"value":1903},"Honor ",{"type":43,"tag":78,"props":1905,"children":1907},{"className":1906},[],[1908],{"type":49,"value":1909},"prefers-reduced-motion",{"type":49,"value":256},{"type":49,"value":1912}," Any motion added must soften or disable under ",{"type":43,"tag":78,"props":1914,"children":1916},{"className":1915},[],[1917],{"type":49,"value":1918},"@media (prefers-reduced-motion: reduce)",{"type":49,"value":1920}," — typically skip the ",{"type":43,"tag":78,"props":1922,"children":1924},{"className":1923},[],[1925],{"type":49,"value":1926},"animate",{"type":49,"value":1928}," (render the initial\u002Fresting state) or cut the duration to near-zero. This is an accessibility default, not an opt-in.",{"type":43,"tag":74,"props":1930,"children":1931},{},[1932,1937],{"type":43,"tag":103,"props":1933,"children":1934},{},[1935],{"type":49,"value":1936},"Validate one animation end-to-end before batching.",{"type":49,"value":1938}," Build, reload, and watch one full timeline loop — confirm each animated node appears at the time its keyframe track says it should. \"Renders without error\" is not \"renders correctly.\" Motion failures compound when you batch — a wrong easing on one node is easy to spot; the same bug across twenty nodes is hours of untangling.",{"type":43,"tag":74,"props":1940,"children":1941},{},[1942,1947],{"type":43,"tag":103,"props":1943,"children":1944},{},[1945],{"type":49,"value":1946},"Don't fabricate motion.",{"type":49,"value":1948}," If a node has no motion data in the response, leave it static. Do not borrow easing\u002Fduration defaults from elsewhere in the design, and do not auto-animate \"because the rest of the component is animated.\"",{"type":43,"tag":74,"props":1950,"children":1951},{},[1952,1965,1966,1971,1972,1977,1979,1985,1987,1993,1995,2001,2003,2009,2011,2017,2019,2024,2026,2031],{"type":43,"tag":103,"props":1953,"children":1954},{},[1955,1957,1963],{"type":49,"value":1956},"Don't download an asset just to ",{"type":43,"tag":78,"props":1958,"children":1960},{"className":1959},[],[1961],{"type":49,"value":1962},"Read",{"type":49,"value":1964}," it.",{"type":49,"value":203},{"type":43,"tag":78,"props":1967,"children":1969},{"className":1968},[],[1970],{"type":49,"value":116},{"type":49,"value":148},{"type":43,"tag":78,"props":1973,"children":1975},{"className":1974},[],[1976],{"type":49,"value":83},{"type":49,"value":1978}," return assets as URLs (",{"type":43,"tag":78,"props":1980,"children":1982},{"className":1981},[],[1983],{"type":49,"value":1984},"\u002Fapi\u002Fmcp\u002Fasset\u002F...",{"type":49,"value":1986},"), often SVG. Reference the URL directly where the consumer fetches it (an ",{"type":43,"tag":78,"props":1988,"children":1990},{"className":1989},[],[1991],{"type":49,"value":1992},"\u003Cimg src>",{"type":49,"value":1994},", CSS ",{"type":43,"tag":78,"props":1996,"children":1998},{"className":1997},[],[1999],{"type":49,"value":2000},"background-image",{"type":49,"value":2002},", an asset import), or ",{"type":43,"tag":78,"props":2004,"children":2006},{"className":2005},[],[2007],{"type":49,"value":2008},"curl",{"type":49,"value":2010}," one to inline its contents (e.g. inline the SVG and render via ",{"type":43,"tag":78,"props":2012,"children":2014},{"className":2013},[],[2015],{"type":49,"value":2016},"NSImage(data:)",{"type":49,"value":2018}," on SwiftUI). The important exception is path-level SVG motion: if the motion snippet targets a path inside an SVG asset, inline the SVG and animate the real path instead of leaving it behind an ",{"type":43,"tag":78,"props":2020,"children":2022},{"className":2021},[],[2023],{"type":49,"value":1342},{"type":49,"value":2025},". Don't download an asset and feed the file to the ",{"type":43,"tag":78,"props":2027,"children":2029},{"className":2028},[],[2030],{"type":49,"value":1962},{"type":49,"value":2032}," tool: SVG isn't a Read-able image format, so the read is rejected and wasted — and a file tool that doesn't detect SVG-as-image can stall the loop on it.",{"type":43,"tag":74,"props":2034,"children":2035},{},[2036,2041,2043,2048,2050,2055,2057,2063,2065,2071,2073,2077,2079,2083],{"type":43,"tag":103,"props":2037,"children":2038},{},[2039],{"type":49,"value":2040},"Factor out repeated motion — never copy-paste the snippet per element.",{"type":49,"value":2042}," Many nodes usually share the ",{"type":43,"tag":495,"props":2044,"children":2045},{},[2046],{"type":49,"value":2047},"same",{"type":49,"value":2049}," animation differing only by a stagger delay, offset, or target value. Implement the shared motion ",{"type":43,"tag":103,"props":2051,"children":2052},{},[2053],{"type":49,"value":2054},"once",{"type":49,"value":2056}," — a reusable animated component or a ",{"type":43,"tag":78,"props":2058,"children":2060},{"className":2059},[],[2061],{"type":49,"value":2062},"variants",{"type":49,"value":2064}," object parameterized by the values that vary — render from a mapped array (",{"type":43,"tag":78,"props":2066,"children":2068},{"className":2067},[],[2069],{"type":49,"value":2070},"items.map(...)",{"type":49,"value":2072},"), and pull repeated literals (durations, easing arrays, offsets) into named constants. The animation's ",{"type":43,"tag":495,"props":2074,"children":2075},{},[2076],{"type":49,"value":512},{"type":49,"value":2078}," stay verbatim from the snippet (Rule 1); the ",{"type":43,"tag":495,"props":2080,"children":2081},{},[2082],{"type":49,"value":78},{"type":49,"value":2084}," stays DRY. The same transition object pasted 15+ times (800 lines that should be 150) is a low-quality result — fidelity and maintainability are both graded.",{"type":43,"tag":52,"props":2086,"children":2088},{"id":2087},"framework-recommendations",[2089],{"type":49,"value":380},{"type":43,"tag":59,"props":2091,"children":2092},{},[2093],{"type":49,"value":2094},"Rule 2 covers the general posture: prefer the user's existing stack. When none exists, defaults:",{"type":43,"tag":70,"props":2096,"children":2097},{},[2098,2125,2149],{"type":43,"tag":74,"props":2099,"children":2100},{},[2101,2106,2108,2116,2118,2123],{"type":43,"tag":103,"props":2102,"children":2103},{},[2104],{"type":49,"value":2105},"React",{"type":49,"value":2107},": ",{"type":43,"tag":277,"props":2109,"children":2113},{"href":2110,"rel":2111},"https:\u002F\u002Fmotion.dev",[2112],"nofollow",[2114],{"type":49,"value":2115},"motion.dev",{"type":49,"value":2117}," (the ",{"type":43,"tag":78,"props":2119,"children":2121},{"className":2120},[],[2122],{"type":49,"value":1226},{"type":49,"value":2124}," package). The tool returns motion.dev code directly — use it.",{"type":43,"tag":74,"props":2126,"children":2127},{},[2128,2133,2135,2140,2142,2147],{"type":43,"tag":103,"props":2129,"children":2130},{},[2131],{"type":49,"value":2132},"Vanilla \u002F non-React web",{"type":49,"value":2134},": CSS ",{"type":43,"tag":78,"props":2136,"children":2138},{"className":2137},[],[2139],{"type":49,"value":91},{"type":49,"value":2141}," with ",{"type":43,"tag":78,"props":2143,"children":2145},{"className":2144},[],[2146],{"type":49,"value":14},{"type":49,"value":2148}," shorthand, returned directly by the tool.",{"type":43,"tag":74,"props":2150,"children":2151},{},[2152,2157,2159,2165,2167,2172,2174,2179,2181,2186,2187,2192,2194,2199,2201,2206],{"type":43,"tag":103,"props":2153,"children":2154},{},[2155],{"type":49,"value":2156},"SwiftUI",{"type":49,"value":2158},": Native ",{"type":43,"tag":78,"props":2160,"children":2162},{"className":2161},[],[2163],{"type":49,"value":2164},".animation(...)",{"type":49,"value":2166}," modifiers, translated from the ",{"type":43,"tag":103,"props":2168,"children":2169},{},[2170],{"type":49,"value":2171},"CSS",{"type":49,"value":2173}," snippet (",{"type":43,"tag":78,"props":2175,"children":2177},{"className":2176},[],[2178],{"type":49,"value":83},{"type":49,"value":2180}," emits no SwiftUI code, but SwiftUI\u002FiOS clients still get the CSS format; fall back to ",{"type":43,"tag":78,"props":2182,"children":2184},{"className":2183},[],[2185],{"type":49,"value":654},{"type":49,"value":148},{"type":43,"tag":78,"props":2188,"children":2190},{"className":2189},[],[2191],{"type":49,"value":665},{"type":49,"value":2193}," \u002F cohort only when snippet-less). ",{"type":43,"tag":103,"props":2195,"children":2196},{},[2197],{"type":49,"value":2198},"Use only real SwiftUI APIs",{"type":49,"value":2200}," — no modifier takes a Figma\u002FCSS easing directly, so load ",{"type":43,"tag":277,"props":2202,"children":2204},{"href":2203},"references\u002Fframework-recommendations.md#swiftui-translation",[2205],{"type":49,"value":1717},{"type":49,"value":2207},", map the easing to its SwiftUI equivalent, and verify rather than invent. This path is evolving; confirm with the user if unsure.",{"type":43,"tag":59,"props":2209,"children":2210},{},[2211,2216,2218,2222],{"type":43,"tag":103,"props":2212,"children":2213},{},[2214],{"type":49,"value":2215},"For established effect classes, prefer a library over hand-rolled CSS.",{"type":49,"value":2217}," Effects like glass\u002Fglassmorphism, confetti, particle systems, physics-based interactions, and scroll-linked motion have battle-tested library implementations that handle cross-browser quirks, accessibility, and performance far better than generated keyframes. Load ",{"type":43,"tag":277,"props":2219,"children":2220},{"href":1717},[2221],{"type":49,"value":1717},{"type":49,"value":2223}," for the full library-by-effect-class table. Surface these as recommendations, not mandates — the user decides.",{"type":43,"tag":52,"props":2225,"children":2227},{"id":2226},"examples",[2228],{"type":49,"value":2229},"Examples",{"type":43,"tag":59,"props":2231,"children":2232},{},[2233,2234,2238,2240,2245,2247,2252],{"type":49,"value":1798},{"type":43,"tag":277,"props":2235,"children":2236},{"href":1039},[2237],{"type":49,"value":1039},{"type":49,"value":2239}," when you need worked examples or failure patterns. It covers the simple merge flow, plain text elements that need ",{"type":43,"tag":78,"props":2241,"children":2243},{"className":2242},[],[2244],{"type":49,"value":895},{"type":49,"value":2246}," added, interleaved static+animated transforms, SVG path-level motion, and anti-examples for DOM rebuilding, node-id\u002Fposition drift, and missing per-element ",{"type":43,"tag":78,"props":2248,"children":2250},{"className":2249},[],[2251],{"type":49,"value":812},{"type":49,"value":256},{"type":43,"tag":52,"props":2254,"children":2255},{"id":1821},[2256],{"type":49,"value":2257},"References",{"type":43,"tag":59,"props":2259,"children":2260},{},[2261],{"type":49,"value":2262},"Six deep dives, fetched on demand. General frontend concerns (performance, units, accessibility mechanics) are handled by the critical rules above — these references focus on Figma-specific signal only. If this skill names one of these files in an inline instruction, load that file before continuing with that part of the task.",{"type":43,"tag":70,"props":2264,"children":2265},{},[2266,2281,2304,2326,2335,2356],{"type":43,"tag":74,"props":2267,"children":2268},{},[2269,2273,2275,2280],{"type":43,"tag":277,"props":2270,"children":2271},{"href":1039},[2272],{"type":49,"value":1039},{"type":49,"value":2274}," — worked examples and failure patterns. Load when applying the merge workflow, handling interleaved transforms, or checking whether a generated implementation has rebuilt the DOM, swapped node positions, or dropped ",{"type":43,"tag":78,"props":2276,"children":2278},{"className":2277},[],[2279],{"type":49,"value":812},{"type":49,"value":256},{"type":43,"tag":74,"props":2282,"children":2283},{},[2284,2288,2290,2302],{"type":43,"tag":277,"props":2285,"children":2286},{"href":1201},[2287],{"type":49,"value":1201},{"type":49,"value":2289}," — Figma-specific motion bugs and their fixes. Rotation\u002Fscale origin on nested groups, HOLD easing semantics, CUSTOM_SPRING preservation, independent axis scaling ambiguity, color interpolation. Load when troubleshooting unexpected runtime behavior. ",{"type":43,"tag":103,"props":2291,"children":2292},{},[2293,2295,2300],{"type":49,"value":2294},"Always load ",{"type":43,"tag":277,"props":2296,"children":2298},{"href":2297},"references\u002Fmotion-lint-rules.md",[2299],{"type":49,"value":2297},{"type":49,"value":2301}," alongside this file",{"type":49,"value":2303}," — gotcha entries reference specific lint rules that must be surfaced to the user.",{"type":43,"tag":74,"props":2305,"children":2306},{},[2307,2311,2313,2318,2319,2324],{"type":43,"tag":277,"props":2308,"children":2309},{"href":1354},[2310],{"type":49,"value":1354},{"type":49,"value":2312}," — implementing motion that targets an SVG vector path (inline the asset, ",{"type":43,"tag":78,"props":2314,"children":2316},{"className":2315},[],[2317],{"type":49,"value":1327},{"type":49,"value":171},{"type":43,"tag":78,"props":2320,"children":2322},{"className":2321},[],[2323],{"type":49,"value":1364},{"type":49,"value":2325},", wrapper+path layering, CSS path-trim). Load when a vector's snippet targets the path, not a wrapper transform.",{"type":43,"tag":74,"props":2327,"children":2328},{},[2329,2333],{"type":43,"tag":277,"props":2330,"children":2331},{"href":1717},[2332],{"type":49,"value":1717},{"type":49,"value":2334}," — motion.dev, CSS keyframes, SwiftUI defaults, library-by-effect-class table (glass, confetti, particles, physics, scroll-linked). Load before hand-rolling an effect.",{"type":43,"tag":74,"props":2336,"children":2337},{},[2338,2343,2345,2354],{"type":43,"tag":277,"props":2339,"children":2341},{"href":2340},"references\u002Funsupported-and-fallbacks.md",[2342],{"type":49,"value":2340},{"type":49,"value":2344}," — Figma motion features that don't export cleanly today (text animations, path animations, masks\u002Fbooleans, variants\u002Ftransitions). Includes video\u002Flottie fallback guidance. Load when the tool response seems incomplete. ",{"type":43,"tag":103,"props":2346,"children":2347},{},[2348,2349,2353],{"type":49,"value":2294},{"type":43,"tag":277,"props":2350,"children":2351},{"href":2297},[2352],{"type":49,"value":2297},{"type":49,"value":2301},{"type":49,"value":2355}," — unsupported entries reference specific lint rules that must be surfaced to the user.",{"type":43,"tag":74,"props":2357,"children":2358},{},[2359,2363],{"type":43,"tag":277,"props":2360,"children":2361},{"href":2297},[2362],{"type":49,"value":2297},{"type":49,"value":2364}," — Linting rules: known export limitations (errors and warnings) that must be surfaced to the user. Load when generating motion code to check whether any active limitations apply.",{"items":2366,"total":2483},[2367,2384,2400,2412,2432,2451,2471],{"slug":2368,"name":2368,"fn":2369,"description":2370,"org":2371,"tags":2372,"stars":25,"repoUrl":26,"updatedAt":2383},"accessibility-and-inclusive-visualization","make data visualizations accessible","Make data visualizations accessible and inclusive. Use when the user needs chart or diagram accessibility guidance, text alternatives for complex visuals, color and contrast review, keyboard support, reduced-motion behavior for animation or parallax, or an accessibility QA workflow for exported figures, UML-like diagrams, and dashboards.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2373,2376,2379,2382],{"name":2374,"slug":2375,"type":15},"Accessibility","accessibility",{"name":2377,"slug":2378,"type":15},"Charts","charts",{"name":2380,"slug":2381,"type":15},"Data Visualization","data-visualization",{"name":23,"slug":24,"type":15},"2026-06-30T19:00:57.102",{"slug":2385,"name":2385,"fn":2386,"description":2387,"org":2388,"tags":2389,"stars":25,"repoUrl":26,"updatedAt":2399},"agent-browser","automate browser interactions for agents","Browser automation CLI for AI agents. Use when the user needs to interact with websites, verify dev server output, test web apps, navigate pages, fill forms, click buttons, take screenshots, extract data, or automate any browser task. Also triggers when a dev server starts so you can verify it visually.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2390,2393,2396],{"name":2391,"slug":2392,"type":15},"Agents","agents",{"name":2394,"slug":2395,"type":15},"Browser Automation","browser-automation",{"name":2397,"slug":2398,"type":15},"Testing","testing","2026-04-06T18:41:03.44016",{"slug":2401,"name":2401,"fn":2402,"description":2403,"org":2404,"tags":2405,"stars":25,"repoUrl":26,"updatedAt":2411},"agent-browser-verify","verify dev server output with automated browser","Automated browser verification for dev servers. Triggers when a dev server starts to run a visual gut-check with agent-browser — verifies the page loads, checks for console errors, validates key UI elements, and reports pass\u002Ffail before continuing.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2406,2407,2410],{"name":2394,"slug":2395,"type":15},{"name":2408,"slug":2409,"type":15},"Local Development","local-development",{"name":2397,"slug":2398,"type":15},"2026-04-06T18:41:17.526867",{"slug":2413,"name":2413,"fn":2414,"description":2415,"org":2416,"tags":2417,"stars":25,"repoUrl":26,"updatedAt":2431},"agents-sdk","build AI agents on Cloudflare Workers","Build AI agents on Cloudflare Workers using the Agents SDK. Load when creating stateful agents, durable workflows, real-time WebSocket apps, scheduled tasks, MCP servers, or chat applications. Covers Agent class, state management, callable RPC, Workflows integration, and React hooks. Biases towards retrieval from Cloudflare docs over pre-trained knowledge.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2418,2419,2422,2425,2428],{"name":2391,"slug":2392,"type":15},{"name":2420,"slug":2421,"type":15},"Cloudflare Workers","cloudflare-workers",{"name":2423,"slug":2424,"type":15},"SDK","sdk",{"name":2426,"slug":2427,"type":15},"Serverless","serverless",{"name":2429,"slug":2430,"type":15},"WebSockets","websockets","2026-04-06T18:39:51.717063",{"slug":2433,"name":2433,"fn":2434,"description":2435,"org":2436,"tags":2437,"stars":25,"repoUrl":26,"updatedAt":2450},"ai-elements","build chat UIs with AI Elements","AI Elements component library guidance — pre-built React components for AI interfaces built on shadcn\u002Fui. Use when building chat UIs, message displays, tool call rendering, streaming responses, reasoning panels, or any AI-native interface with the AI SDK.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2438,2439,2441,2444,2447],{"name":17,"slug":18,"type":15},{"name":2105,"slug":2440,"type":15},"react",{"name":2442,"slug":2443,"type":15},"shadcn\u002Fui","shadcn-ui",{"name":2445,"slug":2446,"type":15},"UI Components","ui-components",{"name":2448,"slug":2449,"type":15},"Vercel","vercel","2026-04-06T18:40:59.619419",{"slug":2452,"name":2452,"fn":2453,"description":2454,"org":2455,"tags":2456,"stars":25,"repoUrl":26,"updatedAt":2470},"ai-gateway","configure Vercel AI Gateway","Vercel AI Gateway expert guidance. Use when configuring model routing, provider failover, cost tracking, or managing multiple AI providers through a unified API.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2457,2460,2463,2466,2469],{"name":2458,"slug":2459,"type":15},"AI Infrastructure","ai-infrastructure",{"name":2461,"slug":2462,"type":15},"Cost Optimization","cost-optimization",{"name":2464,"slug":2465,"type":15},"LLM","llm",{"name":2467,"slug":2468,"type":15},"Performance","performance",{"name":2448,"slug":2449,"type":15},"2026-04-06T18:40:44.377464",{"slug":2472,"name":2472,"fn":2473,"description":2474,"org":2475,"tags":2476,"stars":25,"repoUrl":26,"updatedAt":2482},"ai-generation-persistence","implement persistence patterns for AI generations","AI generation persistence patterns — unique IDs, addressable URLs, database storage, and cost tracking for every LLM generation",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2477,2478,2481],{"name":2461,"slug":2462,"type":15},{"name":2479,"slug":2480,"type":15},"Database","database",{"name":2464,"slug":2465,"type":15},"2026-04-06T18:41:08.513425",600,{"items":2485,"total":2678},[2486,2507,2530,2547,2563,2580,2599,2609,2623,2637,2649,2662],{"slug":2487,"name":2487,"fn":2488,"description":2489,"org":2490,"tags":2491,"stars":2504,"repoUrl":2505,"updatedAt":2506},"prior-auth-packet-builder","build healthcare prior authorization packets","Build a concise prior authorization packet from local case files and payer policy docs.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2492,2495,2498,2501],{"name":2493,"slug":2494,"type":15},"Documents","documents",{"name":2496,"slug":2497,"type":15},"Healthcare","healthcare",{"name":2499,"slug":2500,"type":15},"Insurance","insurance",{"name":2502,"slug":2503,"type":15},"Regulatory Compliance","regulatory-compliance",28169,"https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-agents-python","2026-04-16T05:11:39.180399",{"slug":2508,"name":2508,"fn":2509,"description":2510,"org":2511,"tags":2512,"stars":2527,"repoUrl":2528,"updatedAt":2529},"aspnet-core","build ASP.NET Core web applications","Build, review, refactor, or architect ASP.NET Core web applications using current official guidance for .NET web development. Use when working on Blazor Web Apps, Razor Pages, MVC, Minimal APIs, controller-based Web APIs, SignalR, gRPC, middleware, dependency injection, configuration, authentication, authorization, testing, performance, deployment, or ASP.NET Core upgrades.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2513,2516,2518,2521,2524],{"name":2514,"slug":2515,"type":15},".NET","dotnet",{"name":2517,"slug":2508,"type":15},"ASP.NET Core",{"name":2519,"slug":2520,"type":15},"Blazor","blazor",{"name":2522,"slug":2523,"type":15},"C#","csharp",{"name":2525,"slug":2526,"type":15},"Web Development","web-development",23787,"https:\u002F\u002Fgithub.com\u002Fopenai\u002Fskills","2026-04-12T05:07:02.819491",{"slug":2531,"name":2531,"fn":2532,"description":2533,"org":2534,"tags":2535,"stars":2527,"repoUrl":2528,"updatedAt":2546},"chatgpt-apps","build ChatGPT Apps SDK applications","Build, scaffold, refactor, and troubleshoot ChatGPT Apps SDK applications that combine an MCP server and widget UI. Use when Codex needs to design tools, register UI resources, wire the MCP Apps bridge or ChatGPT compatibility APIs, apply Apps SDK metadata or CSP or domain settings, or produce a docs-aligned project scaffold. Prefer a docs-first workflow by invoking the openai-docs skill or OpenAI developer docs MCP tools before generating code.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2536,2539,2542,2545],{"name":2537,"slug":2538,"type":15},"Apps SDK","apps-sdk",{"name":2540,"slug":2541,"type":15},"ChatGPT","chatgpt",{"name":2543,"slug":2544,"type":15},"MCP","mcp",{"name":9,"slug":8,"type":15},"2026-04-12T05:07:05.468097",{"slug":2548,"name":2548,"fn":2549,"description":2550,"org":2551,"tags":2552,"stars":2527,"repoUrl":2528,"updatedAt":2562},"cli-creator","build CLIs from API docs","Build a composable CLI for Codex from API docs, an OpenAPI spec, existing curl examples, an SDK, a web app, an admin tool, or a local script. Use when the user wants Codex to create a command-line tool that can run from any repo, expose composable read\u002Fwrite commands, return stable JSON, manage auth, and pair with a companion skill.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2553,2556,2559],{"name":2554,"slug":2555,"type":15},"API Development","api-development",{"name":2557,"slug":2558,"type":15},"CLI","cli",{"name":2560,"slug":2561,"type":15},"Codex","codex","2026-04-12T05:07:04.132762",{"slug":2564,"name":2564,"fn":2565,"description":2566,"org":2567,"tags":2568,"stars":2527,"repoUrl":2528,"updatedAt":2579},"cloudflare-deploy","deploy projects to Cloudflare","Deploy applications and infrastructure to Cloudflare using Workers, Pages, and related platform services. Use when the user asks to deploy, host, publish, or set up a project on Cloudflare.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2569,2572,2575,2576],{"name":2570,"slug":2571,"type":15},"Cloudflare","cloudflare",{"name":2573,"slug":2574,"type":15},"Cloudflare Pages","cloudflare-pages",{"name":2420,"slug":2421,"type":15},{"name":2577,"slug":2578,"type":15},"Deployment","deployment","2026-04-12T05:07:14.275118",{"slug":2581,"name":2581,"fn":2582,"description":2583,"org":2584,"tags":2585,"stars":2527,"repoUrl":2528,"updatedAt":2598},"define-goal","define and set measurable project goals","Help the user define a concrete, measurable goal before starting work, especially when they ask to use the goal tool, create a goal, set an objective, clarify success criteria, or turn a fuzzy intention into a quantitative outcome. Use this skill for goal creation and goal refinement only; it does not manage durable snapshots, decision logs, or long-running execution artifacts.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2586,2589,2592,2595],{"name":2587,"slug":2588,"type":15},"Productivity","productivity",{"name":2590,"slug":2591,"type":15},"Project Management","project-management",{"name":2593,"slug":2594,"type":15},"Strategy","strategy",{"name":2596,"slug":2597,"type":15},"Task Management","task-management","2026-05-23T06:17:16.870838",{"slug":21,"name":21,"fn":2600,"description":2601,"org":2602,"tags":2603,"stars":2527,"repoUrl":2528,"updatedAt":2608},"translate Figma designs into code","Use the Figma MCP server to fetch design context, screenshots, variables, and assets from Figma, and to translate Figma nodes into production code. Trigger when a task involves Figma URLs, node IDs, design-to-code implementation, or Figma MCP setup and troubleshooting.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2604,2605,2606,2607],{"name":23,"slug":24,"type":15},{"name":20,"slug":21,"type":15},{"name":17,"slug":18,"type":15},{"name":2543,"slug":2544,"type":15},"2026-04-12T05:06:47.939943",{"slug":2610,"name":2610,"fn":2611,"description":2612,"org":2613,"tags":2614,"stars":2527,"repoUrl":2528,"updatedAt":2622},"figma-code-connect-components","connect Figma designs to code components","Connects Figma design components to code components using Code Connect mapping tools. Use when user says \"code connect\", \"connect this component to code\", \"map this component\", \"link component to code\", \"create code connect mapping\", or wants to establish mappings between Figma designs and code implementations. For canvas writes via `use_figma`, use `figma-use`.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2615,2616,2619,2620,2621],{"name":23,"slug":24,"type":15},{"name":2617,"slug":2618,"type":15},"Design System","design-system",{"name":20,"slug":21,"type":15},{"name":17,"slug":18,"type":15},{"name":2445,"slug":2446,"type":15},"2026-05-10T05:59:52.971881",{"slug":2624,"name":2624,"fn":2625,"description":2626,"org":2627,"tags":2628,"stars":2527,"repoUrl":2528,"updatedAt":2636},"figma-create-design-system-rules","generate design system rules from Figma","Generates custom design system rules for the user's codebase. Use when user says \"create design system rules\", \"generate rules for my project\", \"set up design rules\", \"customize design system guidelines\", or wants to establish project-specific conventions for Figma-to-code workflows. Requires Figma MCP server connection.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2629,2630,2631,2634,2635],{"name":23,"slug":24,"type":15},{"name":2617,"slug":2618,"type":15},{"name":2632,"slug":2633,"type":15},"Documentation","documentation",{"name":20,"slug":21,"type":15},{"name":17,"slug":18,"type":15},"2026-05-16T06:07:47.821474",{"slug":2638,"name":2638,"fn":2639,"description":2640,"org":2641,"tags":2642,"stars":2527,"repoUrl":2528,"updatedAt":2648},"figma-implement-design","translate Figma designs into application code","Translates Figma designs into production-ready application code with 1:1 visual fidelity. Use when implementing UI code from Figma files, when user mentions \"implement design\", \"generate code\", \"implement component\", provides Figma URLs, or asks to build components matching Figma specs. For Figma canvas writes via `use_figma`, use `figma-use`.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2643,2644,2645,2646,2647],{"name":23,"slug":24,"type":15},{"name":20,"slug":21,"type":15},{"name":17,"slug":18,"type":15},{"name":2445,"slug":2446,"type":15},{"name":2525,"slug":2526,"type":15},"2026-05-16T06:07:40.583615",{"slug":2650,"name":2650,"fn":2651,"description":2652,"org":2653,"tags":2654,"stars":2527,"repoUrl":2528,"updatedAt":2661},"hatch-pet","create animated pets for Codex","Create, repair, validate, visually QA, and package Codex-compatible animated pets and pet spritesheets from character art, generated images, company or prospect brand cues, or visual references. Use when a user wants a lightweight-worker Codex pet workflow, a non-pixel custom pet style, a prospect or company mascot pet, or a full 8x9 animated pet atlas with transparent unused cells, QA contact sheets, and pet.json packaging. This skill composes the installed $imagegen system skill for visual generation and uses bundled scripts for deterministic spritesheet assembly.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2655,2656,2657,2660],{"name":13,"slug":14,"type":15},{"name":2560,"slug":2561,"type":15},{"name":2658,"slug":2659,"type":15},"Creative","creative",{"name":23,"slug":24,"type":15},"2026-05-02T05:31:48.48485",{"slug":2663,"name":2663,"fn":2664,"description":2665,"org":2666,"tags":2667,"stars":2527,"repoUrl":2528,"updatedAt":2677},"imagegen","generate and edit raster images","Generate or edit raster images when the task benefits from AI-created bitmap visuals such as photos, illustrations, textures, sprites, mockups, or transparent-background cutouts. Use when Codex should create a brand-new image, transform an existing image, or derive visual variants from references, and the output should be a bitmap asset rather than repo-native code or vector. Do not use when the task is better handled by editing existing SVG\u002Fvector\u002Fcode-native assets, extending an established icon or logo system, or building the visual directly in HTML\u002FCSS\u002Fcanvas.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2668,2669,2670,2673,2676],{"name":2658,"slug":2659,"type":15},{"name":23,"slug":24,"type":15},{"name":2671,"slug":2672,"type":15},"Image Generation","image-generation",{"name":2674,"slug":2675,"type":15},"Images","images",{"name":9,"slug":8,"type":15},"2026-05-15T06:23:24.312127",675]