skills/animation-system-architect/SKILL.md
Design performant animation systems with Framer Motion, GSAP, View Transitions API, and spring physics. Activate on: page transitions, micro-interactions, scroll animations, layout animations, spring physics. NOT for: CSS-only hover effects (use css-in-js-architect), video/canvas rendering (use creative-coding-expert).
npx skillsauth add curiositech/windags-skills animation-system-architectInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Build performant, accessible animation systems using Framer Motion, GSAP, the View Transitions API, and spring physics for fluid UI experiences.
Activate on: page transitions, layout animations, scroll-triggered animations, micro-interactions, spring physics, motion.div, gsap.to, View Transition API, shared element transitions, staggered list animations.
NOT for: CSS-only hover/focus effects -- use css-in-js-architect. Canvas/WebGL rendering -- use creative-coding-expert. Lottie file playback -- use standard Lottie integration.
will-change sparingly -- only on elements about to animate, remove after completion.prefers-reduced-motion -- disable or simplify all animations for users who request it.| Domain | Technologies | Key Patterns |
|--------|-------------|--------------|
| Declarative React | Framer Motion 11+, motion components | Layout animations, AnimatePresence, variants |
| Timeline Animation | GSAP 3.12+, ScrollTrigger | Scroll-driven sequences, pinning, scrubbing |
| Page Transitions | View Transitions API, Next.js useViewTransition | Cross-page shared element transitions |
| Spring Physics | Framer Motion springs, react-spring | Natural easing, interruptible animations |
| Micro-interactions | CSS transitions + Framer Motion | Button feedback, hover states, loading indicators |
| Scroll-driven | CSS animation-timeline: scroll(), GSAP ScrollTrigger | Parallax, progress indicators, reveal on scroll |
import { motion, AnimatePresence, LayoutGroup } from 'framer-motion';
function FilterableGrid({ items, filter }: Props) {
const filtered = items.filter(item => item.category === filter);
return (
<LayoutGroup>
<motion.div layout className="grid grid-cols-3 gap-4">
<AnimatePresence mode="popLayout">
{filtered.map(item => (
<motion.div
key={item.id}
layout // animate position changes
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.8 }}
transition={{ type: 'spring', stiffness: 300, damping: 25 }}
>
<Card item={item} />
</motion.div>
))}
</AnimatePresence>
</motion.div>
</LayoutGroup>
);
}
// app/components/TransitionLink.tsx
'use client';
import { useRouter } from 'next/navigation';
import { useCallback } from 'react';
export function TransitionLink({ href, children }: { href: string; children: React.ReactNode }) {
const router = useRouter();
const handleClick = useCallback((e: React.MouseEvent) => {
e.preventDefault();
if (!document.startViewTransition) {
router.push(href);
return;
}
document.startViewTransition(() => {
router.push(href);
});
}, [href, router]);
return <a href={href} onClick={handleClick}>{children}</a>;
}
/* Shared element transitions via view-transition-name */
.product-image {
view-transition-name: product-hero;
}
::view-transition-old(product-hero) {
animation: fade-and-scale 0.3s ease-out;
}
::view-transition-new(product-hero) {
animation: fade-and-scale 0.3s ease-in reverse;
}
import { useReducedMotion } from 'framer-motion';
function AnimatedComponent() {
const shouldReduce = useReducedMotion();
return (
<motion.div
initial={{ opacity: 0, y: shouldReduce ? 0 : 20 }}
animate={{ opacity: 1, y: 0 }}
transition={shouldReduce
? { duration: 0 }
: { type: 'spring', stiffness: 260, damping: 20 }
}
>
Content
</motion.div>
);
}
┌─ Animation Decision Tree ───────────────────────┐
│ │
│ prefers-reduced-motion? │
│ ├── YES → instant opacity fade only (no motion) │
│ └── NO → full spring/transform animation │
│ │
│ What's animating? │
│ ├── transform/opacity → GPU compositor (good) │
│ ├── width/height → layout thrash (avoid) │
│ └── box-shadow → paint-only (acceptable) │
└───────────────────────────────────────────────────┘
width, height, top, left -- triggers layout recalculation every frame. Use transform: translate/scale instead for 60fps.will-change on every element -- promotes too many layers to GPU, increasing memory usage. Apply only to elements about to animate.prefers-reduced-motion -- motion-sensitive users experience nausea or seizures. Always check and respect this media query.requestAnimationFrame or ScrollTrigger -- causes jank. Use GSAP ScrollTrigger or CSS animation-timeline: scroll() for scroll-driven animations.transform and opacity (compositor-friendly properties)prefers-reduced-motion respected with useReducedMotion or CSS media queryAnimatePresence used for mount/unmount animationslayout prop (not manual position calc)will-change applied only during animation, removed afterease)animation-timeline or ScrollTrigger (not scroll event listeners)tools
Building resilient distributed systems with circuit breakers, retries with full-jitter exponential backoff, retry budgets (per-request 3-attempt + per-client 10% ratio per Google SRE), deadline propagation, and the cascading-failure math (4 layers × 3 retries = 64x amplification). Grounded in Resilience4j, Microsoft Cloud Patterns, AWS Architecture Blog (Marc Brooker), and Google SRE Book.
testing
Designing HTTP cache headers that work correctly across browsers, CDNs, and shared proxies — `Cache-Control` directives per RFC 9111, `stale-while-revalidate` and `stale-if-error` per RFC 5861, the Vary header for varying responses, and surrogate keys for tag-based purging. Grounded in IETF RFCs and Cloudflare/Fastly docs.
development
Use when designing or fixing a Content Security Policy on a real site, choosing between nonce-based and hash-based CSP, adding strict-dynamic, debugging "Refused to execute inline script" errors, deploying CSP in report-only mode first, configuring report-to / report-uri, or auditing an existing policy for unsafe-inline / unsafe-eval / wildcards. Triggers: "CSP blocks legitimate inline script", strict-dynamic, nonce-{RANDOM}, sha256-{HASH}, object-src none, base-uri none, frame-ancestors, Trusted Types, X-Content-Security-Policy obsolete, report-only vs enforced. NOT for general HTTP security headers (HSTS, COOP/COEP), Trusted Types deep dive, CORS configuration, or building a WAF.
tools
Choosing and operating an HTTP API versioning strategy that doesn't break clients — Stripe's date-based pinned versions, the Deprecation/Sunset header pair (RFC 9745 + RFC 8594), URI vs header vs media-type approaches, and the version-transformer pattern. Grounded in Stripe's published architecture and IETF RFCs.