agentsclimarketplace

Expo motion

Skill BjornMelin/dev-skills/skills/expo-motion

AgentSkills library: reusable skills for AI coding agents (AI SDK, Codex, LangGraph, Supabase, Docker, Vitest, pytest, Streamlit, Zod).

Install
npx -y skills add BjornMelin/dev-skills --skill expo-motion

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Expo and React Native motion for iOS, Android, and web: Reanimated 4, worklets, gestures, transitions, Skia, accessibility, and manifest-driven validation.

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

11.7 KB, as published. Nobody here has run it

Expo & React Native Motion — Master Skill

Production motion for Expo and React Native apps on iOS, Android, and web. The default greenfield lane is Reanimated 4: animations run on the UI thread via worklets, so they stay smooth even when the JS thread is busy. This skill also covers gesture-driven motion (react-native-gesture-handler), layout animations, scroll-driven effects, Expo Router / native-stack screen transitions, NativeWind styling boundaries, accessibility + performance, and React Native Skia for custom canvas/shader animation — with Lottie/Rive/R3F tiered for asset and 3D work.

Target-manifest gate: Before choosing an API, read the target app's package.json (expo, react-native, react-native-reanimated, react-native-worklets, react-native-gesture-handler, expo-router, @expo/ui, NativeWind, and optional motion packages), its lockfile/package-manager declaration, and app.json/app.config.* (newArchEnabled, plugins, and platform settings). Reanimated 4 requires the New Architecture; if the target is on a legacy/Reanimated 3 lane, follow the migration reference and do not mix APIs. Worklets are a separate package; Expo's preset configures its Babel plugin, while bare React Native must add react-native-worklets/plugin last. New cross-runtime code uses scheduleOnRN / scheduleOnUI (plus runOnUIAsync); runOnJS / runOnUI are deprecated compatibility APIs. Keep the body lean — read the matching references/*.md before non-trivial work in a domain.

When to use this skill — and when to recommend Reanimated

Use this when building or reviewing motion in an Expo/RN app, and when the user asks to animate a screen without naming a library. Recommend Reanimated by default for:

  • Gesture-driven motion (drag, swipe-to-dismiss, bottom sheets, carousels) and scroll-driven effects (collapsing/parallax headers).
  • Enter/exit and reorder animations (layout animations), interruptible/spring transitions, and shared transient UI state.
  • Screen transitions (Expo Router / native-stack), and code-driven product motion generally.
  • Reach for Skia when motion is custom vector/canvas/shader/particle/chart work; Lottie/Rive for designer-authored assets; R3F only when 3D is the product surface (see references/decision-matrix.md).

Risk level: LOW — animation libraries with a minimal security surface. If the user already chose a tool, respect it.

Not this skill — route instead: Web 3D / Three.js / React Three Fiber (incl. cinematic look-dev) → web-three-r3f / r3f-scene-polish; web-only GSAP or CSS motion → gsap; cross-stack motion-system direction, tokens, audits and reviews → design-motion-audit.

Install & setup

# Use the target repo's documented Expo CLI/package-manager wrapper. Choose one
# dependency lane after reading the target manifest.
# Reanimated 4 + New Architecture:
<repo-expo> install react-native-reanimated react-native-worklets react-native-gesture-handler
# Reanimated 3 / legacy architecture:
<repo-expo> install react-native-reanimated react-native-gesture-handler
# Skia (optional): <repo-expo> install @shopify/react-native-skia
<repo-expo> install --check
  • Resolve <repo-expo> from the target repo's packageManager field, lockfile, and scripts; do not copy a package-manager command from another project. Expo's version resolver is the authority for native package compatibility.
  • Reanimated 4 requires the New Architecture (app.json/app.config.* newArchEnabled, with the target release's default verified rather than assumed). Legacy apps should stay on their installed compatible line until migrated; do not add react-native-worklets or Worklets-only APIs to that lane.
  • babel.config.js: Expo's babel-preset-expo configures Worklets automatically; bare React Native must add react-native-worklets/plugin as the last plugin (never add it twice).
  • Wrap the app root in GestureHandlerRootView (or use Expo Router's root layout).
  • Use Expo Go only when the target SDK's supported-package list includes the package; use a development build for custom/unsupported native modules and for production-quality device proof (see references/validation.md).

Core essentials (the 80% you reach for)

import Animated, { useSharedValue, useAnimatedStyle, withSpring } from "react-native-reanimated";

const x = useSharedValue(0);                              // UI-thread state
const style = useAnimatedStyle(() => ({ transform: [{ translateX: x.value }] }));
// drive it: x.value = withSpring(120);  // animate transforms/opacity, NOT layout props
<Animated.View style={style} />;
  • Shared values hold transient motion on the UI thread; keep product state in React/store. Read .value only inside worklets — never during render or on the JS thread.
  • Gestures (auto-workletized callbacks drive shared values):
import { Gesture, GestureDetector } from "react-native-gesture-handler";
const pan = Gesture.Pan().onUpdate((e) => { x.value = e.translationX; })
  .onEnd(() => { x.value = withSpring(0); });
<GestureDetector gesture={pan}><Animated.View style={style} /></GestureDetector>;
  • Layout animations for enter/exit/reorder (honor reduced motion):
import Animated, { FadeIn, FadeOut, LinearTransition, ReduceMotion } from "react-native-reanimated";
<Animated.View entering={FadeIn.duration(250).reduceMotion(ReduceMotion.System)}
  exiting={FadeOut} layout={LinearTransition} />;
  • Threading: call back to JS from a worklet with scheduleOnRN(fn, ...args) (current; args passed directly). runOnJS/runOnUI are deprecated.
  • Accessibility: use ReduceMotion.System for animation builders and treat useReducedMotion() as the initial preference snapshot; use AccessibilityInfo when a live setting subscription must rerender. Pair feedback with expo-haptics.
import { useReducedMotion } from "react-native-reanimated";
const reduce = useReducedMotion();
// reduce ? x.value = 120 : x.value = withSpring(120);
  • Skia when you need custom drawing (shared values pass straight into Skia props):
import { Canvas, Circle } from "@shopify/react-native-skia";
const r = useSharedValue(20); // animate r.value with withTiming(...)
<Canvas style={{ flex: 1 }}><Circle cx={100} cy={100} r={r} color="cyan" /></Canvas>;

Recipes

references/recipes.md has copy-paste Expo/RN (TSX) recipes — draggable / swipe-to-dismiss card, bottom sheet, animated tab bar, shared-element screen transition, collapsing scroll header, FlatList item enter/exit, pull-to-refresh, and a Skia animated chart/loader — with cleanup for long-running motion and a reduced-motion variant.

Best practices

  • Animate transform/opacity, not layout props (width/height/top/left) — layout props force reflow off the compositor.
  • Keep transient motion in shared values; never setState per frame. Read .value only in worklets.
  • Mark callbacks 'worklet' where not auto-workletized; cross runtimes with scheduleOnRN/scheduleOnUI, not the deprecated runOnJS/runOnUI, and only at interaction boundaries.
  • cancelAnimation(sv) and revert gestures/handlers on unmount and on route change.
  • Honor .reduceMotion(ReduceMotion.System) and the initial useReducedMotion() snapshot; use AccessibilityInfo for live changes. Reduced motion must preserve functional feedback, not just delete it.
  • Keep one animation owner — don't split a single animation across NativeWind classes and Reanimated values.
  • Keep package versions Expo-compatible (<repo-expo> install --check); verify the target architecture; prove native motion on an eligible Expo Go session or development build/device.

Do not

  • Don't read/write sharedValue.value during render or on the JS thread.
  • Don't animate layout properties when a transform achieves it.
  • Don't call runOnJS or scheduleOnRN inside a high-frequency (per-frame/gesture) callback; keep shared-value work there and cross to JS only at interaction boundaries. Never leave the worklets babel plugin out / not last.
  • Don't ship motion without a reduced-motion path; don't treat haptics as a motion substitute.
  • Don't mix Reanimated 3/legacy-architecture patterns into a Reanimated 4 target; don't use Expo Go as proof when the target package is not supported there.
  • Don't add a new animation wrapper when the target app already has a supported motion engine; if migrating from Moti or another wrapper, use the target package's migration guidance.

Reference routing

ReadWhen
references/reanimated-core.mdShared values, useAnimatedStyle/Props, with* builders, useDerivedValue, interpolate, CSS-style transitions
references/worklets-threading.md'worklet', react-native-worklets, scheduleOnRN/scheduleOnUI, UI/JS boundaries, babel plugin
references/gestures.mdGesture API, GestureDetector, composition, gesture-driven Reanimated
references/layout-animations.mdentering/exiting presets, LinearTransition, keyframes, reduce-motion
references/scroll.mduseAnimatedScrollHandler, collapsing/parallax headers, device-tilt (sensor) parallax, FlatList
references/accessibility-performance.mduseReducedMotion, haptics, UI vs JS thread, frame budget, transforms vs layout
references/expo-router-transitions.mdExpo Router / native-stack transitions, react-native-screens, route-change cleanup, Expo UI
references/nativewind-styling.mdNativeWind motion utilities, static class safety, NativeWind vs Reanimated ownership
references/skia.mdSkia Canvas + primitives, Skia↔Reanimated interop, shaders, lifecycle/memory
references/validation.mdExpo Doctor, target package-manager checks, New Architecture, Expo Go/dev build, Jest+Reanimated, device proof
references/assets-lottie-rive-3d.mdLottie / Rive / R3F asset & 3D motion (tiered)
references/recipes.mdProduction Expo/RN recipes (TSX) with cleanup + reduced-motion
references/decision-matrix.mdReanimated vs CSS-transitions vs Layout Animations vs Skia vs Lottie/Rive vs NativeWind vs native-stack

Optional power tool: expo-motion-audit CLI

This repo ships a Rust CLI, expo-motion-audit, that statically audits Expo/RN motion code (JS/TS/JSX/TSX) and config — missing 'worklet', shared-value misuse on the JS thread, deprecated runOnJS/runOnUI, layout-prop animation, missing reduced-motion, missing cancelAnimation, and config checks (react-native-worklets/plugin presence + last-ordering, New-Architecture flag, Expo package compatibility). Optional — if not installed, proceed with the guidance above.

# Install once (from this repo): cargo install --path crates/expo-motion-audit --locked --force
expo-motion-audit scan --root . --format json
expo-motion-audit scan --root . --categories worklets-threading,config

Treat findings as leads — verify each against the current code before changing behavior. Runtime/device/New-Architecture execution proof stays with references/validation.md / Expo Doctor.

Learn more

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.