nextjs-framer-motion-animations

v2026.09.24

Implement and debug Motion for React in Next.js: local interaction, presence, layout, shared elements, scroll, reduced motion, and router integration. Use for explicit Motion/Framer Motion work or interactions that need it; prefer CSS for simple effects and framework-native view transitions for supported route cases.

GitHub
Install command
npx skhub add tristanmanchester/nextjs-framer-motion-animations
Markdown
SKILL.md

Purposeful Motion in Next.js

Choose motion to explain state or improve interaction, not to add a mandatory layer to every page. Keep existing design tokens and semantic controls. For a small colour/focus/hover transition, CSS may avoid unnecessary client JavaScript.

Inspect before choosing the boundary

Read the actual component, router (App or Pages), package/lockfiles, installed Motion API, and build configuration. Identify who owns mounting, state, focus, scroll, and navigation. Distinguish a local reveal from a route transition. A filename/token scanner cannot prove these relationships or build compatibility.

For modernised/new Motion code, use motion/react. In a Server Component, the supported motion/react-client entry point exposes motion elements; it does not turn hooks or arbitrary callbacks into server-safe code. Put interactive/hooks in the smallest Client Component, keeping fetching and secrets server-side. Server-rendered children can pass through a client wrapper without moving their implementation into the client bundle. Props across that boundary must meet React's actual serialisation contract.

For an existing framer-motion project, inspect its installed version and decide whether migration is in scope. A deliberate migration updates package, imports, lockfile, tests, and any changed APIs together. Do not mix runtimes or mechanically rewrite namespace imports from motion/react-m into a different module. This skill ships no compatibility branch or automatic import rewriting.

Choose the mechanism

NeedStart withEssential condition
Small local tween/gesturemotion elementPreserve semantic element and disabled/focus behaviour
Several coordinated childrenvariants and staggerStable identity and a bounded delay budget
Local removalAnimatePresenceIt survives and observes the removed keyed child
Layout changelayout / layout="position"Correct measurement and retained identity
Shared element within a live treelayoutId / LayoutGroupUnique, intentionally scoped IDs
Visibility revealwhileInViewCorrect scroll root and progressive visibility
Scroll-linked valueuseScroll plus motion valuesCorrect target/container and reduced-motion policy
Imperative sequenceuseAnimateScoped targets and cancellation/cleanup
Bundle-sensitive regionLazyMotion with mFeature set covers the used layout/drag APIs
Route/shared-view transitionFramework-supported ViewTransitionActual Next/React/browser contract, not a pathname wrapper

Read component patterns for implementation decisions and router integration for route changes. Do not assume one package-wide provider or one animation duration fits every interaction.

Presence and application state

A persistent AnimatePresence is necessary for its own exits but is not sufficient to control a router-owned subtree. Keying a wrapper by pathname does not establish that outgoing route content is retained unchanged. Do not freeze private router context, intercept every click, or delay all navigation to make an exit demo work. Use the supported framework route mechanism or an honest enter-only enhancement.

An animation callback is not a transaction boundary. Do not make a payment, delete, navigation confirmation, or other application outcome depend on whether an animation happened to finish. Cancellation, interruption, remount, and reduced motion must preserve the same logical outcome.

Accessibility and rendering

Use MotionConfig reducedMotion="user" where it fits the existing tree, plus local useReducedMotion decisions for scroll, autoplay, and bespoke effects. Opacity-only animations and independent CSS/view-transition paths need their own policy; one Motion provider is not a universal motion switch.

Use real buttons/links/dialogs. Preserve keyboard paths, visible focus, logical reading order, and an equivalent to drag-only interaction. Exiting invisible controls must not remain focusable or intercept input. A visual modal shell is not focus management, Escape behaviour, a label, or background inertness.

Do not server-render critical text permanently invisible and depend on successful hydration/intersection observation to reveal it. Keep layout boxes stable and handle font/image loading, viewport changes, and no-JavaScript/failure behaviour where required. Use transform/opacity where suitable, but measure actual paint, layout, compositing, and bundle costs before claiming a speed improvement.

Validate the actual change

Run the project's existing typecheck/lint/build as authorised; do not assume its scripts are named npm run lint/build. Test in the browser with rapid interactions, back/forward navigation, slow data, interruptions, reduced motion, keyboard use, and multiple copies of shared-layout components. Check console/hydration errors, scroll restoration, focus, and usable nonanimated fallback. Unit mocks are not a browser performance or router-lifetime test.

Deliver the patch, chosen boundary/mechanism, actual verification, and remaining browser checks. The old generic scanners, generated plans, all-assets scaffolder, and their golden-output pack are removed; real integration evidence is the goal, not reproducing a heuristic's preferred output.

Sources and maintenance

Reviewed 2026-09-13: Motion installation, AnimatePresence, Next templates, and Next view transitions. Evaluation cases describe required checks, not tests run.

Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

Not specified

Source path

nextjs-framer-motion-animations

Default branch

main

Latest commit

3323bc9

Tree SHA

9837a32