<!--
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
-->

# Agent Skills \[Accurate rxfy context for AI coding assistants]

rxfy ships **two agent skills** — structured reference libraries that AI coding assistants (Claude Code, GitHub Copilot Agent, Codex, and others) load on demand to get accurate, rxfy-specific guidance without hallucinating APIs.

Without a skill an agent has only its training data: it may invent hook signatures, confuse normalized ids with entity data, or silently omit the `name`/`key` fields that SSR requires. With a skill it has the real API surface and the common pitfalls already in context.

## Two skills — one for setup, one for usage

| Skill        | Use it when                                                                                                                                                                                                             |
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `rxfy-setup` | **Getting rxfy into a project** — starting a new app from a template, or adding rxfy to an existing app at a chosen depth. Routes the two paths, gives the install commands, records the setup variant, then hands off. |
| `rxfy`       | **Working in a project that already has rxfy** — declaring models/states, reading data, SSR, sync, debugging. A task-indexed reference library that orients to your integration level.                                  |

rxfy is one framework you adopt at progressive levels — **Store → +SSR → +Sync**. `rxfy-setup` gets you to a level; `rxfy` is how you work once you're there. During setup, `rxfy-setup` records which variant you chose (in `CLAUDE.md` or memory) so `rxfy` never has to re-detect the project type.

## Install

```bash
# setup / installation front-door
npx skills add vanya2h/rxfy --skill rxfy-setup

# working in an rxfy project
npx skills add vanya2h/rxfy --skill rxfy
```

Installing both is fine — they cover different phases and don't overlap.

## How the `rxfy` skill works

The skill's `SKILL.md` is a small router, not a wall of text. It carries the two invariant rules (`data$` emits ids, not entities; `patch` edits in place while `stale` triggers a refetch) and a **library table** the agent reads from by task. On first contact it detects — from files on disk — whether it's in a scaffolded template or an existing app, and which level the app is at, then opens only the matching mini-guides. A client-only project never pulls sync or grants context.

## What the skill covers

**Store + React (always):**

* Models (`createModel`) and states (`defineState`), including [plain value fields](/rxfy/define-state#plain-value-fields)
* The normalized data flow: `useStateData` returns ids, `useModelStore` gives entities
* `useAtom`, `usePending`, `<Pending>` — async rendering patterns
* Mutations, `set` vs `setRaw`, pagination with `useStatePagedData`
* Lens composition with `createLens` / `keyLens`
* Common mistakes: inline observable creation, `store.get()` on unloaded ids, atom stability, missing-data-after-SSR

**SSR:**

* `name`/`key` requirements, buffered (`onAllReady`), streaming (`<HydrationStream />`), and two-pass (`collectStateData`) modes

**Sync (real-time layer):**

* Binding Drizzle tables with `defineResource` and writing through `sync.create` / `sync.update` / `sync.delete`
* `patch` vs `stale`: which writes publish what, and why lists refresh instead of mutating in place
* The wire protocol and the `rxfy-ws` transports (`createWsServer`, `createWsClient`)
* `createSyncClient`, the `StoreProvider` `syncClient` prop, and `updatesAvailable$` / `applyUpdates`
* Grants and sync hydration: `sync.serve` (signs a channel grant as `$grant`), `sync.hydration`, `createSyncClient` with grant renewal, `readSsrGrants`

**Templates:**

* What each `create-rxfy-app` template (`vite-spa`, `next`, `vite`) already wires, where the model/state lives, and where to add the next entity — so the agent extends the scaffold instead of rebuilding it
