# Astro SSR + Supabase: request-scoped client via Astro.cookies
Astro's partial hydration means some code runs at build, some per request, some in the browser. Agents put `createClient` at the top of a `.astro` file or a shared module and it silently does the wrong thing in two of those three places.
## Checkable procedure
1. Enable SSR (`output: 'server'`) if you need per-user pages. With static output there is no request to scope a client to.
2. Build the server client inside the frontmatter of each `.astro` page or in `src/middleware.ts`, per request, with `createServerClient` from `@supabase/ssr` wired to `Astro.cookies` (`getAll`/`setAll`).
3. Never create the client at module scope in `src/lib/`. Module scope in SSR output persists across requests on the server: the classic cross-user session leak.
4. For islands (client components), create a separate browser client with `createBrowserClient` inside the component file, guarded to run only in the browser.
5. Middleware is the right place for the session refresh: run `auth.getClaims()` there so expired tokens refresh before page render, and return the response carrying the refreshed cookies.
## Quick test
Build the site and confirm no Supabase client is constructed at build time for user pages. Then load a user page as two different users and confirm no cross-talk.