Next.js 16 + Supabase Auth SSR in a PWA: sessions, cookies, and offline UX
How HTTP-only cookies, proxy.ts session refresh, and an offline shell work together in a production SaaS PWA — without losing auth when the network drops.

Indie builders shipping a PWA + Supabase Auth SSR stack hit the same question on launch day: what happens to JWT refresh when the app goes offline?
This is the pattern we ship in the Vibe PWA Starter-kit — honest scope, no magic background sync.
Cookies, not localStorage
Supabase Auth SSR stores sessions in HTTP-only cookies via @supabase/ssr. That means:
- Server components and route handlers can read the session
- Client JS cannot exfiltrate the refresh token trivially
- Every online navigation can refresh the JWT through your edge proxy
On Next.js 16, proxy.ts runs createServerClient() and copies Set-Cookie headers on redirects — the session survives SSR round-trips.
Offline: what actually happens
The service worker serves a dedicated /offline shell. It does not refresh auth in the background (by design — fewer surprise token races).
When connectivity returns:
- The next navigation hits
proxy.ts - Supabase SSR attempts a silent refresh
- If the refresh token expired during a long offline window → redirect to
/login
That is predictable, debuggable behavior — better than pretending offline PWAs can keep billing-grade sessions forever.
Lemon Squeezy + access control
For paid kits sold through your own deploy, webhooks upsert billing_subscriptions with idempotent Postgres claims. Refunds and cancellations revoke access via the same table — one source of truth for /billing and download gates.
Try it live
Walk through the stack on the hosted demo. Install the PWA, toggle offline mode in DevTools, and navigate back online.
Want the full codebase? The starter-kit is on Gumroad ($100 · 14-day refund · START-HERE docs included).
Passer du papier au système
Ce guide pose le diagnostic ; le pack correspondant livre les fichiers, prompts et checklists pour exécuter sans friction.