pmndrs/zustand
66.3
Adequate · 28 September 2026
2.2k
lines of production code
TypeScript
with JavaScript
4
measurements over time
What this system is
This system is Zustand, a state management library for JavaScript applications, currently at version 5. It provides a core store API for managing state alongside React-specific hooks like useStore and useShallow for optimized rendering. The library includes a suite of middleware for features such as persistence, debugging, and immutable updates, supported by a modernized build and testing infrastructure.
Features
Add Zustand starter example with Vite and React
A new starter example has been added to the \examples/starter\ directory, providing a minimal, runnable React application that demonstrates basic Zustand usage. The example is built with Vite (using the \@vitejs/plugin-react-swc\ plugin) and includes a simple counter component that manages state via a Zustand store. It also provides setup instructions for both local development and running the project directly in StackBlitz.
examples/starter · high confidence
Add useShallow hook for React state selectors
A new \useShallow\ hook is introduced in \src/react/shallow.ts\ to optimize React component re-renders. It wraps a state selector and uses a shallow comparison logic (imported from the vanilla implementation) to return the previous state object if the selected values have not changed, thereby preventing unnecessary updates when the reference changes but the content remains equivalent.
src/react · high confidence
Add vanilla shallow comparison utility
Introduces a new \shallow\ function in \src/vanilla/shallow.ts\ that performs a shallow equality check on values. The implementation handles primitive comparisons via \Object.is\, validates object prototypes, and specifically supports iterable objects (including Maps and other iterables) by comparing their entries or element sequences in order, falling back to standard property comparison for plain objects.
src/vanilla · high confidence
Demo site rebuilt with Vite and enhanced code preview
The Zustand demo page has been migrated from the previous setup to Vite, introducing a modernized build pipeline and a new visual design featuring a 3D interactive scene. The demo now includes a code preview component that allows users to toggle between JavaScript and TypeScript examples and copy the code directly to their clipboard. Additionally, the site has been optimized as a Progressive Web App with a manifest, favicon, and offline fallback, and includes a robust error boundary to handle scenarios where hardware acceleration is disabled.
examples/demo · high confidence
Behavioural changes
Middleware codebase restructured into individual files with new capabilities
The middleware implementation has been refactored from a single module into separate files (combine, devtools, immer, persist, redux, ssrSafe, subscribeWithSelector). This change introduces several new capabilities: the devtools middleware now supports an \enabled\ option to control visibility and provides a \cleanup()\ method; the persist middleware adds a \skipHydration\ option, a \getOptions()\ API, and improved handling for Maps and synchronous storage race conditions; the immer middleware now correctly types \setState\ with immer drafts; and a new \ssrSafe\ middleware is available to prevent state-setting errors during server-side rendering.
src/middleware · high confidence
Project restructured with modern tooling and documentation
The repository has been reorganized to support a modern development workflow. The legacy \index.js\ entry point and \readme.md\ have been removed and replaced with a comprehensive \README.md\ and a new \CONTRIBUTING.md\ guide. The build system has been upgraded from Babel to esbuild via a new \rollup.config.mjs\, and the test runner has migrated to Vitest with a corresponding \vitest.config.mts\. TypeScript configuration is now stricter (\tsconfig.json\), and linting has moved to a flat config (\eslint.config.mjs\). Package management has standardized on pnpm (\pnpm-workspace.yaml\), and the project now includes a \FUNDING.json\ file for community support.
(repo-wide) · high confidence
Zustand v5 core API restructuring and React integration
The library has been updated to version 5, introducing a new core architecture that separates the vanilla store (\src/vanilla.ts\) from the React bindings (\src/react.ts\). The primary React hook \useStore\ now leverages \useSyncExternalStore\ for improved performance and consistency, replacing the previous \useLayoutEffect\-based implementation. A new \create\ function is exposed as the standard entry point, while the legacy \createWithEqualityFn\ is preserved in \src/traditional.ts\ for backward compatibility. The middleware system has been reorganized into explicit named exports in \src/middleware.ts\, including \persist\, \devtools\, \subscribeWithSelector\, and \combine\. Additionally, shallow comparison utilities (\shallow\, \useShallow\) are now exported from dedicated entry points, and the \StoreApi\ interface now includes \getInitialState\ and passes the previous state to subscribers.
src · high confidence
Test coverage
Added test coverage for vanilla store, shallow comparison, and subscription behaviors; Comprehensive test suite for Zustand core and middleware.
Dependencies
Zustand v5 release with React 19 support and modern build tooling
This update introduces Zustand version 5.0.15, which adds support for React 19 and upgrades the development environment to use Vite, Vitest, and ESLint 9. The package now uses a modern ESM-first export structure with TypeScript definitions, replacing the previous CommonJS build. Additionally, the repository has migrated from Yarn to pnpm, and the demo and starter examples have been updated to reflect these new tooling standards.
(dependencies) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.
Score
- CAI 48 → 66 (+18.7)
- Rubric changed (rubric-2026.08.15 → rubric-2026.09.16) — scores are not directly comparable.
Lenses
- Code Health 83 → 92 (+9.0)
- Architecture 95 (new)
- Maturity 59 → 61 (+2.2)
- Readiness 35 → 65 (+30.2)
- Security 54 → 64 (+9.5)
Resolved (43)
- Change coupling: devtools.ts ↔ immer.ts (src/middleware/devtools.ts)
- Change coupling: devtools.ts ↔ subscribeWithSelector.ts (src/middleware/devtools.ts)
- Change coupling: immer.ts ↔ persist.ts (src/middleware/immer.ts)
- Change coupling: immer.ts ↔ redux.ts (src/middleware/immer.ts)
- Change coupling: immer.ts ↔ subscribeWithSelector.ts (src/middleware/immer.ts)
- Change coupling: persist.ts ↔ redux.ts (src/middleware/persist.ts)
- Change coupling: persist.ts ↔ subscribeWithSelector.ts (src/middleware/persist.ts)
- Change coupling: react.ts ↔ traditional.ts (src/react.ts)
- Change coupling: redux.ts ↔ subscribeWithSelector.ts (src/middleware/redux.ts)
- Change coupling: subscribeWithSelector.ts ↔ react.ts (src/middleware/subscribeWithSelector.ts)
- Dimension evaluation failed
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- …and 23 more
New (29)
- Dependency hygiene PARTLY measured — npm pinning read, dependency currency not (the committed lockfile resolved no direct production dependency)
- Documentation: no project overview (docs/learn/guides/connect-to-state-with-url-hash.md)
- FixmeComment (src/middleware/devtools.ts)
- FixmeComment (src/middleware/devtools.ts)
- FixmeComment (src/middleware/devtools.ts)
- FunctionTooLong: persist.persistImpl (src/middleware/persist.ts)
- HackComment (src/vanilla/shallow.ts)
- High CVE: [GHSA redacted] (package-lock.json)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (package-lock.json)
- High CVE: [GHSA redacted] (package-lock.json)
- High CVE: [GHSA redacted] (package-lock.json)
- High CVE: [GHSA redacted] (package-lock.json)
- High CVE: [GHSA redacted] (package-lock.json)
- High CVE: [GHSA redacted] (pnpm-lock.yaml)
- High CVE: [GHSA redacted] (package-lock.json)
- High: security finding (details withheld)
- Low vulnerability: [GHSA redacted] (pnpm-lock.yaml)
- Medium CVE: [GHSA redacted] (package-lock.json)
- Medium CVE: [GHSA redacted] (package-lock.json)
- …and 9 more
Changes since last survey
- 9 commits — 7 feature/other, 2 fixes
By area
- (root) — 4 commits
- docs/reference — 2 commits
- .github/workflows — 1 commit
- docs/learn — 1 commit
- src/middleware — 1 commit
Notable commits
- fix: fix(devtools): correct V8 stack regex when source path contains spaces (#3531)
- fix: fix(persist): clearStorage() should invalidate concurrent async rehydration (#3555)
- change: Change CounterStore type from intersection to union (#3565)
- change: chore(deps): update dev dependencies (#3560)
- change: ci: build the docs with pmndrs/docs@v4 (#3570)
- change: docs(create): document that state cannot be read during initialization (#3569)
- change: docs: add zustand-devtools-bridge (#3559)
- change: docs: fix broken migrating-to-v5 link in README (#3567)
- change: v5.0.15
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
pmndrs/zustand was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 28 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit b57db4f86ef179285da216eeb291266da82c361c — the exact code this score is about.
- Scored under rubric-2026.09.16 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-eb9197011364.