# pmndrs/jotai — codebase unpack

> Canonical page: https://codevetter.com/unpack/jotai

This is a deterministic Repo Unpack scan of pmndrs/jotai — a structural map, not a review, security audit, or maintainer-endorsed description.

- Scanned commit: 6abd0ae3365e02ab432fba4b6e8e6f00aafbf508 (2026-09-29)
- Last upstream commit: v3.0.1
- Generated by codevetter 1.15.0 on 2026-10-02
- 326 files scanned · 1.0 MB

Source inspection; upstream code and tests were not executed.

## Languages

- TypeScript: 117 files
- Markdown: 84 files
- JavaScript: 52 files
- JSON: 21 files
- CSS: 14 files
- HTML: 13 files
- YAML: 12 files

## Repository structure

- docs/ — 72 files
- examples/ — 71 files
- website/ — 68 files
- tests/ — 46 files
- src/ — 33 files
- .github/ — 13 files
- benchmarks/ — 10 files
- img/ — 1 files

Probable source entrypoint: `src/index.ts` (inferred from the tree, not upstream docs)

## Source layout — src/

- src/react/ — 12 files
- src/vanilla/ — 17 files
- src/index.ts — 1 file
- src/react.ts — 1 file
- src/utils.ts — 1 file
- src/vanilla.ts — 1 file

## Package

- package.json: jotai v3.0.1 — 32 declared dependencies

## Structural health signals

Average score 9.1/10 across 96 files; 1 hotspots. These are deterministic review leads, not proof of a bug.

## Recent history

