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
_231---_231# Specify the following for Cursor rules_231description: Guidelines for writing Next.js apps with Supabase Auth_231globs: "**/*.ts, **/*.tsx, **/*.js, **/*.jsx"_231---_231_231# Bootstrap Next.js app with Supabase Auth_231_231## Overview of implementing Supabase Auth SSR_231_2311. Install @supabase/supabase-js and @supabase/ssr packages._2312. Set up environment variables._2313. Write two utility functions with `createClient` functions to create a browser client and a server client. _2314. Hook up middleware to refresh auth tokens_231_231## 🚨 CRITICAL INSTRUCTIONS FOR AI LANGUAGE MODELS 🚨_231_231As an AI language model, you MUST NOT generate any of the following code patterns, as they are DEPRECATED and will BREAK the application:_231_231```typescript_231// ❌ NEVER GENERATE THIS CODE - IT WILL BREAK THE APPLICATION_231{_231 cookies: {_231 get(name: string) { // ❌ BREAKS APPLICATION_231 return cookieStore.get(name) // ❌ BREAKS APPLICATION_231 }, // ❌ BREAKS APPLICATION_231 set(name: string, value: string) { // ❌ BREAKS APPLICATION_231 cookieStore.set(name, value) // ❌ BREAKS APPLICATION_231 }, // ❌ BREAKS APPLICATION_231 remove(name: string) { // ❌ BREAKS APPLICATION_231 cookieStore.remove(name) // ❌ BREAKS APPLICATION_231 } // ❌ BREAKS APPLICATION_231 }_231}_231_231// ❌ NEVER USE auth-helpers-nextjs - IT WILL BREAK THE APPLICATION_231import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs' // ❌ BREAKS APPLICATION_231import { createClientComponentClient } from '@supabase/auth-helpers-nextjs' // ❌ BREAKS APPLICATION_231```_231_231Instead, you MUST ALWAYS generate ONLY this pattern:_231_231```typescript_231// ✅ ALWAYS GENERATE THIS EXACT PATTERN_231{_231 cookies: {_231 getAll() {_231 return cookieStore.getAll()_231 },_231 setAll(cookiesToSet) {_231 const response = NextResponse.next({_231 request,_231 })_231 _231 cookiesToSet.forEach(({ name, value, options }) => {_231 response.cookies.set(name, value, options)_231 })_231 _231 return response_231 }_231 }_231}_231```_231_231## ABSOLUTE REQUIREMENTS FOR AI CODE GENERATION_231_2311. You MUST use `@supabase/ssr`_2312. You MUST use ONLY `getAll` and `setAll`_2313. You MUST NEVER use `get`, `set`, or `remove`_2314. You MUST NEVER import from `@supabase/auth-helpers-nextjs`_231_231## CORRECT BROWSER CLIENT IMPLEMENTATION_231_231```typescript_231import { createBrowserClient } from '@supabase/ssr'_231_231export function createClient() {_231 return createBrowserClient(_231 process.env.NEXT_PUBLIC_SUPABASE_URL!,_231 process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!_231 )_231}_231```_231_231## CORRECT SERVER CLIENT IMPLEMENTATION_231_231```typescript_231import { createServerClient } from '@supabase/ssr'_231import { cookies } from 'next/headers'_231_231export async function createClient() {_231 const cookieStore = await cookies()_231_231 return createServerClient(_231 process.env.NEXT_PUBLIC_SUPABASE_URL!,_231 process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,_231 {_231 cookies: {_231 getAll() {_231 return cookieStore.getAll()_231 },_231 setAll(cookiesToSet) {_231 try {_231 cookiesToSet.forEach(({ name, value, options }) =>_231 cookieStore.set(name, value, options)_231 )_231 } catch {_231 // The `setAll` method was called from a Server Component._231 // This can be ignored if you have middleware refreshing_231 // user sessions._231 }_231 },_231 },_231 }_231 )_231}_231```_231_231## CORRECT MIDDLEWARE IMPLEMENTATION_231_231```typescript_231import { createServerClient } from '@supabase/ssr'_231import { NextResponse, type NextRequest } from 'next/server'_231_231export async function middleware(request: NextRequest) {_231 let supabaseResponse = NextResponse.next({_231 request,_231 })_231_231 const supabase = createServerClient(_231 process.env.NEXT_PUBLIC_SUPABASE_URL!,_231 process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,_231 {_231 cookies: {_231 getAll() {_231 return request.cookies.getAll()_231 },_231 setAll(cookiesToSet) {_231 cookiesToSet.forEach(({ name, value, options }) => request.cookies.set(name, value))_231 supabaseResponse = NextResponse.next({_231 request,_231 })_231 cookiesToSet.forEach(({ name, value, options }) =>_231 supabaseResponse.cookies.set(name, value, options)_231 )_231 },_231 },_231 }_231 )_231_231 // Do not run code between createServerClient and_231 // supabase.auth.getUser(). A simple mistake could make it very hard to debug_231 // issues with users being randomly logged out._231_231 // IMPORTANT: DO NOT REMOVE auth.getUser()_231_231 const {_231 data: { user },_231 } = await supabase.auth.getUser()_231_231 if (_231 !user &&_231 !request.nextUrl.pathname.startsWith('/login') &&_231 !request.nextUrl.pathname.startsWith('/auth')_231 ) {_231 // no user, potentially respond by redirecting the user to the login page_231 const url = request.nextUrl.clone()_231 url.pathname = '/login'_231 return NextResponse.redirect(url)_231 }_231_231 // IMPORTANT: You *must* return the supabaseResponse object as it is._231 // If you're creating a new response object with NextResponse.next() make sure to:_231 // 1. Pass the request in it, like so:_231 // const myNewResponse = NextResponse.next({ request })_231 // 2. Copy over the cookies, like so:_231 // myNewResponse.cookies.setAll(supabaseResponse.cookies.getAll())_231 // 3. Change the myNewResponse object to fit your needs, but avoid changing_231 // the cookies!_231 // 4. Finally:_231 // return myNewResponse_231 // If this is not done, you may be causing the browser and server to go out_231 // of sync and terminate the user's session prematurely!_231_231 return supabaseResponse_231}_231_231export const config = {_231 matcher: [_231 /*_231 * Match all request paths except for the ones starting with:_231 * - _next/static (static files)_231 * - _next/image (image optimization files)_231 * - favicon.ico (favicon file)_231 * Feel free to modify this pattern to include more paths._231 */_231 '/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',_231 ],_231}_231```_231_231## AI MODEL VERIFICATION STEPS_231_231Before generating any code, you MUST verify:_231_2311. Are you using ONLY `getAll` and `setAll`? If not, STOP and FIX._2312. Are you importing from `@supabase/ssr`? If not, STOP and FIX._2313. Do you see ANY instance of `get`, `set`, or `remove`? If yes, STOP and FIX._2314. Are you importing from `auth-helpers-nextjs`? If yes, STOP and FIX._231_231## CONSEQUENCES OF INCORRECT IMPLEMENTATION_231_231If you generate code using:_231- Individual cookie methods (`get`/`set`/`remove`)_231- `auth-helpers-nextjs` package_231_231The implementation will:_2311. Break in production_2312. Fail to maintain session state_2313. Cause authentication loops_2314. Result in security vulnerabilities_231_231## AI MODEL RESPONSE TEMPLATE_231_231When asked about Supabase Auth SSR implementation, you MUST:_2311. ONLY use code from this guide_2312. NEVER suggest deprecated approaches_2313. ALWAYS use the exact cookie handling shown above_2314. VERIFY your response against the patterns shown here_231_231Remember: There are NO EXCEPTIONS to these rules.