<!--
Sitemap:
- [rxfy](/index): Typed, normalized, reactive state — built on RxJS
- [Comparison](/comparison): rxfy versus Redux Toolkit, MobX, Jotai, TanStack Query, and TanStack DB
- [Inspired by](/inspired-by): the libraries and ideas rxfy grew out of
- [Agent Skills](/agent-skills): Accurate rxfy context for AI coding assistants
- [Examples](/examples): Runnable apps, from client-only to fully synced
- [Changelog](/changelog)
- [Getting Started](/getting-started)
- [Create Store](/getting-started/create-store): Normalized reactive state in a client-only app
- [Add SSR](/getting-started/add-ssr): Render the first paint on the server, hydrate with no refetch
- [Add Sync Client](/getting-started/add-sync-client): The full stack: the server publishes, the client syncs
- [Core Concepts](/core-concepts): The ideas rxfy is built on
- [Observables](/core-concepts/observables): A value that changes over time, that you can subscribe to
- [Normalization](/core-concepts/normalization): Store each entity once, reference it by id
- [Late Unwrapping](/core-concepts/late-unwrapping): Unwrap async state at the leaf, not the trunk
- [Server-Side Rendering](/core-concepts/ssr): Dehydrate on the server, hydrate with no refetch
- [rxfy](/rxfy): The core package: atoms, lenses, models, and states
- [createModel](/rxfy/create-model): Typed entities in normalized storage
- [defineState](/rxfy/define-state): Typed, normalized state shapes with fetching and mutations
- [createAtom](/rxfy/create-atom): A reactive cell with synchronous get, set, and modify
- [createLens](/rxfy/create-lens): A two-way view into part of an Atom
- [React Bindings](/react): Hooks and helpers for using rxfy in React
- [useStateData](/react/use-state-data): Fetch, normalize, and subscribe to a query
- [useStatePagedData](/react/use-state-paged-data): Paginated and infinite-scroll lists
- [useModelStore](/react/use-model-store): Subscribe to one normalized entity by id
- [useAtom](/react/use-atom): Two-way binding for any IAtom
- [Pending](/react/pending): Render pending, rejected, and fulfilled UI for any observable
- [usePending](/react/use-pending): The status value behind Pending
- [useObservable](/react/use-observable): Bind a raw Observable to React
- [Sync Client in React](/react/sync-client): StoreProvider, useSyncClient, and update handles
- [rxfy-client](/framework/client): The framework-agnostic browser sync runtime
- [createSyncClient](/framework/client/create-sync-client): Connect a transport and drive the sync loop
- [readSsrGrants](/framework/client/read-ssr-grants): Lift SSR-embedded channel grants
- [rxfy-server](/framework/server): Bind Drizzle tables, write, and publish sync updates
- [defineResource](/framework/server/define-resource): Tie a Drizzle table to an rxfy model
- [createSync](/framework/server/create-server): Wire a storage adapter, hub, and secret into a Live object
- [createInMemoryHub](/framework/server/hub): The socket-keyed pub/sub backbone
- [Writes](/framework/server/writes): sync.create / sync.update / sync.delete and touch
- [Storage adapters](/framework/server/storage-adapters): Persist writes with Drizzle or in memory
- [Sync messages](/framework/server/messages): What travels between server and client
- [Grants](/framework/server/grants): The server signs what it serves; the client subscribes with the token
- [rxfy-ws](/framework/ws): The default WebSocket transport
- [createWsServer](/framework/ws/server): Attach a Hub to WebSocket connections
- [createWsClient](/framework/ws/client): The browser transport with reconnect and replay
- [Custom transports](/framework/ws/custom-transport): Bring your own ClientTransport
- [Guides](/guides): Task-focused walkthroughs of common rxfy patterns
- [Pagination and infinite scroll](/guides/pagination): Load and append pages into one normalized list
-->

# Inspired by \[the libraries and ideas rxfy grew out of]

rxfy is the endpoint of a path through several libraries and ideas. Each one taught
something worth keeping — and, just as often, marked a boundary rxfy decided to cross.
This page credits those influences and records what rxfy took from each, including where
it deliberately diverged.

## DataLoader

The first thing that pointed the way was
[graphql/dataloader](https://github.com/graphql/dataloader). Its interesting move is a
**store keyed by entity id** that not only caches entities but also owns *how each one is
loaded* — a load function batches and dedupes the fetches behind the cache, so the rest of
the app asks for an entity by id and never thinks about the request.

What drew me in was exactly that entity store: a single place where each entity lives once,
addressed by id, shared across everything that reads it. That idea is at the core of rxfy's
[normalized stores](/core-concepts/normalization).

The part rxfy could not keep was the store owning the fetch. When the store loads an entity
straight from its own endpoint, that endpoint is **state-agnostic** — it answers for an id
with no notion of *which view, which query, or which user* asked. There is nowhere to put an
authorization layer: the entity read has no context to authorize against. Security has to live
somewhere, and a per-entity loader is the wrong place for it.

So rxfy splits the two concerns. [States](/rxfy/define-state) do the fetching and normalize
the result into the shared stores, referencing each entity by **id** rather than embedding it.
The entity store still gives you one cell per entity, shared and reactive — but nothing fetches
*through* it. Authorization sits on the **state fetch**, where the request carries the params,
the query, and the caller's identity, and the store holds only what that authorized fetch
produced.

## Focal

The second library that shaped rxfy was
[grammarly/focal](https://github.com/grammarly/focal). It is the clearest example I know of
observables carrying state inside React: state lives in an observable **`Atom`**, a **`Lens`**
focuses a piece of it for reading and writing, and observables embed directly in the view. It made a case I still believe — that Atom and Lens are primitives React
data flow genuinely needs.

What I took is the two primitives themselves. rxfy's [`Atom`](/rxfy/create-atom) is the same
idea — a reactive cell you can read synchronously with `get()`, write with `set()`, and
`modify()` in place — and its [`Lens`](/rxfy/create-lens) is the same functional view-plus-edit
optic, composed with `keyLens` and driven from React through [`useAtom`](/react/use-atom).
Two-way binding in rxfy is a Lens over a store cell.

Where rxfy diverges is scope. Focal is a rendering library: its Atom holds the state *behind a
component*, and `<F.div>` and other proxies push observables into the DOM. rxfy leaves rendering
to React and puts the primitives under a data layer.