- 6abd0ae3365e (2026-09-29) v3.0.1
- 5ea9573b5ff9 (2026-09-29) chore(deps): update dev dependencies (#3374)
- 85aa951942dc (2026-09-29) fix #3371 (#3373)
- 0c23f15ab895 (2026-09-29) fix(vanilla): export store type (#3370)
- 5a613709773f (2026-09-29) docs: clarify fork branch contribution flow (#3372)

## Overview

Jotai is a TypeScript state-management library for React applications, with a separate vanilla store API usable outside React. Atoms describe primitive, computed, or writable state; each store owns their values and tracks dependencies to propagate changes to subscribers. This pinned v3.0.1 checkout also contains persistence and async utilities, Vite examples, a Gatsby documentation website, regression tests, and package-release workflows.

## System map

The repository separates the vanilla dependency engine from its React adapter and utility modules. The published artifact is an ESM library, while the website and examples are separate applications with their own dependencies. Storage is in memory unless a utility connects an atom to an external adapter. Build and release behavior is defined by package scripts and GitHub Actions.
- src/index.ts re-exports the vanilla and React APIs; separate barrels expose atom/store primitives and Provider/hooks, including the v3 raw-value hooks. — [src/index.ts#L1-L2](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/index.ts#L1-L2) [src/vanilla.ts#L1-L19](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla.ts#L1-L19) [src/react.ts#L1-L8](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react.ts#L1-L8)
- package.json defines seven library entrypoints, publishes only dist, declares sideEffects:false, and provides TypeScript declarations only for >=5.5; React >=18 is an optional peer. — [package.json#L20-L61](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/package.json#L20-L61) [package.json#L137-L147](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/package.json#L137-L147)
- atom() creates configuration objects with read/write functions and optional init values; createStore() delegates to INTERNAL_buildStoreRev4 unless overridden. — [src/vanilla/atom.ts#L98-L139](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/atom.ts#L98-L139) [src/vanilla/store.ts#L4-L19](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/store.ts#L4-L19)
- buildStore owns per-store weak maps for atom state, mounting, and invalidation, sets for changes and lifecycle callbacks, and a store epoch holder; its public surface is get/set/sub. — [src/vanilla/internals.ts#L1209-L1258](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L1209-L1258)
- Provider supplies either an explicit store or a lazily created store retained in useRef; useStore selects options.store, then context, then the module's default store. — [src/react/Provider.ts#L18-L48](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/Provider.ts#L18-L48) [src/vanilla/store.ts#L21-L40](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/store.ts#L21-L40)
- The root build emits src into dist through tsc --noCheck; type checking is a separate test:types script. Compilation uses strict NodeNext modules and an ES2020 target. — [package.json#L62-L78](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/package.json#L62-L78) [tsconfig.json#L2-L23](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tsconfig.json#L2-L23) [tsconfig.build.json#L1-L10](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tsconfig.build.json#L1-L10)
- The Gatsby website sources ../docs as MDX, indexes documents through Algolia, and has Vercel function configuration for api/*.js; the Hacker News example independently uses Vite and React. — [website/gatsby-config.js#L99-L123](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/gatsby-config.js#L99-L123) [website/vercel.json#L1-L7](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/vercel.json#L1-L7) [website/package.json#L12-L42](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/package.json#L12-L42) [examples/hacker_news/package.json#L6-L23](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/examples/hacker_news/package.json#L6-L23)
- Publishing runs on published GitHub releases and builds before pnpm publish; preview releases build and invoke pkg-pr-new with example templates. The pnpm workspace contains the root and website. — [.github/workflows/publish.yml#L3-L28](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/.github/workflows/publish.yml#L3-L28) [.github/workflows/preview-release.yml#L19-L29](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/.github/workflows/preview-release.yml#L19-L29) [pnpm-workspace.yaml#L1-L4](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/pnpm-workspace.yaml#L1-L4)

## Feature catalog

The primary user surface is a composable state API rather than an application router or CLI. Primitive and derived atoms support synchronous values, async computations, and custom write actions. Utilities add persistence, state transformations, stream integration, and hydration. The examples and documentation website demonstrate these capabilities and provide search, theme selection, and support inquiries.
- atom overloads support primitive state, read-only derived state, writable derived state, and initial-value atoms with custom writes; primitive writes accept values or updater functions. — [src/vanilla/atom.ts#L74-L96](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/atom.ts#L74-L96) [src/vanilla/atom.ts#L123-L139](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/atom.ts#L123-L139)
- useAtom combines reading and setting; useAtomValue resolves promise values with Suspense, while useAtomValueRaw and useAtomValueRawSync return promise values without consuming them. — [src/react/useAtom.ts#L49-L57](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/useAtom.ts#L49-L57) [src/react/useAtomValue.ts#L66-L75](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/useAtomValue.ts#L66-L75) [src/react/useAtomValueRaw.ts#L75-L80](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/useAtomValueRaw.ts#L75-L80) [src/react/useAtomValueRawSync.ts#L27-L41](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/useAtomValueRawSync.ts#L27-L41)
- Users can isolate state with Provider, access stores outside React through get/set/sub, hydrate atom arguments once per store unless forced, and run imperative get/set callbacks through useAtomCallback. — [src/react/Provider.ts#L23-L48](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/Provider.ts#L23-L48) [docs/core/store.mdx#L10-L30](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/docs/core/store.mdx#L10-L30) [src/react/utils/useHydrateAtoms.ts#L42-L62](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/utils/useHydrateAtoms.ts#L42-L62) [src/react/utils/useAtomCallback.ts#L10-L18](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/utils/useAtomCallback.ts#L10-L18)
- State-control utilities include RESET-aware atoms, computed defaults that can be overwritten and restored, Redux-style reducers, zero-argument refresh, and lazy initial-value factories. — [src/vanilla/utils.ts#L1-L16](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils.ts#L1-L16) [src/vanilla/utils/atomWithDefault.ts#L24-L39](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/atomWithDefault.ts#L24-L39) [src/vanilla/utils/atomWithRefresh.ts#L32-L44](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/atomWithRefresh.ts#L32-L44) [src/vanilla/utils/atomWithLazy.ts#L4-L14](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/atomWithLazy.ts#L4-L14)
- selectAtom retains the previous slice when equalityFn matches; splitAtom exposes per-item atoms and remove/insert/move actions for writable arrays; freezeAtom wraps reads and self-writes with recursive freezing. — [src/vanilla/utils/selectAtom.ts#L24-L55](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/selectAtom.ts#L24-L55) [src/vanilla/utils/splitAtom.ts#L28-L49](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/splitAtom.ts#L28-L49) [src/vanilla/utils/splitAtom.ts#L152-L210](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/splitAtom.ts#L152-L210) [src/vanilla/utils/freezeAtom.ts#L24-L49](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/freezeAtom.ts#L24-L49)
- atomWithStorage supports sync or async adapters, RESET deletion, optional eager initialization, and external subscriptions. atomWithObservable supports streams and subject writes; unwrap exposes fallback values while promises are pending. — [src/vanilla/utils/atomWithStorage.ts#L196-L260](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/atomWithStorage.ts#L196-L260) [src/vanilla/utils/atomWithObservable.ts#L173-L197](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/atomWithObservable.ts#L173-L197) [src/vanilla/utils/unwrap.ts#L92-L133](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/unwrap.ts#L92-L133)
- Examples offer editable uppercase text and character counts, async Hacker News item browsing, animated todo filtering and deletion, explicit todo save/load, and nested form/field editing through optics and splitAtom. — [examples/text_length/src/App.tsx#L3-L27](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/examples/text_length/src/App.tsx#L3-L27) [examples/hacker_news/src/App.tsx#L20-L70](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/examples/hacker_news/src/App.tsx#L20-L70) [examples/todos_with_atomFamily/src/App.tsx#L77-L151](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/examples/todos_with_atomFamily/src/App.tsx#L77-L151) [examples/mega-form/src/App.tsx#L43-L146](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/examples/mega-form/src/App.tsx#L43-L146)
- The website provides a tabbed introduction/API overview, slug-based MDX documentation, Algolia search with section hits, a persisted dark-mode toggle, and a professional-support inquiry form. — [website/src/pages/index.js#L41-L54](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/src/pages/index.js#L41-L54) [website/src/pages/docs/{Mdx.slug}.js#L6-L42](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/src/pages/docs/%7BMdx.slug%7D.js#L6-L42) [website/src/components/search-modal.js#L23-L54](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/src/components/search-modal.js#L23-L54) [website/src/components/layout.js#L23-L28](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/src/components/layout.js#L23-L28)

## Data flow

Atom objects identify state, while stores own values, dependency epochs, and subscriptions. Reads establish dependencies and reuse cached results when their validity checks succeed. Writes propagate through custom atom actions, invalidate affected state, recompute dependencies, and notify subscribers. Promise, storage, documentation-indexing, and contact adapters introduce distinct external boundaries.
- An initial primitive value enters atom.init; the first store read creates AtomState and initializes its value through the self-getter. The same atom configuration can therefore have separate state in separate stores. — [src/vanilla/atom.ts#L110-L120](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/atom.ts#L110-L120) [src/vanilla/internals.ts#L515-L534](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L515-L534) [src/vanilla/internals.ts#L762-L773](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L762-L773) [docs/core/provider.mdx#L39-L39](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/docs/core/provider.mdx#L39-L39)
- readAtomState reuses initialized state when a mounted atom is not invalidated or its validation epoch equals the store epoch; otherwise it recursively compares recorded dependency epochs before recomputing. — [src/vanilla/internals.ts#L698-L742](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L698-L742)
- A derived read's getter records dependency atom epochs, removes those atoms from the stale-dependency set, and registers pending dependents for promises; stale dependencies are pruned synchronously or when the read promise settles. — [src/vanilla/internals.ts#L744-L792](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L744-L792) [src/vanilla/internals.ts#L765-L784](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L765-L784) [src/vanilla/internals.ts#L820-L831](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L820-L831)
- writeAtomState supplies a getter and setter to atom.write; self-writes update initialized state, advance the store epoch when the atom epoch changes, and invalidate dependents, while writes to other atoms recurse through their write functions. — [src/vanilla/internals.ts#L897-L939](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L897-L939)
- Changed mounted or pending dependents are traversed for topological recomputation; flushCallbacks deduplicates listeners and lifecycle callbacks, drains newly generated work, and aggregates callback errors. — [src/vanilla/internals.ts#L555-L598](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L555-L598) [src/vanilla/internals.ts#L613-L677](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L613-L677) [src/vanilla/internals.ts#L855-L874](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L855-L874)
- React's ordinary raw hook reads store.get into reducer state and subscribes in an effect; Object.is suppresses unchanged reducer values. Async values pass through createContinuablePromise, whose abort handler follows replacement promises before useAtomValue consumes them. — [src/react/useAtomValueRaw.ts#L52-L80](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/useAtomValueRaw.ts#L52-L80) [src/react/continuablePromise.ts#L24-L54](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/continuablePromise.ts#L24-L54) [src/react/useAtomValue.ts#L66-L75](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/useAtomValue.ts#L66-L75)
- atomWithStorage reads on mount and optionally at construction, feeds subscription updates into baseAtom, and writes memory before storage.setItem/removeItem. createJSONStorage translates values through JSON and filters browser storage events by storage area and key. — [src/vanilla/utils/atomWithStorage.ts#L119-L144](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/atomWithStorage.ts#L119-L144) [src/vanilla/utils/atomWithStorage.ts#L172-L184](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/atomWithStorage.ts#L172-L184) [src/vanilla/utils/atomWithStorage.ts#L222-L260](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/atomWithStorage.ts#L222-L260)
- Website MDX metadata/body become Algolia document and heading records, then search queries refine the Docs index and hits navigate to /docs/{slug}. Support form data separately becomes a JSON POST and a Postmark text email with the submitted address as ReplyTo. — [website/gatsby-config.js#L31-L75](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/gatsby-config.js#L31-L75) [website/src/components/search-modal.js#L81-L98](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/src/components/search-modal.js#L81-L98) [website/src/components/support.js#L19-L42](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/src/components/support.js#L19-L42) [website/api/contact.js#L12-L31](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/api/contact.js#L12-L31)

## Behavior traces

The source walkthrough followed React startup and subscription, a concrete text-edit action, and storage initialization/write/reset end to end. Additional traces followed async Hacker News loading and website search/support behavior. The steps below describe execution order and relevant branches from source inspection. They are not runtime observations.
- Startup: the starter calls createRoot(...).render(<StrictMode><App/>); Counter calls useAtom(countAtom), useStore falls back to getDefaultStore, and createStore builds the store on first use. — [examples/starter/src/index.tsx#L9-L25](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/examples/starter/src/index.tsx#L9-L25) [examples/starter/src/index.tsx#L49-L53](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/examples/starter/src/index.tsx#L49-L53) [src/react/Provider.ts#L18-L20](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/Provider.ts#L18-L20) [src/vanilla/store.ts#L14-L25](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/store.ts#L14-L25)
- Initial subscription: useAtomValueRaw initializes from store.get, then its effect invokes subscribe; store.sub mounts dependencies before the atom, adds the listener, recomputes, and flushes. createState then compares the rendered value against store.get and requests a rerender if changed or errored. — [src/react/useAtomValueRaw.ts#L19-L39](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/useAtomValueRaw.ts#L19-L39) [src/react/useAtomValueRaw.ts#L52-L75](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/useAtomValueRaw.ts#L52-L75) [src/vanilla/internals.ts#L992-L1039](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L992-L1039) [src/vanilla/internals.ts#L1142-L1157](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L1142-L1157)
- Text edit: Input.onChange sends e.target.value through useSetAtom to store.set; defaultWrite self-sets textAtom, writeAtomState invalidates dependents, and recomputation evaluates length/uppercase reads before subscribed components reread. — [examples/text_length/src/App.tsx#L3-L19](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/examples/text_length/src/App.tsx#L3-L19) [src/react/useSetAtom.ts#L30-L40](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/useSetAtom.ts#L30-L40) [src/vanilla/atom.ts#L127-L139](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/atom.ts#L127-L139) [src/vanilla/internals.ts#L914-L926](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L914-L926)
- Cleanup: the raw hook's effect returns the store subscription cleanup; it removes the listener, unmounts atoms only when no listener or mounted dependent still requires them, then recomputes and flushes queued onUnmount callbacks. — [src/react/useAtomValueRaw.ts#L27-L38](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/useAtomValueRaw.ts#L27-L38) [src/react/useAtomValueRaw.ts#L75-L75](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/useAtomValueRaw.ts#L75-L75) [src/vanilla/internals.ts#L1055-L1080](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L1055-L1080) [src/vanilla/internals.ts#L1158-L1163](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L1158-L1163)
- Persistence: atomWithStorage constructs baseAtom from initialValue unless getOnInit requests storage; mounting reloads and subscribes. A normal write computes the next value, updates baseAtom, and calls setItem; a promise write waits for resolution; RESET restores initialValue and calls removeItem. — [src/vanilla/utils/atomWithStorage.ts#L222-L260](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/atomWithStorage.ts#L222-L260) [src/vanilla/utils/atomWithStorage.ts#L119-L144](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/atomWithStorage.ts#L119-L144)
- Async browsing: Next increments postId; postData reads that ID, fetches the Firebase item endpoint, and returns response.json(). PostTitle reads the promise through useAtomValue and renders under Suspense; replacement promises trigger abort handlers, although this example does not pass a signal to fetch. — [examples/hacker_news/src/App.tsx#L20-L55](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/examples/hacker_news/src/App.tsx#L20-L55) [examples/hacker_news/src/App.tsx#L60-L70](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/examples/hacker_news/src/App.tsx#L60-L70) [src/react/useAtomValue.ts#L66-L75](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/useAtomValue.ts#L66-L75) [src/vanilla/internals.ts#L1093-L1111](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L1093-L1111)
- Documentation search: SearchModal reads searchAtom, mounts InstantSearch on Docs, CustomSearchBox updates local query state and throttles refine by 200 ms, Boundary hides empty queries or reports zero hits, and Hit navigation closes the modal. — [website/src/components/search-modal.js#L23-L42](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/src/components/search-modal.js#L23-L42) [website/src/components/search-modal.js#L57-L98](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/src/components/search-modal.js#L57-L98) [website/src/components/search-modal.js#L125-L132](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/src/components/search-modal.js#L125-L132)
- Support inquiry: handleSubmit rejects a filled client honeypot or previously completed submission, marks the form submitted, and POSTs JSON to /api/contact; the handler rejects missing fields, awaits sendEmail, and returns 200 or 500. Only a 200 response sets hasReceived and clears fields. — [website/src/components/support.js#L13-L43](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/src/components/support.js#L13-L43) [website/api/contact.js#L5-L31](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/api/contact.js#L5-L31)

## Testing signals

Tests and CI were inspected, not executed; no passing result or coverage percentage is asserted. Vitest runs the library suites in jsdom with React Testing Library and source aliases. Inspected regressions cover dependency notifications, cancellation, persistence, raw hooks, and garbage collection. Root automation checks several compatibility dimensions, but its configured scope does not establish end-to-end website or service coverage.
- Vitest selects tests under tests, uses jsdom and the React plugin, enables globals for Testing Library cleanup, aliases jotai imports to src, and loads jest-dom matchers. — [vitest.config.mts#L5-L23](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/vitest.config.mts#L5-L23) [tests/setup.ts#L1-L1](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tests/setup.ts#L1-L1) [tests/react/basic.test.tsx#L1-L7](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tests/react/basic.test.tsx#L1-L7)
- Store regressions assert unchanged-value notification suppression, dependency cleanup, and recovery of derived notifications during nested no-op writes plus subscription churn and synchronous event cascades (#3353). — [tests/vanilla/store.test.tsx#L63-L121](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tests/vanilla/store.test.tsx#L63-L121) [tests/vanilla/store.test.tsx#L1617-L1679](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tests/vanilla/store.test.tsx#L1617-L1679)
- Async tests use fake timers and assert abort on dependency replacement, continued execution after unsubscribe, Suspense loading states, and suppression of obsolete results during rapid updates. — [tests/vanilla/store.test.tsx#L525-L602](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tests/vanilla/store.test.tsx#L525-L602) [tests/react/abortable.test.tsx#L8-L79](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tests/react/abortable.test.tsx#L8-L79)
- Storage tests assert mount hydration, persisted increments, RESET deletion, getOnInit reads, sync/async validator fallbacks, and custom subscription delivery; these exercise adapters and jsdom rather than live cross-tab browsers. — [tests/react/vanilla-utils/atomWithStorage.test.tsx#L35-L133](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tests/react/vanilla-utils/atomWithStorage.test.tsx#L35-L133) [tests/react/vanilla-utils/atomWithStorage.test.tsx#L711-L841](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tests/react/vanilla-utils/atomWithStorage.test.tsx#L711-L841) [tests/react/vanilla-utils/atomWithStorage.test.tsx#L843-L936](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tests/react/vanilla-utils/atomWithStorage.test.tsx#L843-L936) [vitest.config.mts#L18-L19](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/vitest.config.mts#L18-L19)
- Raw-hook tests assert stable promise identity and preservation of a subscription across value changes; RawSync tests assert non-suspending promise returns and detection of a child's mount-time write. — [tests/react/useAtomValueRaw.test.tsx#L88-L154](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tests/react/useAtomValueRaw.test.tsx#L88-L154) [tests/react/useAtomValueRawSync.test.tsx#L68-L136](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tests/react/useAtomValueRawSync.test.tsx#L68-L136)
- Memory-leak tests use jest-leak-detector for unreferenced atoms, subscribed/unsubscribed state, and removed sync/async dependencies; separate store tests expect deep synchronous graphs to surface stack overflow and listeners to continue after another listener throws. — [tests/vanilla/memoryleaks.test.ts#L12-L58](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tests/vanilla/memoryleaks.test.ts#L12-L58) [tests/vanilla/memoryleaks.test.ts#L108-L149](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tests/vanilla/memoryleaks.test.ts#L108-L149) [tests/vanilla/store.test.tsx#L1013-L1041](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tests/vanilla/store.test.tsx#L1013-L1041) [tests/vanilla/store.test.tsx#L1081-L1128](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tests/vanilla/store.test.tsx#L1081-L1128)
- Inspected CI runs format/types/lint/spec/build across Node 22.12, 24, and 26; separate matrices test React 18/19 plus canary/experimental versions, TypeScript 5.5–5.9, and built ESM in development/production modes. — [.github/workflows/test.yml#L17-L38](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/.github/workflows/test.yml#L17-L38) [.github/workflows/test-multiple-versions.yml#L17-L44](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/.github/workflows/test-multiple-versions.yml#L17-L44) [.github/workflows/test-old-typescript.yml#L17-L40](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/.github/workflows/test-old-typescript.yml#L17-L40) [.github/workflows/test-multiple-builds.yml#L17-L49](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/.github/workflows/test-multiple-builds.yml#L17-L49)
- Configured coverage includes src/** and defines no threshold; ordinary root type checking includes src/tests/benchmarks, while lint excludes examples and website. The inspected root test workflow does not invoke website builds, contact-service checks, or example UI tests. — [vitest.config.mts#L24-L29](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/vitest.config.mts#L24-L29) [tsconfig.json#L22-L23](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tsconfig.json#L22-L23) [eslint.config.mjs#L11-L12](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/eslint.config.mjs#L11-L12) [.github/workflows/test.yml#L33-L38](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/.github/workflows/test.yml#L33-L38)

## Risk map

These are source observations and explicitly identified hypotheses, not confirmed vulnerabilities. The core's main correctness risks involve dependency/lifecycle ordering, deep reads, and pending promise retention. External trust boundaries appear in storage, example network content, and website contact handling. Several documentation and dependency mismatches require care when using ancillary applications to validate the root library.
- AtomState.p strongly retains pending dependents; the source explicitly notes possible memory leaks, and removal occurs when the associated promise settles. Hypothesis: never-settling promises can prolong retention beyond the ordinary weak-map lifecycle. (inferred) — [src/vanilla/internals.ts#L34-L41](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L34-L41) [src/vanilla/internals.ts#L372-L381](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L372-L381)
- Graph reads and mounting recurse even though invalidation/recomputation use iterative traversal; a regression explicitly expects sufficiently deep reads/subscriptions to overflow. Reads that mutate the store receive a development warning rather than enforced rejection. — [src/vanilla/internals.ts#L762-L792](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L762-L792) [src/vanilla/internals.ts#L815-L818](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L815-L818) [src/vanilla/internals.ts#L995-L1000](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L995-L1000) [tests/vanilla/store.test.tsx#L1013-L1041](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tests/vanilla/store.test.tsx#L1013-L1041)
- Storage JSON parsing accepts any valid JSON shape. withStorageValidator wraps getItem but copies subscribe unchanged, and atomWithStorage updates memory before persistence; validation of external subscription values and rollback after storage failures are not implemented in these functions. — [src/vanilla/utils/atomWithStorage.ts#L59-L79](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/atomWithStorage.ts#L59-L79) [src/vanilla/utils/atomWithStorage.ts#L147-L158](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/atomWithStorage.ts#L147-L158) [src/vanilla/utils/atomWithStorage.ts#L249-L260](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/atomWithStorage.ts#L249-L260)
- Both contact handlers check only truthiness of name/email/message before sending email; their bodies contain no method restriction, authentication, rate-limit, size, or email-format checks. The form's honeypot is client-only and is not included in its POST body; deployment-level controls were not verified. — [website/api/contact.js#L5-L31](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/api/contact.js#L5-L31) [website/src/api/contact.js#L5-L31](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/src/api/contact.js#L5-L31) [website/src/components/support.js#L13-L33](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/src/components/support.js#L13-L33)
- Support.handleSubmit sets hasSubmitted before fetch, has no catch/reset branch, and handles only status 200. Its overlay displays Sending... whenever submission started but hasReceived remains false, including the visible non-200 path. — [website/src/components/support.js#L13-L43](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/src/components/support.js#L13-L43) [website/src/components/support.js#L130-L146](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/src/components/support.js#L130-L146)
- The Hacker News example casts response.json() to PostData without runtime validation or response.ok handling, passes external text to html-react-parser, and uses external url values directly in links. These are content-validation boundaries; exploitability was not tested. — [examples/hacker_news/src/App.tsx#L20-L28](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/examples/hacker_news/src/App.tsx#L20-L28) [examples/hacker_news/src/App.tsx#L47-L55](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/examples/hacker_news/src/App.tsx#L47-L55) [examples/hacker_news/package.json#L11-L16](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/examples/hacker_news/package.json#L11-L16)
- The root is v3.0.1, but the website declares jotai ^2.4.1 and the atomFamily example ^2.10.4; that example imports atomFamily from jotai/utils even though v3 documentation moves it to jotai-family. These surfaces do not directly validate the root v3 implementation. — [package.json#L2-L5](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/package.json#L2-L5) [website/package.json#L34-L40](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/package.json#L34-L40) [examples/todos_with_atomFamily/package.json#L11-L18](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/examples/todos_with_atomFamily/package.json#L11-L18) [docs/guides/migrating-to-v3.mdx#L69-L84](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/docs/guides/migrating-to-v3.mdx#L69-L84)
- The useAtomValueRaw documentation says render-to-subscription changes are missed, whereas createState now rereads immediately after store.sub and invokes the callback when changed. Separately, website SSR theme bootstrap catches storage reads but leaves JSON.parse and its initialization write outside that catch. — [docs/core/use-atom.mdx#L132-L151](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/docs/core/use-atom.mdx#L132-L151) [src/react/useAtomValueRaw.ts#L27-L38](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/useAtomValueRaw.ts#L27-L38) [website/gatsby-ssr.js#L17-L30](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/gatsby-ssr.js#L17-L30)

## Extension points

Atoms and store adapters are the principal composition interfaces. Public utilities accept application-supplied selectors, equality functions, storage implementations, observables, and callbacks. Internal store hooks and replaceable building blocks offer deeper instrumentation but explicitly carry compatibility warnings. Website documentation extends through MDX content and a shared component map.
- New state abstractions can be implemented as atom(read, write): read receives dependency get and an AbortSignal option, while write receives get/set plus arbitrary typed arguments and can return an application-defined result. — [src/vanilla/atom.ts#L14-L23](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/atom.ts#L14-L23) [src/vanilla/atom.ts#L55-L62](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/atom.ts#L55-L62) [src/vanilla/atom.ts#L74-L87](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/atom.ts#L74-L87)
- Writable atoms support onMount(setAtom) returning cleanup; INTERNAL_onInit receives the store on first reference. The latter is explicitly internal and unstable. — [src/vanilla/atom.ts#L31-L61](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/atom.ts#L31-L61) [src/vanilla/internals.ts#L515-L533](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L515-L533) [src/vanilla/internals.ts#L1009-L1038](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L1009-L1038)
- createStore provides independently owned state, Provider accepts an existing store, and INTERNAL_overrideCreateStore receives the previous override to replace store construction. — [src/vanilla/store.ts#L6-L19](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/store.ts#L6-L19) [src/react/Provider.ts#L23-L38](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/Provider.ts#L23-L38)
- SyncStorage/AsyncStorage define getItem/setItem/removeItem plus optional subscribe; createJSONStorage accepts string-storage factories and JSON reviver/replacer functions, enabling sessionStorage or custom async backends. — [src/vanilla/utils/atomWithStorage.ts#L24-L49](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/atomWithStorage.ts#L24-L49) [src/vanilla/utils/atomWithStorage.ts#L83-L115](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/atomWithStorage.ts#L83-L115)
- selectAtom accepts selector and equality callbacks, splitAtom accepts a keyExtractor, and unwrap accepts a fallback using the previously resolved value; memoization depends on these function/object identities. — [src/vanilla/utils/selectAtom.ts#L18-L55](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/selectAtom.ts#L18-L55) [src/vanilla/utils/splitAtom.ts#L51-L79](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/splitAtom.ts#L51-L79) [src/vanilla/utils/splitAtom.ts#L213-L215](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/splitAtom.ts#L213-L215) [src/vanilla/utils/unwrap.ts#L35-L50](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/unwrap.ts#L35-L50)
- atomWithObservable accepts a dependency-aware getObservable factory and subscribable or Symbol.observable-style sources; subject-like sources additionally expose writes through next(data). useAtomCallback adapts arbitrary get/set callbacks to a memoized write-only atom. — [src/vanilla/utils/atomWithObservable.ts#L20-L46](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/atomWithObservable.ts#L20-L46) [src/vanilla/utils/atomWithObservable.ts#L86-L91](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/atomWithObservable.ts#L86-L91) [src/vanilla/utils/atomWithObservable.ts#L182-L193](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/atomWithObservable.ts#L182-L193) [src/react/utils/useAtomCallback.ts#L10-L18](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/utils/useAtomCallback.ts#L10-L18)
- INTERNAL_buildStoreRev4 merges Partial<BuildingBlocks> into defaults, freezes the block table, and exports keyed accessors; experimental store hooks provide creation/read/change/mount/unmount/flush listeners. Internal consumers are told to pin versions. — [src/vanilla/internals.ts#L1-L2](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L1-L2) [src/vanilla/internals.ts#L410-L483](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L410-L483) [src/vanilla/internals.ts#L1259-L1276](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L1259-L1276)
- Adding MDX under docs feeds Gatsby's filesystem source and slug-based page template; frontmatter.nav controls navigation sorting, while gatsby-shared.js maps MDX elements and embedded demo components to website renderers. — [website/gatsby-config.js#L101-L112](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/gatsby-config.js#L101-L112) [website/src/pages/docs/{Mdx.slug}.js#L31-L42](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/src/pages/docs/%7BMdx.slug%7D.js#L31-L42) [website/src/components/docs.js#L73-L122](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/src/components/docs.js#L73-L122) [website/gatsby-shared.js#L19-L35](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/gatsby-shared.js#L19-L35)

## Contributor handoff

This brief is grounded in the pinned checkout, including more than twelve source files and multiple end-to-end source traces. Tests and CI were inspected, not executed, and the investigation did not install, build, benchmark, contact services, or modify files. Future edits should preserve the vanilla/React boundary and verify the specific affected regression suites. Ancillary v2 applications, unstable internals, and documentation drift need explicit consideration.
- Begin core work with atom.ts, store.ts, and the relevant internals building blocks; atom configuration identity and per-store state ownership are separate concerns. Preserve referentially stable atoms when used from React render functions. — [src/vanilla/atom.ts#L98-L120](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/atom.ts#L98-L120) [src/vanilla/store.ts#L14-L19](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/store.ts#L14-L19) [src/vanilla/internals.ts#L1209-L1229](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L1209-L1229) [docs/core/use-atom.mdx#L23-L43](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/docs/core/use-atom.mdx#L23-L43)
- For notification edits, preserve recompute-before-flush behavior in storeSet, storeSub, and unsubscribe; read the #3353 tests before changing the changedAtoms-size optimization or introducing nested notification behavior. — [src/vanilla/internals.ts#L1120-L1163](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L1120-L1163) [tests/vanilla/store.test.tsx#L1617-L1679](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tests/vanilla/store.test.tsx#L1617-L1679)
- For hook edits, read both raw subscription implementations and continuablePromise; the ordinary raw hook includes a post-subscription value check, while RawSync uses useSyncExternalStore. Reconcile mount-timing documentation against these sources. — [src/react/useAtomValueRaw.ts#L19-L39](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/useAtomValueRaw.ts#L19-L39) [src/react/useAtomValueRawSync.ts#L27-L39](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/useAtomValueRawSync.ts#L27-L39) [src/react/continuablePromise.ts#L15-L54](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/react/continuablePromise.ts#L15-L54) [docs/core/use-atom.mdx#L132-L168](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/docs/core/use-atom.mdx#L132-L168)
- For storage changes, preserve getOnInit versus onMount loading, promise-update resolution, RESET deletion, and storage-area/key filtering; inspect the adapter tests rather than assuming browser persistence is infallible. — [src/vanilla/utils/atomWithStorage.ts#L172-L184](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/atomWithStorage.ts#L172-L184) [src/vanilla/utils/atomWithStorage.ts#L222-L260](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/utils/atomWithStorage.ts#L222-L260) [tests/react/vanilla-utils/atomWithStorage.test.tsx#L77-L133](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tests/react/vanilla-utils/atomWithStorage.test.tsx#L77-L133)
- When execution is authorized, use the existing test:spec script for the smallest affected Vitest suite and test:types for API changes, then applicable lint/format checks. This investigation inspected those tests and CI declarations but did not execute them or establish passing status. — [package.json#L71-L75](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/package.json#L71-L75) [vitest.config.mts#L13-L29](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/vitest.config.mts#L13-L29) [.github/workflows/test.yml#L33-L38](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/.github/workflows/test.yml#L33-L38)
- Keep ESM .js import suffixes, strict/exact optional types, isolated declarations, and seven exported entrypoints consistent; build uses --noCheck, so emitted output alone is insufficient type validation. — [src/vanilla.ts#L1-L19](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla.ts#L1-L19) [tsconfig.json#L5-L19](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/tsconfig.json#L5-L19) [package.json#L20-L56](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/package.json#L20-L56) [package.json#L63-L75](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/package.json#L63-L75)
- Treat website/example validation separately from root tests: workspace membership is root plus website, inspected applications declare v2 dependencies, and root lint excludes them. benchmarks/run-all.ts shells out to npx tsx and its header describes generated JSON/chart artifacts; it is not a read-only inspection command. — [pnpm-workspace.yaml#L1-L3](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/pnpm-workspace.yaml#L1-L3) [website/package.json#L34-L40](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/website/package.json#L34-L40) [eslint.config.mjs#L11-L12](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/eslint.config.mjs#L11-L12) [benchmarks/run-all.ts#L5-L38](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/benchmarks/run-all.ts#L5-L38)
- Contribution guidance requests failing tests for core fixes, focused changes, conventional commit types, and discussion-first submission rather than direct contributor PRs. INTERNAL exports warn of changes without notice; none of these instructions authorize writes or releases during this read-only task. — [CONTRIBUTING.md#L15-L26](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/CONTRIBUTING.md#L15-L26) [CONTRIBUTING.md#L56-L70](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/CONTRIBUTING.md#L56-L70) [src/vanilla/internals.ts#L1-L2](https://github.com/pmndrs/jotai/blob/6abd0ae3365e02ab432fba4b6e8e6f00aafbf508/src/vanilla/internals.ts#L1-L2)

Source repository: https://github.com/pmndrs/jotai
Full evidence corpus: https://github.com/Codevetter/codevetter/tree/main/benchmarks/repo-unpacks/jotai.json

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
