RepoPilotOpen in app →

pmndrs/react-spring

✌️ A spring physics based React animation library

Healthy

Healthy across the board

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit today
  • 27+ active contributors
  • Distributed ownership (top contributor 44% of recent commits)
  • MIT licensed
  • CI configured
  • Tests present

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the “Healthy” badge

Paste into your README — live-updates from the latest cached analysis.

RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/pmndrs/react-spring)](https://repopilot.app/r/pmndrs/react-spring)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/pmndrs/react-spring on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: pmndrs/react-spring

Generated by RepoPilot · 2026-05-06 · Source

Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/pmndrs/react-spring shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

Verdict

GO — Healthy across the board

  • Last commit today
  • 27+ active contributors
  • Distributed ownership (top contributor 44% of recent commits)
  • MIT licensed
  • CI configured
  • Tests present

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live pmndrs/react-spring repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/pmndrs/react-spring.

What it runs against: a local clone of pmndrs/react-spring — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in pmndrs/react-spring | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch next exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 30 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>pmndrs/react-spring</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of pmndrs/react-spring. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/pmndrs/react-spring.git
#   cd react-spring
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of pmndrs/react-spring and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "pmndrs/react-spring(\\.git)?\\b" \\
  && ok "origin remote is pmndrs/react-spring" \\
  || miss "origin remote is not pmndrs/react-spring (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify next >/dev/null 2>&1 \\
  && ok "default branch next exists" \\
  || miss "default branch next no longer exists"

# 4. Critical files exist
test -f "package.json" \\
  && ok "package.json" \\
  || miss "missing critical file: package.json"
test -f ".github/workflows/tests.yml" \\
  && ok ".github/workflows/tests.yml" \\
  || miss "missing critical file: .github/workflows/tests.yml"
test -f ".changeset/config.json" \\
  && ok ".changeset/config.json" \\
  || miss "missing critical file: .changeset/config.json"
test -f "CONTRIBUTING.md" \\
  && ok "CONTRIBUTING.md" \\
  || miss "missing critical file: CONTRIBUTING.md"
test -f ".eslintrc" \\
  && ok ".eslintrc" \\
  || miss "missing critical file: .eslintrc"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 30 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~0d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/pmndrs/react-spring"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

react-spring is a spring-physics-based animation library for React that provides declarative and imperative APIs for fluid, natural-feeling animations across platforms (React DOM, React Native, React Three Fiber, React Konva, React ZDog). It abstracts away complex spring physics calculations, letting developers animate values like opacity and transforms with a single useSpring() hook or imperative controls, defaulting to spring-based easing but supporting duration/easing configs. Monorepo structure with platform-specific packages (implied by README's mention of @react-spring/web, @react-spring/native, etc.) and CI test suites for multiple targets (.github/publish-ci/{cra5, next, vite, node-esm, node-standard}). Core TypeScript implementation likely resides in src/ or packages/core (inferred from language stats: 405KB TypeScript), with bundled demos and examples. Uses Changesets for versioning (.changeset/config.json).

Who it's for

React developers building interactive UIs (web, native, 3D, canvas) who need smooth, physics-based animations without manually calculating spring forces or managing animation state. Specifically: UI engineers at companies like Next.js, CodeSandbox, and Aragon who need cross-platform animation tooling.

Maturity & risk

Highly mature and production-ready. The repo is actively maintained by the pmndrs (Poimandres) collective with 405KB+ TypeScript codebase, comprehensive CI/CD pipelines (.github/publish-ci with CRA5, Next, Vite, Node ESM integration tests), and widespread adoption across major frameworks. The presence of detailed GitHub issue templates and a Discord community (740k members) indicates sustained, professional stewardship.

Standard open source risks apply.

Active areas of work

Active development indicated by presence of .changeset/gentle-tomatoes-nail.md (recent changeset entry) and maintained CI pipelines for React 19.1.0 compatibility (see .github/publish-ci/cra5/package.json). Discord and sponsorship infrastructure suggest ongoing community engagement and feature iteration, though specific PR/milestone details are absent from file list.

Get running

git clone https://github.com/pmndrs/react-spring.git
cd react-spring
yarn install
yarn start

(yarn is inferred from .yarn.lock files in .github/publish-ci subdirs; npm install react-spring or npm install @react-spring/web to use the library)

Daily commands:

yarn install
yarn start        # dev server (inferred from publish-ci CRA5 package.json: react-scripts start)
yarn build        # production build
yarn test         # minimal test runner (test script: 'echo Done' in example config)

For specific packages, enter .github/publish-ci/{cra5|next|vite|node-esm|node-standard} and yarn start.

Map of the codebase

  • package.json — Root workspace configuration defining all packages, scripts, and dependencies for the monorepo
  • .github/workflows/tests.yml — CI/CD pipeline that validates all contributions before merge; defines test coverage expectations
  • .changeset/config.json — Versioning and release management configuration; controls how package versions are bumped and published
  • CONTRIBUTING.md — Developer onboarding guide explaining contribution workflow, testing requirements, and code standards
  • .eslintrc — Linting rules enforced across the entire codebase; defines code quality and style standards
  • cypress.config.ts — E2E test configuration; defines how visual and functional tests are executed and validated
  • .yarnrc.yml — Yarn workspace configuration; controls monorepo dependency resolution and plugin setup

Components & responsibilities

  • @react-spring/core (TypeScript, requestAnimationFrame) — Physics engine; spring calculations and animation loop
    • Failure mode: If spring math is incorrect, animations will jitter or overshoot unexpectedly
  • @react-spring/web (React, CSS transforms, opacity) — React DOM bindings; applies animated values to DOM elements via style attributes
    • Failure mode: If DOM binding fails, animations render but do not update; memory leaks if cleanup is missed
  • Cypress E2E — undefined

How to make changes

Add a new animation package or variant

  1. Create a new workspace entry in the root package.json with proper naming (e.g., @react-spring/new-target) (package.json)
  2. Create package directory with src/ and dist/ structure following existing @react-spring/web pattern (demo/CONTRIBUTING.md)
  3. Add ESLint configuration extending the root .eslintrc (.eslintrc)
  4. Create changeset file documenting the new package (using pnpm changeset or manual .changeset/*.md) (.changeset/gentle-tomatoes-nail.md)
  5. Add test suite to .github/publish-ci/*/package.json to validate bundle in each target environment (.github/publish-ci/cra5/package.json)

Add a new E2E test for an animation feature

  1. Create new test file in cypress/e2e/ following the pattern of parallax.cy.ts (cypress/e2e/parallax.cy.ts)
  2. Configure test in cypress.config.ts if special viewport or browser settings are needed (cypress.config.ts)
  3. Add visual regression snapshots to cypress/snapshots/ for each test scenario (cypress/snapshots/parallax.cy.ts)
  4. Wire test into CI by ensuring it runs in .github/workflows/tests.yml (.github/workflows/tests.yml)

Publish a new release of the library

  1. Create changeset file in .changeset/ using changeset CLI or manual YAML describing changes and version bumps (.changeset/gentle-tomatoes-nail.md)
  2. Ensure all tests pass in .github/workflows/tests.yml and bundle size checks pass (.github/workflows/tests.yml)
  3. Merge PR with changesets; the publish workflow automatically creates release PR using .changeset/config.json rules (.changeset/config.json)
  4. Merge release PR; publish workflow in .github/workflows triggers npm publish for all updated packages (.github/publish-ci/node-standard/package.json)

Why these technologies

  • TypeScript — Provides type safety across animation logic and component APIs; critical for correctness in physics-based animations
  • Yarn workspaces (v3.x) — Enables modular monorepo with separate packages for different platforms (web, native, three) while sharing core physics engine
  • Cypress — Visual regression testing captures animation behavior; ensures physics simulation output is stable across versions
  • Changesets — Multi-package semantic versioning automation; handles complex release scenarios where different packages have different version bumps
  • Vite + Next.js + CRA test apps — Validates that the library works correctly across different React bundler configurations and SSR scenarios

Trade-offs already made

  • Monorepo structure (@react-spring/web, @react-spring/native, etc.) instead of single package

    • Why: Allows consumers to install only the platform-specific code they need; reduces bundle size for web-only projects
    • Consequence: Increases complexity of versioning and release management; requires coordinated testing across multiple packages
  • Spring physics calculations at library level rather than CSS Animations

    • Why: Provides deterministic, predictable animations across platforms; enables complex spring choreography impossible with CSS
    • Consequence: Higher CPU usage during animations; developers must understand spring config (tension, friction, mass)
  • CI test apps (CRA5, Vite, Next.js) instead of relying on user reports

    • Why: Catches integration bugs early before they reach production; validates compatibility with major bundlers
    • Consequence: Significant CI overhead; slow feedback loop; requires maintaining test app dependencies

Non-goals (don't propose these)

  • Does not provide CSS animation polyfills or fallbacks for older browsers
  • Does not handle gesture recognition or touch input (relies on external libraries like react-use-gesture)
  • Does not implement layout animations or Framer Motion-style layout shift detection
  • Not a comprehensive UI animation framework; focused purely on spring physics primitives

Traps & gotchas

No explicit env vars or secrets management visible in snippets, but monorepo may require Yarn workspaces setup (no yarn.lock at root in file list—confirm yarn version). Platform-specific timing: Spring animations may behave differently across React Native and web due to frame scheduling (React Native's requestAnimationFrame vs browser RAF). Bundle size: Each platform target (@react-spring/web vs @react-spring/native) ships separately; importing wrong package breaks at runtime. React version lock: Tests pin React ^19.1.0 in CRA5; older React versions may have undocumented compatibility issues. No visible lock file at repo root, only in publish-ci subdirs—check for monorepo-level lock discipline.

Architecture

Concepts to learn

  • Spring Physics Engine — Core differentiator of react-spring; understanding damping, stiffness, and tension params is critical to tuning animation feel and predictability.
  • Interpolation & Easing — react-spring supports both spring-based and duration/easing curves; developers must choose between declarative spring defaults and imperative easing functions like easeInOutQuad.
  • Request Animation Frame (RAF) Scheduling — Cross-platform animations rely on RAF or platform equivalents; blocking the frame or poor frame scheduling degrades animation smoothness, especially in React Native.
  • React Concurrent Rendering & Suspense — React 19 introduces concurrent features that may interact unpredictably with spring animations; developers must understand priority and interruption behavior.
  • Platform Abstraction Layers — react-spring adapts to DOM, React Native, Three.js, Konva, ZDog via separate packages; understanding how values are mutated (DOM style vs RN props) is key to debugging.
  • Imperative vs Declarative APIs — react-spring offers both hooks (declarative useSpring) and controller objects (imperative .start/.stop); choosing the right pattern avoids state management bugs.
  • Transform Origin & Layer Compositing — Web animations often target transform properties (translate, rotate, scale); GPU-accelerated properties vs reflow-triggering ones (width, height) drastically impact performance.

Related repos

  • react-motion/react-motion — Predecessor spring-based animation library for React; react-spring evolved as a more feature-rich modern alternative with better TypeScript support.
  • framer/motion — Competing declarative animation library; handles both spring and duration-based easing, targeting React DOM primarily (less cross-platform than react-spring).
  • pmndrs/zustand — Sibling library in pmndrs ecosystem; lightweight state management often paired with react-spring for managing animated state transitions.
  • react-three/fiber — Companion ecosystem that react-spring explicitly supports via @react-spring/three; enables 3D animation integration.
  • react-native/react-native — Platform target that react-spring adapts to; understanding RN's animation APIs and lifecycle is essential for @react-spring/native users.

PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add integration tests for publish-ci environments

The repo has 4 different publish-ci test environments (cra5, next, vite, node-esm, node-standard) in .github/publish-ci but no dedicated CI workflow validates they all build and run correctly. Currently only generic checks.yml and tests.yml exist. This would catch breaking changes across different bundlers/frameworks before release.

  • [ ] Create .github/workflows/publish-ci-verify.yml that runs build and test scripts for each environment in .github/publish-ci/*
  • [ ] Add matrix strategy to test cra5, next, vite, node-esm, and node-standard in parallel
  • [ ] Ensure each publish-ci app's package.json test script is executable (currently many just echo 'Done')
  • [ ] Document in contributing guide that publish-ci environments must pass before merging

Add unit tests for @react-spring/web package exports

The repo uses a monorepo structure with @react-spring/web as a key entry point (evident from CRA5 test app importing it), but there's no visible dedicated test file validating all named exports, tree-shaking capabilities, and ESM/CJS compatibility. This prevents regressions in public API surface.

  • [ ] Create src/tests/exports.test.ts (or similar location in packages/web) to validate all named exports from @react-spring/web are importable
  • [ ] Test both ESM import and CommonJS require patterns match
  • [ ] Add tests validating tree-shaking by checking bundle size of minimal imports
  • [ ] Run this test in checks.yml or create separate workflow to ensure it runs on every PR

Document and test changeset workflow in CONTRIBUTING guide

The repo has .changeset/config.json and .changeset/gentle-tomatoes-nail.md present, indicating a changeset-based release process (popular for monorepos), but there's no visible CONTRIBUTING.md explaining how contributors should use changesets. This causes friction for new PRs and manual work for maintainers.

  • [ ] Create or update .github/CONTRIBUTING.md with step-by-step instructions on running 'changeset add' before committing
  • [ ] Add pre-commit hook in .husky/pre-commit to remind contributors about changesets (or validate presence)
  • [ ] Document the changeset format and when to use 'patch', 'minor', 'major' with examples relevant to react-spring
  • [ ] Add test/validation in checks.yml to ensure each PR has a changeset file (except docs-only changes)

Good first issues

  • Add missing TypeScript definitions for animated component refs (e.g., animated.div.current type safety): Currently no ref typing visible in examples; consumers struggle with imperative APIs requiring useRef
  • Expand test coverage for React 19 concurrent features (Suspense, useDeferredValue integration with spring animations): CRA5 test app exists but .github/publish-ci/cra5 has no test.js; concurrent rendering edge cases likely untested
  • Document platform-specific timing differences (web RAF vs React Native frame scheduling) with example code: README mentions cross-platform support but .github/publish-ci has separate node-standard and node-esm; timing guarantees are ambiguous

Top contributors

Recent commits

  • e0c2004 — chore: update README (joshuaellis)
  • 6c37f69 — fix: exitBeforeEnter in useTransition doesn't work when used with trail (#1868) (#2407) (hiebj)
  • 2ff6de7 — Update README.md (joshuaellis)
  • b2d53b9 — chore: update readme (#2399) (joshuaellis)
  • 949bb28 — docs: add gtm (joshuaellis)
  • b6fbb98 — v10.0.3 (joshuaellis)
  • f69b748 — fix: ref access issue in jest and legacy react apps (#2394) (dimitris-tsetsonis)
  • 8631391 — v10.0.2 (joshuaellis)
  • 7cc1c90 — fix: respect immediate option to useResize hook (#2375) (LoganDark)
  • 197e0a7 — fix: remove accessing elem.ref in renderTransitions (#2373) (robertjarske)

Security observations

The react-spring repository shows generally good security practices with GitHub workflows for CI/CD and proper configuration structure. However, there are moderate concerns: wildcard dependency versions remove reproducibility guarantees, outdated TypeScript limits type safety, and missing security-specific configurations. The codebase is an animation library (inherently low-risk for direct injection attacks), but dependency management and tooling updates are needed. No hardcoded secrets were detected in the provided file structure. Recommendation: Implement strict version pinning, update development tools, add automated dependency scanning, and establish a security policy.

  • High · Wildcard Dependency Version — .github/publish-ci/cra5/package.json - dependencies. @react-spring/web is pinned to '*' which means any version (including breaking changes and potentially vulnerable versions) will be installed. This removes version control guarantees and could introduce security vulnerabilities in minor updates. Fix: Pin @react-spring/web to a specific version (e.g., '^9.8.0') and regularly update with tested releases.
  • Medium · Outdated TypeScript Version — .github/publish-ci/cra5/package.json - devDependencies. TypeScript 4.9.5 is significantly outdated. Current stable versions are 5.x, which include security fixes and improved type safety that could catch potential vulnerabilities. Fix: Update TypeScript to the latest stable version (5.x) to receive security patches and improved language features.
  • Medium · React Scripts Security Concerns — .github/publish-ci/cra5/package.json - dependencies. react-scripts 5.0.1 is used in CRA5 test environment. While functional, CRA is less commonly maintained. Ensure dependencies within react-scripts are kept current via yarn/npm audit. Fix: Run 'yarn audit' and 'npm audit' regularly. Consider upgrading to the latest CRA version or using alternative bundlers like Vite for better security practices.
  • Low · Missing Security Configuration Files — Repository root. No evidence of security-related configuration files such as SECURITY.md for vulnerability reporting policy, or .dependabot configuration for automated dependency updates. Fix: Create a SECURITY.md file with vulnerability disclosure policy and add .dependabot/dependabot.yml for automated dependency vulnerability scanning.
  • Low · Broad ESLint Configuration — .eslintrc. The ESLint configuration extends 'react-app' which may not include strict security-focused rules. No custom security rules (e.g., from eslint-plugin-security) are evident. Fix: Extend ESLint configuration to include security plugins like 'eslint-plugin-security' and enforce strict rules for potential XSS, injection vulnerabilities.

LLM-derived; treat as a starting point, not a security audit.

Where to read next


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · pmndrs/react-spring — RepoPilot