The debug logs reveal the root cause: signInWithPassword returns hasSession: true, hasUser: true, but immediately after, getSession() returns false. This means the session is being created by Supabase but the cookies are not being persisted in the browser.
This is a known issue with how @supabase/ssr handles cookies in the browser client. The problem is that the Supabase client is being created fresh each time instead of using a singleton pattern. Let me check and fix the client:
The client is being created fresh each call, but createBrowserClient from @supabase/ssr should handle singleton internally. However, the real issue is that the login is working (session is created), but getSession() immediately after doesn't see it because cookies haven't been written yet.
The fix: Don't check getSession() after login - the session exists in memory. Just navigate. But more importantly, the RSC fetch is failing because the middleware or server isn't seeing the session cookies. Let me also check the login page and simplify the flow:
The issue is clear now: login succeeds (session exists in memory), but immediately after getSession() returns false because the cookies haven't been written to the browser yet. The router.push then tries to navigate but the server-side middleware doesn't see the session.
The fix is to use window.location.href instead of router.push for the redirect after login. This forces a full page reload which gives the cookies time to be written and ensures the server sees them:
Now let me also remove the unused router import since we're using window.location instead:
Fixed the login redirect to use window.location.href instead of Next.js router.push. The issue was that Supabase's signInWithPassword creates the session and returns successfully, but the cookies are written asynchronously. When using router.push, Next.js tries to fetch the RSC payload immediately before the cookies are fully persisted, causing the middleware to not see the session. Using window.location.href forces a full browser navigation which allows cookies to sync properly.
Root Cause: The createBrowserClient in /lib/supabase/client.ts creates a new client instance on every call. By default, createBrowserClient uses localStorage for session persistence, NOT cookies. The session returned by signInWithPassword is stored in localStorage but not synced to cookies. When the browser navigates to /campus, the middleware calls supabase.auth.getUser() which reads from cookies (via request.cookies.getAll()), finds nothing, and redirects back to login.
Files Affected:
/lib/supabase/client.ts - Missing cookie-based storage configMinimal Fix: Configure the browser client to use cookies for storage instead of localStorage:
The browser client now explicitly uses document.cookie for session storage instead of localStorage. This ensures that when signInWithPassword creates a session, the auth tokens are written to cookies that the server middleware can read on subsequent requests.
You can send messages while the preview loads