π¨ CRITICAL: DEPRECATED PATTERNS π¨
NEVER generate these patterns - they BREAK the application:
// β NEVER USE - BREAKS APPLICATION { cookies: { get(name: string) { // β BREAKS return cookieStore.get(name) }, set(name: string, value: string) { // β BREAKS cookieStore.set(name, value) }, remove(name: string) { // β BREAKS cookieStore.remove(name) } } }
// β NEVER import from auth-helpers-nextjs - DEPRECATED import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs' // β import { createClientComponentClient } from '@supabase/auth-helpers-nextjs' // β
Critical Patterns
ALWAYS Use This Pattern (REQUIRED)
// β CORRECT - Only use getAll and setAll { cookies: { getAll() { return cookieStore.getAll() }, setAll(cookiesToSet) { cookiesToSet.forEach(({ name, value, options }) => cookieStore.set(name, value, options) ) } } }
Browser Client (REQUIRED)
import { createBrowserClient } from '@supabase/ssr'
export function createClient() { return createBrowserClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! ) }
Server Client (REQUIRED)
import { createServerClient } from '@supabase/ssr' import { cookies } from 'next/headers'
export async function createClient() { const cookieStore = await cookies()
return createServerClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, { cookies: { getAll() { return cookieStore.getAll() }, setAll(cookiesToSet) { try { cookiesToSet.forEach(({ name, value, options }) => cookieStore.set(name, value, options) ) } catch { // Called from Server Component - ignored if middleware refreshes sessions } }, }, } ) }
Middleware (REQUIRED)
import { createServerClient } from '@supabase/ssr' import { NextResponse, type NextRequest } from 'next/server'
export async function middleware(request: NextRequest) { let supabaseResponse = NextResponse.next({ request })
const supabase = createServerClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, { cookies: { getAll() { return request.cookies.getAll() }, setAll(cookiesToSet) { cookiesToSet.forEach(({ name, value }) => request.cookies.set(name, value)) supabaseResponse = NextResponse.next({ request }) cookiesToSet.forEach(({ name, value, options }) => supabaseResponse.cookies.set(name, value, options) ) }, }, } )
// IMPORTANT: DO NOT REMOVE auth.getUser() const { data: { user } } = await supabase.auth.getUser()
if ( !user && !request.nextUrl.pathname.startsWith('/login') && !request.nextUrl.pathname.startsWith('/auth') ) { const url = request.nextUrl.clone() url.pathname = '/login' return NextResponse.redirect(url) }
// MUST return supabaseResponse as-is to avoid session sync issues return supabaseResponse }
export const config = { matcher: [ '/((?!_next/static|_next/image|favicon.ico|.\.(?:svg|png|jpg|jpeg|gif|webp)$).)', ], }
Decision Tree
Need browser client? β Use createBrowserClient from @supabase/ssr Need server client? β Use createServerClient with getAll/setAll Need route protection? β Use middleware with auth.getUser() Need OAuth? β Use signInWithOAuth Need magic link? β Use signInWithOtp
Code Examples
Sign Up / Sign In
// Sign up const { data, error } = await supabase.auth.signUp({ email: 'user@example.com', password: 'secure-password', });
// Sign in const { data, error } = await supabase.auth.signInWithPassword({ email: 'user@example.com', password: 'secure-password', });
// Sign out await supabase.auth.signOut();
Session Management
// Get current session const { data: { session } } = await supabase.auth.getSession();
// Listen to auth changes supabase.auth.onAuthStateChange((event, session) => { if (event === 'SIGNED_IN') { // Handle sign in } });
AI Verification Checklist
Before generating code, VERIFY:
-
β Using ONLY getAll and setAll ?
-
β Importing from @supabase/ssr ?
-
β Any get , set , or remove ? β FIX
-
β Importing from auth-helpers-nextjs ? β FIX
Consequences of incorrect implementation:
-
Breaks in production
-
Fails to maintain session state
-
Causes authentication loops
-
Security vulnerabilities