Guide
Supabase session lost after login in a Next.js app
Updated
This applies to apps made with AI app builders that use Supabase Auth with Next.js. The official Supabase setup keeps users signed in with a Proxy (proxy.ts on Next.js 16, middleware.ts before that). The Proxy refreshes the Auth token with supabase.auth.getClaims() and passes the refreshed token to both the server and the browser. It must return the response object that setAll last built, because an earlier response does not carry the refreshed cookies.
Login, emails or payments broke in your live app? Our AI agent fixes it in your code, then tests your live app again.
Fixed in your code, then tested live. Check my app free
Why it happens
Local storage isn't accessible by the server, so for server-side rendering the Supabase tokens need to be stored in a cookie. Server-Side Rendering with Supabase requires cookie-based session storage, and the @supabase/ssr package handles this. Since Next.js Server Components can't write cookies, a Proxy is needed to refresh expired Auth tokens and store them. On Next.js 15 and earlier, a proxy.ts file is never called, so sessions never refresh and users get signed out.
Possible causes
- The Proxy is not set up, so expired Auth tokens are not refreshed and stored by it.
- On Next.js 15 and earlier a proxy.ts file is never called, so sessions never refresh and users get signed out. Before Next.js 16 the file is middleware.ts with an exported middleware function.
- The Proxy returns an earlier response instead of the supabaseResponse object that setAll last built, so the refreshed cookies are not carried and the user is signed out on the next request.
- When a different response is returned, the cookies and cache headers are not copied onto it first.
- The app uses the implicit flow instead of the PKCE flow, so the server cannot access the tokens.
- Next.js route prefetching sends server-side requests before the browser has processed the access and refresh tokens, so those requests have no cookies and the server renders unauthenticated content.
Official fix steps
- Install the @supabase/supabase-js and @supabase/ssr helper packages. (supabase.com)
- Create a .env.local file in the project root and set the project's Supabase URL and key. (supabase.com)
- Create a lib/supabase folder with a file for each type of client, then copy the lib utility functions for each client type. (supabase.com)
- Set up the Proxy so it refreshes the Auth token by calling supabase.auth.getClaims(). On Next.js 15 and earlier the file is middleware.ts, because Next.js renamed it to proxy.ts in version 16. (supabase.com)
- Return the supabaseResponse object that setAll last built, so the refreshed cookies are carried. (supabase.com)
- When you need to return a different response, copy the cookies and the cache headers onto it first. (supabase.com)
- Add a matcher so the Proxy does not run on routes that don't access Supabase. (supabase.com)
- Use getClaims to protect pages and user data, and do not trust getSession inside server code such as the Proxy. (supabase.com)
- If you were using the implicit flow, change to the PKCE flow for server-side rendering. Supabase clients from the @supabase/ssr package use the PKCE flow by default. (supabase.com)
- Redirect users after sign-in to one specific page that does not use Next.js route prefetching. Once the browser client has obtained the tokens, you can send users to pages that use prefetching. (supabase.com)
You can't see it yourself
You're signed in, your customers aren't. Your own signed-in session can hide a problem with how the session cookie is refreshed and passed along. From your own screen you can't tell whether a new visitor stays signed in.
What to do next
App broke after you published it? Our AI agent fixes it in your code, then tests your live app again so you see the result yourself. The first check is free.
Fixed in your code, then tested live. Check my app free
Related: Login broken after publishing: loops or localhost · Works in the preview but not after publishing · Sign-up loops back to the login page: the causes
Sources
VibeFix's free check tries the problem you describe on your live app: tell us what broke, and our AI agent tries it and sends you a screenshot. If you want it fixed, it finds the cause, fixes it in your code and re-checks your live app.
Last checked: 3 November 2026, against the sources listed above.
VibeFix is independent. Lovable, Bolt, Replit, Base44, v0 and Supabase are trademarks of their owners.
Want it fixed?
Our AI agent fixes it in your code and tests your live app again. See pricing.
It starts with a free check that confirms the problem on your live app, no account needed.