AI Prompt: Bootstrap Next.js app with Supabase Auth
How to use
Copy the prompt to a file in your repo.
Use the "include file" feature from your AI tool to include the prompt when chatting with your AI assistant. For example, with GitHub Copilot, use #<filename>, in Cursor, use @Files, and in Zed, use /file.
Prompt
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225# Bootstrap Next.js app with Supabase Auth## Overview of implementing Supabase Auth SSR1. Install @supabase/supabase-js and @supabase/ssr packages.2. Set up environment variables.3. Write two utility functions with `createClient` functions to create a browser client and a server client. 4. Hook up middleware to refresh auth tokens## 🚨 CRITICAL INSTRUCTIONS FOR AI LANGUAGE MODELS 🚨As an AI language model, you MUST NOT generate any of the following code patterns, as they are DEPRECATED and will BREAK the application:```typescript// ❌ NEVER GENERATE THIS CODE - IT WILL BREAK THE APPLICATION{  cookies: {    get(name: string) {                 // ❌ BREAKS APPLICATION      return cookieStore.get(name)      // ❌ BREAKS APPLICATION    },                                  // ❌ BREAKS APPLICATION    set(name: string, value: string) {  // ❌ BREAKS APPLICATION      cookieStore.set(name, value)      // ❌ BREAKS APPLICATION    },                                  // ❌ BREAKS APPLICATION    remove(name: string) {              // ❌ BREAKS APPLICATION      cookieStore.remove(name)          // ❌ BREAKS APPLICATION    }                                   // ❌ BREAKS APPLICATION  }}// ❌ NEVER USE auth-helpers-nextjs - IT WILL BREAK THE APPLICATIONimport { createMiddlewareClient } from '@supabase/auth-helpers-nextjs'  // ❌ BREAKS APPLICATIONimport { createClientComponentClient } from '@supabase/auth-helpers-nextjs'  // ❌ BREAKS APPLICATION```Instead, you MUST ALWAYS generate ONLY this pattern:```typescript// ✅ ALWAYS GENERATE THIS EXACT PATTERN{  cookies: {    getAll() {      return cookieStore.getAll()    },    setAll(cookiesToSet) {      const response = NextResponse.next({        request,      })            cookiesToSet.forEach(({ name, value, options }) => {        response.cookies.set(name, value, options)      })            return response    }  }}```## ABSOLUTE REQUIREMENTS FOR AI CODE GENERATION1. You MUST use `@supabase/ssr`2. You MUST use ONLY `getAll` and `setAll`3. You MUST NEVER use `get`, `set`, or `remove`4. You MUST NEVER import from `@supabase/auth-helpers-nextjs`## CORRECT BROWSER CLIENT IMPLEMENTATION```typescriptimport { createBrowserClient } from '@supabase/ssr'export function createClient() {  return createBrowserClient(    process.env.NEXT_PUBLIC_SUPABASE_URL!,    process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!  )}```## CORRECT SERVER CLIENT IMPLEMENTATION```typescriptimport { 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_PUBLISHABLE_KEY!,    {      cookies: {        getAll() {          return cookieStore.getAll()        },        setAll(cookiesToSet) {          try {            cookiesToSet.forEach(({ name, value, options }) =>              cookieStore.set(name, value, options)            )          } catch {            // The `setAll` method was called from a Server Component.            // This can be ignored if you have middleware refreshing            // user sessions.          }        },      },    }  )}```## CORRECT MIDDLEWARE IMPLEMENTATION```typescriptimport { 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_PUBLISHABLE_KEY!,    {      cookies: {        getAll() {          return request.cookies.getAll()        },        setAll(cookiesToSet) {          cookiesToSet.forEach(({ name, value, options }) => request.cookies.set(name, value))          supabaseResponse = NextResponse.next({            request,          })          cookiesToSet.forEach(({ name, value, options }) =>            supabaseResponse.cookies.set(name, value, options)          )        },      },    }  )  // Do not run code between createServerClient and  // supabase.auth.getUser(). A simple mistake could make it very hard to debug  // issues with users being randomly logged out.  // 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')  ) {    // no user, potentially respond by redirecting the user to the login page    const url = request.nextUrl.clone()    url.pathname = '/login'    return NextResponse.redirect(url)  }  // IMPORTANT: You *must* return the supabaseResponse object as it is.  // If you're creating a new response object with NextResponse.next() make sure to:  // 1. Pass the request in it, like so:  //    const myNewResponse = NextResponse.next({ request })  // 2. Copy over the cookies, like so:  //    myNewResponse.cookies.setAll(supabaseResponse.cookies.getAll())  // 3. Change the myNewResponse object to fit your needs, but avoid changing  //    the cookies!  // 4. Finally:  //    return myNewResponse  // If this is not done, you may be causing the browser and server to go out  // of sync and terminate the user's session prematurely!  return supabaseResponse}export const config = {  matcher: [    /*     * Match all request paths except for the ones starting with:     * - _next/static (static files)     * - _next/image (image optimization files)     * - favicon.ico (favicon file)     * Feel free to modify this pattern to include more paths.     */    '/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',  ],}```## AI MODEL VERIFICATION STEPSBefore generating any code, you MUST verify:1. Are you using ONLY `getAll` and `setAll`? If not, STOP and FIX.2. Are you importing from `@supabase/ssr`? If not, STOP and FIX.3. Do you see ANY instance of `get`, `set`, or `remove`? If yes, STOP and FIX.4. Are you importing from `auth-helpers-nextjs`? If yes, STOP and FIX.## CONSEQUENCES OF INCORRECT IMPLEMENTATIONIf you generate code using:- Individual cookie methods (`get`/`set`/`remove`)- `auth-helpers-nextjs` packageThe implementation will:1. Break in production2. Fail to maintain session state3. Cause authentication loops4. Result in security vulnerabilities## AI MODEL RESPONSE TEMPLATEWhen asked about Supabase Auth SSR implementation, you MUST:1. ONLY use code from this guide2. NEVER suggest deprecated approaches3. ALWAYS use the exact cookie handling shown above4. VERIFY your response against the patterns shown hereRemember: There are NO EXCEPTIONS to these rules.