Next.js Integration
StateMesh works with both Next.js App Router and Pages Router. All browser API access is SSR-guarded.
App Router
tsx
// providers.tsx
"use client";
import { StateMeshProvider } from "statemesh-core";
import { mesh } from "./mesh";
export function Providers({ children }: { children: React.ReactNode }) {
return (
<StateMeshProvider mesh={mesh}>
{children}
</StateMeshProvider>
);
}tsx
// app/layout.tsx
import { Providers } from "./providers";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}SSR Safety
All StateMesh features are SSR-safe:
isBrowser()guards all browser API access- URL state is SSR-guarded (no
windowaccess on server) - Persistence adapters check for
localStorage/sessionStorageavailability - Tab sync uses
BroadcastChannelonly in browser
Hydration
For SSR data transfer:
tsx
// Server component
export default async function Page() {
const data = await fetchData();
return (
<>
<script
dangerouslySetInnerHTML={{
__html: `window.__STATEMESH__ = ${JSON.stringify(data)}`
}}
/>
<ClientApp initialData={data} />
</>
);
}tsx
// Client component
"use client";
export function ClientApp({ initialData }: { initialData: Data }) {
// Hydrate on mount
useEffect(() => {
mesh.hydrate(initialData);
}, []);
return <AppContent />;
}Important Notes
TIP
Create the mesh instance outside of React (module scope) to persist across re-renders in development.
WARNING
In Next.js App Router, components are server components by default. Add "use client" to components that use StateMesh hooks.
Next Steps
- Migration — Migrate from other libraries
- Dehydrate & Hydrate — SSR patterns
