| name | mongez-atom-stores |
| description | How to use `AtomStore` and `createAtomStore` to isolate per-request atom state in SSR environments and avoid cross-request state leaks.
TRIGGER when: code imports `AtomStore`, `createAtomStore`, or calls `store.use`, `store.get`, `store.has`, `store.list`, `store.hydrate`, `store.snapshot`, `store.destroy` from `@mongez/atom`; user asks "how do I scope atoms per request in Next.js / Express / Fastify", "how do I avoid SSR state leaks", or "how do I serialize server atom state and rehydrate on the client"; `import { createAtomStore, AtomStore } from "@mongez/atom"`.
SKIP: defining the template atoms themselves (use `mongez-atom-atoms` / `mongez-atom-defining-atoms`); React-side `AtomStoreProvider` / `useAtomStore` (lives in `@mongez/react-atom`); pure client-only apps with no SSR; the sibling `mongez-atom-atom-store` skill — only one of the two should fire for the same request.
|
Atom Stores (SSR)
The module-level atoms registry is shared per Node process. In an SSR context, two concurrent requests would write to the same atoms and see each other's state. AtomStore solves this by giving each request its own bag of scoped atom clones.
Why
const userAtom = createAtom({ key: "auth.user", default: { name: "Anon" } });
userAtom.update({ name: "Alice" });
Usage
import { AtomStore, createAtomStore } from "@mongez/atom";
const store = createAtomStore();
const scopedUser = store.use(userAtom);
scopedUser.update({ name: "Alice" });
userAtom.value;
API
class AtomStore {
use<V, A>(template: Atom<V, A>): Atom<V, A>;
get<V>(key: string): Atom<V> | undefined;
has(key: string): boolean;
list(): Atom<any>[];
hydrate(snapshot: Record<string, unknown>): void;
snapshot(): Record<string, unknown>;
destroy(): void;
}
use(template) → returns the scoped clone, creating it lazily.
hydrate(snapshot) → seeds values for atoms that may not have been accessed yet. Pending values are applied when the atom first enters the store.
snapshot() → serializable record of every scoped atom's current value.
destroy() → unsubscribes events for every scoped atom and clears the store. Always call at the end of a request lifecycle.
React integration
The hook-side wiring lives in @mongez/react-atom: <AtomStoreProvider>, useAtom(template | key), useAtomStore(). See its skills/stores.md.
Server-side hand-off pattern
import { createAtomStore } from "@mongez/atom";
app.get("/users", async (req, res) => {
const store = createAtomStore();
store.hydrate({ "auth.user": req.user });
try {
const html = renderToString(<AppShell store={store} />);
const payload = JSON.stringify(store.snapshot());
res.send();
} finally {
store.destroy();
}
});