Next.js
This guide takes a fresh Next.js App Router project to a fully offline-resilient, single-bootstrap, realtime-synced app.
- An existing Next.js 13+ App Router project.
- (Optional)A backend you can subscribe to — Supabase, or any server that can speak Socket.io, SSE, or raw WebSocket.
- Node 18+.
Install the core package
Install the Next.js integration
withFlux() (the next.config wrapper that generates and injects your service worker), FluxProvider, HydrationGate, ServiceWorkerRegistrar, and the useFlux() / useFluxTime() hooks.Choose your realtime adapter
createPollingAdapter() still gets you full IDB caching, the offline queue, and the SW layer — you're only trading live push updates for a polling interval. Swap in a real adapter later with no changes to your register() calls. If you have no backend at all — static marketing pages or fully hardcoded data — choose the **No realtime backend** option above and use createNoopAdapter() instead. It disables the realtime layer entirely while keeping the rest of the stack.
Define your precache route manifest
Configure withFlux() in next.config
Add your manifest.json
public/manifest.json. Flux's service worker reads it during installation to configure the PWA shell. This step is required for every app — static sites included — because the SW uses the manifest icons and theme colors for the offline splash.Define your types (TypeScript only)
Create your state store
store on register() needs a setState(data) method with this exact signature, because dispatchToStore calls it directly on every IDB cold-boot read, every bootstrap dispatch, and every realtime event (including arrays, delta objects, sparse updates, and deletions).Zustand — native, no adapter needed
Redux Toolkit
Jotai
createStore() since Flux dispatches outside of the React render tree:Stunk
Create the Flux engine singleton
Wrap your app
The hydrate → bootstrap sequence
Your bootstrap API route
Dynamic routes that work offline (optional)
idbGet() on mount — see core-concepts/idb-ttl and ingestion/lru for the full pattern.Your offline fallback page
precacheRoutes and offlineShell in your withFlux() config (Step 5) — otherwise the service worker has nothing to fall back to when a page is neither cached nor reachable.Offline-ready static images (optional)
flux.register(), use CachedImg to store them in Flux's image IDB cache. First render fetches normally and caches in the background; every render after that reads straight from IDB via a blob URL, completely independent of whether they were ever part of a register() payload.If you have no data to sync — a marketing page, a static docs page, anything with no register() calls — you don't need Steps 8 through 14 at all. Skip the engine, the adapter, and the store entirely. You still need Steps 1–6 (install, precache routes, config, manifest). If the page has static images, add Step 15 too. All you need is:
Add every route you want available offline to precacheRoutes, plus your offline shell page from Step 14. The service worker generated by withFlux() precaches these at build time regardless of whether createFlux() is ever called — the SW-level page caching and the data-sync engine are independent systems.