Ssr
How to use `AtomStoreProvider`, `useAtom`, `useAtomStore`, and the hydration utilities (`HydrateAtomsScript`, `readHydration`, `serializeStore`, `serializeSnapshot`) for SSR-safe, per-request atom ...
How to use `AtomStoreProvider`, `useAtom`, `useAtomStore`, and the hydration utilities (`HydrateAtomsScript`, `readHydration`, `serializeStore`, `serializeSnapshot`) for SSR-safe, per-request atom isolation and client hydration. TRIGGER when: code imports `AtomStoreProvider`, `AtomStoreContext`, `useAtom`, `useAtomStore`, `HydrateAtomsScript`, `readHydration`, `serializeStore`, `serializeSnapshot`, `DEFAULT_HYDRATION_SCRIPT_ID`, `AtomStoreProviderProps`, or `HydrateAtomsScriptProps` from `@mo...
Install
Quick install
npx skills add https://github.com/hassanzohdy/mongez-react-atomnpx skills add hassanzohdy/mongez-react-atom --agent claude-codenpx skills add hassanzohdy/mongez-react-atom --agent cursornpx skills add hassanzohdy/mongez-react-atom --agent codexnpx skills add hassanzohdy/mongez-react-atom --agent opencodenpx skills add hassanzohdy/mongez-react-atom --agent github-copilotnpx skills add hassanzohdy/mongez-react-atom --agent windsurfMore install options
Shorthand — useful for multi-skill repos:
npx skills add hassanzohdy/mongez-react-atomManual — clone the repo and drop the folder into your agent's skills directory:
git clone https://github.com/hassanzohdy/mongez-react-atom.gitcp -r mongez-react-atom ~/.claude/skills/Ssr
How to use AtomStoreProvider, useAtom, useAtomStore, and the hydration utilities (HydrateAtomsScript, readHydration, serializeStore, serializeSnapshot) for SSR-safe, per-request atom isolation and client hydration.
TRIGGER when: code imports AtomStoreProvider, AtomStoreContext, useAtom, useAtomStore, HydrateAtomsScript, readHydration, serializeStore, serializeSnapshot, DEFAULT_HYDRATION_SCRIPT_ID, AtomStoreProviderProps, or HydrateAtomsScriptProps from @mo...
---
name: mongez-react-atom-ssr
description: |
How to use AtomStoreProvider, useAtom, useAtomStore, and the hydration utilities (HydrateAtomsScript, readHydration, serializeStore, serializeSnapshot) for SSR-safe, per-request atom isolation and client hydration.AtomStoreProvider
TRIGGER when: code imports , AtomStoreContext, useAtom, useAtomStore, HydrateAtomsScript, readHydration, serializeStore, serializeSnapshot, DEFAULT_HYDRATION_SCRIPT_ID, AtomStoreProviderProps, or HydrateAtomsScriptProps from @mongez/react-atom; user asks "how do I avoid hydration mismatches with atoms in Next.js App Router", "how do I isolate atom state per SSR request", "how do I pre-fill atoms on the server", or "how do I call an action method safely under SSR"; typical import import { AtomStoreProvider, HydrateAtomsScript, readHydration } from "@mongez/react-atom".mongez-react-atom-atoms
SKIP: client-only single-page apps where module-level singletons are fine — no provider needed, so reach for instead; preset atoms in a non-SSR context use mongez-react-atom-presets; the underlying store primitive createAtomStore and snapshot() itself live in @mongez/atom, the core layer this package wraps; mixed end-to-end flows use mongez-react-atom-recipes.
---SSR & stores
The module-level atom registry is shared per Node process. To keep concurrent SSR requests from leaking state into each other, wrap your tree in <AtomStoreProvider> — each request gets its own scoped clones of every atom that's read inside it.
<AtomStoreProvider>
import { AtomStoreProvider } from "@mongez/react-atom";
<AtomStoreProvider>
<App />
</AtomStoreProvider>
Props:
type AtomStoreProviderProps = {
store?: AtomStore; // bring your own; otherwise auto-created
initialAtoms?: Atom<any>[]; // pre-register these
initialValues?: Record<string, unknown>; // hydration values keyed by atom key
children: React.ReactNode;
};
- An auto-created store is destroyed on unmount.
- A store
passed via props is caller-owned (NOT destroyed by the provider). - initialValues
are applied viasilentUpdateso the first render of subscribers sees the hydrated values; no flash.
useAtom(template | key)
Two overloads.
useAtom(template: Atom<V, A>): Atom<V, A> // → store-scoped clone (or the template if no provider)
useAtom(key: string): Atom<V> | undefined // → scoped clone by key, or undefined
The per-atom hooks (useValue, useState, use, useWatch) already resolve internally — you only need useAtom(template) explicitly when you want to call an action method from an event handler in an SSR-safe way:
function LogoutButton() {
const scopedAuth = useAtom(authAtom);
return <button onClick={() => scopedAuth.logout()}>Log out</button>;
}
The string overload is a legacy escape hatch — prefer the template overload.
useAtomStore()
Returns the active AtomStore or null if no provider is mounted. Use for advanced cases: snapshotting on demand, manually hydrating, integrating with a non-React layer.
Snapshot / Hydrate
serializeSnapshot(snapshot: Record<string, unknown>, options?: { replacer, space }): string
serializeStore(store: AtomStore, options?): string
readHydration(id?: string): Record<string, unknown> | null
<HydrateAtomsScript
snapshot={snapshotOrString}
id="__mongez_atom_state" // optional; default constant
nonce={cspNonce} // optional
/>
- serializeSnapshot
/serializeStoreproduce a string safe to embed in<script type="application/json">:</script>and U+2028/U+2029 are escaped. - <HydrateAtomsScript>
renders an inline JSON script tag. Place it once per<AtomStoreProvider>you want to hydrate. - readHydration()
is the client-side companion: parses the JSON out of the script tag. Returnsnullif missing or malformed.
Why hydrate at all?
Without hydration, atoms on the client start from their default value. For data the server already has (current user, feature flags, initial page data), this means the first render shows a loading state — or worse, a different UI than the server rendered — causing a hydration mismatch or a visible content flash.
Hydration lets you:
- Fetch data once on the server (no extra client round-trip on load).
- Inline the result as JSON in the HTML.
- Have the client's atom start pre-filled — first render matches server HTML, no flash.
Real-world example — pre-loading the current user (Next.js App Router)
// atoms/user.ts — shared between server and client
import { atom } from "@mongez/react-atom";
type User = { id: number; name: string; role: "admin" | "viewer" } | null;
export const currentUserAtom = atom<User>({ key: "currentUser", default: null });
// app/layout.tsx — SERVER component
import { createAtomStore } from "@mongez/atom";
import { AtomStoreProvider, HydrateAtomsScript } from "@mongez/react-atom";
import { getCurrentUser } from "@/lib/auth"; // your server-side auth helper
import { currentUserAtom } from "@/atoms/user";
export default async function RootLayout({ children }: { children: React.ReactNode }) {
// Runs on the server — no client round-trip needed
const user = await getCurrentUser();
const store = createAtomStore();
store.use(currentUserAtom).update(user); // pre-fill the store
return (
<html lang="en">
<body>
<AtomStoreProvider store={store}>
{children}
{/* Serialises atom state into an inline <script type="application/json"> tag */}
<HydrateAtomsScript snapshot={store.snapshot()} />
</AtomStoreProvider>
</body>
</html>
);
}
// app/providers.tsx — CLIENT boundary
"use client";
import { AtomStoreProvider, readHydration } from "@mongez/react-atom";
export function ClientProviders({ children }: { children: React.ReactNode }) {
// readHydration() parses the JSON script tag injected by the server.
// Pass it as initialValues so the client store starts pre-filled.
return (
<AtomStoreProvider initialValues={readHydration() ?? undefined}>
{children}
</AtomStoreProvider>
);
}
// components/UserMenu.tsx — any client component
"use client";
import { currentUserAtom } from "@/atoms/user";
export function UserMenu() {
const user = currentUserAtom.useValue();
// user is never null on first render — the server already fetched it.
// No loading spinner, no hydration mismatch.
if (!user) return <a href="/login">Sign in</a>;
return (
<div>
<span>{user.name}</span>
{user.role === "admin" && <a href="/admin">Admin</a>}
</div>
);
}
Without this pattern currentUserAtom.useValue() would be null on the client's first render even though the server knew the user — you'd see a brief "Sign in" flicker before the client fetched and re-rendered.
End-to-end minimal example
// server component
import { createAtomStore } from "@mongez/atom";
import { AtomStoreProvider, HydrateAtomsScript } from "@mongez/react-atom";
export default function Layout({ children }) {
const store = createAtomStore();
store.use(someAtom).update(serverFetchedValue);
return (
<AtomStoreProvider store={store}>
{children}
<HydrateAtomsScript snapshot={store.snapshot()} />
</AtomStoreProvider>
);
}
// client root
"use client";
import { AtomStoreProvider, readHydration } from "@mongez/react-atom";
export function ClientRoot({ children }) {
return (
<AtomStoreProvider initialValues={readHydration() ?? undefined}>
{children}
</AtomStoreProvider>
);
}
Concurrent isolation
<AtomStoreProvider>` instances are independent. Two providers in different parts of the tree don't share state — useful for multi-tenant dashboards or A/B split views.
<>
<AtomStoreProvider>
<TenantA />
</AtomStoreProvider>
<AtomStoreProvider>
<TenantB />
</AtomStoreProvider>
</>
---
Source: https://github.com/hassanzohdy/mongez-react-atom
Author: hassanzohdy
Discovered via: skillsdirectory.com
Genre: development
SKILL.md source
---
name: Ssr
description: How to use `AtomStoreProvider`, `useAtom`, `useAtomStore`, and the hydration utilities (`HydrateAtomsScript`, `readHydration`, `serializeStore`, `serializeSnapshot`) for SSR-safe, per-request atom ...
---
# Ssr
How to use `AtomStoreProvider`, `useAtom`, `useAtomStore`, and the hydration utilities (`HydrateAtomsScript`, `readHydration`, `serializeStore`, `serializeSnapshot`) for SSR-safe, per-request atom isolation and client hydration.
TRIGGER when: code imports `AtomStoreProvider`, `AtomStoreContext`, `useAtom`, `useAtomStore`, `HydrateAtomsScript`, `readHydration`, `serializeStore`, `serializeSnapshot`, `DEFAULT_HYDRATION_SCRIPT_ID`, `AtomStoreProviderProps`, or `HydrateAtomsScriptProps` from `@mo...
---
name: mongez-react-atom-ssr
description: |
How to use `AtomStoreProvider`, `useAtom`, `useAtomStore`, and the hydration utilities (`HydrateAtomsScript`, `readHydration`, `serializeStore`, `serializeSnapshot`) for SSR-safe, per-request atom isolation and client hydration.
TRIGGER when: code imports `AtomStoreProvider`, `AtomStoreContext`, `useAtom`, `useAtomStore`, `HydrateAtomsScript`, `readHydration`, `serializeStore`, `serializeSnapshot`, `DEFAULT_HYDRATION_SCRIPT_ID`, `AtomStoreProviderProps`, or `HydrateAtomsScriptProps` from `@mongez/react-atom`; user asks "how do I avoid hydration mismatches with atoms in Next.js App Router", "how do I isolate atom state per SSR request", "how do I pre-fill atoms on the server", or "how do I call an action method safely under SSR"; typical import `import { AtomStoreProvider, HydrateAtomsScript, readHydration } from "@mongez/react-atom"`.
SKIP: client-only single-page apps where module-level singletons are fine — no provider needed, so reach for `mongez-react-atom-atoms` instead; preset atoms in a non-SSR context use `mongez-react-atom-presets`; the underlying store primitive `createAtomStore` and `snapshot()` itself live in `@mongez/atom`, the core layer this package wraps; mixed end-to-end flows use `mongez-react-atom-recipes`.
---
# SSR & stores
The module-level atom registry is shared per Node process. To keep concurrent SSR requests from leaking state into each other, wrap your tree in `<AtomStoreProvider>` — each request gets its own scoped clones of every atom that's read inside it.
## `<AtomStoreProvider>`
```tsx
import { AtomStoreProvider } from "@mongez/react-atom";
<AtomStoreProvider>
<App />
</AtomStoreProvider>
```
Props:
```ts
type AtomStoreProviderProps = {
store?: AtomStore; // bring your own; otherwise auto-created
initialAtoms?: Atom<any>[]; // pre-register these
initialValues?: Record<string, unknown>; // hydration values keyed by atom key
children: React.ReactNode;
};
```
- An auto-created store is destroyed on unmount.
- A `store` passed via props is caller-owned (NOT destroyed by the provider).
- `initialValues` are applied via `silentUpdate` so the first render of subscribers sees the hydrated values; no flash.
## `useAtom(template | key)`
Two overloads.
```ts
useAtom(template: Atom<V, A>): Atom<V, A> // → store-scoped clone (or the template if no provider)
useAtom(key: string): Atom<V> | undefined // → scoped clone by key, or undefined
```
The per-atom hooks (`useValue`, `useState`, `use`, `useWatch`) already resolve internally — you only need `useAtom(template)` explicitly when you want to call an action method from an event handler in an SSR-safe way:
```tsx
function LogoutButton() {
const scopedAuth = useAtom(authAtom);
return <button onClick={() => scopedAuth.logout()}>Log out</button>;
}
```
The string overload is a legacy escape hatch — prefer the template overload.
## `useAtomStore()`
Returns the active `AtomStore` or `null` if no provider is mounted. Use for advanced cases: snapshotting on demand, manually hydrating, integrating with a non-React layer.
## Snapshot / Hydrate
```ts
serializeSnapshot(snapshot: Record<string, unknown>, options?: { replacer, space }): string
serializeStore(store: AtomStore, options?): string
readHydration(id?: string): Record<string, unknown> | null
<HydrateAtomsScript
snapshot={snapshotOrString}
id="__mongez_atom_state" // optional; default constant
nonce={cspNonce} // optional
/>
```
- `serializeSnapshot` / `serializeStore` produce a string safe to embed in `<script type="application/json">`: `</script>` and U+2028/U+2029 are escaped.
- `<HydrateAtomsScript>` renders an inline JSON script tag. Place it once per `<AtomStoreProvider>` you want to hydrate.
- `readHydration()` is the client-side companion: parses the JSON out of the script tag. Returns `null` if missing or malformed.
### Why hydrate at all?
Without hydration, atoms on the client start from their `default` value. For data the server already has (current user, feature flags, initial page data), this means the first render shows a loading state — or worse, a different UI than the server rendered — causing a **hydration mismatch** or a visible content flash.
Hydration lets you:
1. Fetch data once on the server (no extra client round-trip on load).
2. Inline the result as JSON in the HTML.
3. Have the client's atom start pre-filled — first render matches server HTML, no flash.
### Real-world example — pre-loading the current user (Next.js App Router)
```ts
// atoms/user.ts — shared between server and client
import { atom } from "@mongez/react-atom";
type User = { id: number; name: string; role: "admin" | "viewer" } | null;
export const currentUserAtom = atom<User>({ key: "currentUser", default: null });
```
```tsx
// app/layout.tsx — SERVER component
import { createAtomStore } from "@mongez/atom";
import { AtomStoreProvider, HydrateAtomsScript } from "@mongez/react-atom";
import { getCurrentUser } from "@/lib/auth"; // your server-side auth helper
import { currentUserAtom } from "@/atoms/user";
export default async function RootLayout({ children }: { children: React.ReactNode }) {
// Runs on the server — no client round-trip needed
const user = await getCurrentUser();
const store = createAtomStore();
store.use(currentUserAtom).update(user); // pre-fill the store
return (
<html lang="en">
<body>
<AtomStoreProvider store={store}>
{children}
{/* Serialises atom state into an inline <script type="application/json"> tag */}
<HydrateAtomsScript snapshot={store.snapshot()} />
</AtomStoreProvider>
</body>
</html>
);
}
```
```tsx
// app/providers.tsx — CLIENT boundary
"use client";
import { AtomStoreProvider, readHydration } from "@mongez/react-atom";
export function ClientProviders({ children }: { children: React.ReactNode }) {
// readHydration() parses the JSON script tag injected by the server.
// Pass it as initialValues so the client store starts pre-filled.
return (
<AtomStoreProvider initialValues={readHydration() ?? undefined}>
{children}
</AtomStoreProvider>
);
}
```
```tsx
// components/UserMenu.tsx — any client component
"use client";
import { currentUserAtom } from "@/atoms/user";
export function UserMenu() {
const user = currentUserAtom.useValue();
// user is never null on first render — the server already fetched it.
// No loading spinner, no hydration mismatch.
if (!user) return <a href="/login">Sign in</a>;
return (
<div>
<span>{user.name}</span>
{user.role === "admin" && <a href="/admin">Admin</a>}
</div>
);
}
```
Without this pattern `currentUserAtom.useValue()` would be `null` on the client's first render even though the server knew the user — you'd see a brief "Sign in" flicker before the client fetched and re-rendered.
## End-to-end minimal example
```tsx
// server component
import { createAtomStore } from "@mongez/atom";
import { AtomStoreProvider, HydrateAtomsScript } from "@mongez/react-atom";
export default function Layout({ children }) {
const store = createAtomStore();
store.use(someAtom).update(serverFetchedValue);
return (
<AtomStoreProvider store={store}>
{children}
<HydrateAtomsScript snapshot={store.snapshot()} />
</AtomStoreProvider>
);
}
```
```tsx
// client root
"use client";
import { AtomStoreProvider, readHydration } from "@mongez/react-atom";
export function ClientRoot({ children }) {
return (
<AtomStoreProvider initialValues={readHydration() ?? undefined}>
{children}
</AtomStoreProvider>
);
}
```
## Concurrent isolation
`<AtomStoreProvider>` instances are independent. Two providers in different parts of the tree don't share state — useful for multi-tenant dashboards or A/B split views.
```tsx
<>
<AtomStoreProvider>
<TenantA />
</AtomStoreProvider>
<AtomStoreProvider>
<TenantB />
</AtomStoreProvider>
</>
```
---
**Source**: https://github.com/hassanzohdy/mongez-react-atom
**Author**: hassanzohdy
**Discovered via**: skillsdirectory.com
**Genre**: development
Related skills 6
caveman
Ultra-compressed communication mode. Cuts token usage ~75% by speaking like caveman while keeping full technical accuracy. Supports intensity levels: lite, full (default), ultra, wenyan-lite, wenyan-full, wenyan-ultra. Use when user says "caveman mode", "talk like caveman", "use caveman", "less tokens", "be brief", or invokes /caveman. Also auto-triggers when token efficiency is requested.
secure-linux-web-hosting
Use when setting up, hardening, or reviewing a cloud server for self-hosting, including DNS, SSH, firewalls, Nginx, static-site hosting, reverse-proxying an app, HTTPS with Let's Encrypt or ACME clients, safe HTTP-to-HTTPS redirects, or optional post-launch network tuning such as BBR.
readme-i18n
Use when the user wants to translate a repository README, make a repo multilingual, localize docs, add a language switcher, internationalize the README, or update localized README variants in a GitHub-style repository.
lark-shared
Use when first setting up lark-cli, running auth login, switching user/bot identity (--as), handling permission denied or scope errors, needing to update lark-cli, or seeing _notice in JSON output.
improve-codebase-architecture
Find deepening opportunities in a codebase, informed by the domain language in CONTEXT.md and the decisions in docs/adr/. Use when the user wants to improve architecture, find refactoring opportunities, consolidate tightly-coupled modules, or make a codebase more testable and AI-navigable.
paper-context-resolver
Optional RigorPilot helper for README-first deep learning repo reproduction. Use only when the README and repository files leave a narrow reproduction-critical gap and the task is to resolve a specific paper detail such as dataset split, preprocessing, evaluation protocol, checkpoint mapping, or runtime assumption from primary paper sources while recording conflicts. Do not use for general paper summary, repo scanning, environment setup, command execution, title-only paper lookup, or replacin...