Getting Started

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
_231
description: Guidelines for writing Next.js apps with Supabase Auth
_231
globs: "**/*.ts, **/*.tsx, **/*.js, **/*.jsx"
_231
---
_231
_231
# Bootstrap Next.js app with Supabase Auth
_231
_231
## Overview of implementing Supabase Auth SSR
_231
_231
1. Install @supabase/supabase-js and @supabase/ssr packages.
_231
2. Set up environment variables.
_231
3. Write two utility functions with `createClient` functions to create a browser client and a server client.
_231
4. Hook up middleware to refresh auth tokens
_231
_231
## 🚨 CRITICAL INSTRUCTIONS FOR AI LANGUAGE MODELS 🚨
_231
_231
As 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
_231
import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs' // ❌ BREAKS APPLICATION
_231
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs' // ❌ BREAKS APPLICATION
_231
```
_231
_231
Instead, 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
_231
1. You MUST use `@supabase/ssr`
_231
2. You MUST use ONLY `getAll` and `setAll`
_231
3. You MUST NEVER use `get`, `set`, or `remove`
_231
4. You MUST NEVER import from `@supabase/auth-helpers-nextjs`
_231
_231
## CORRECT BROWSER CLIENT IMPLEMENTATION
_231
_231
```typescript
_231
import { createBrowserClient } from '@supabase/ssr'
_231
_231
export 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
_231
import { createServerClient } from '@supabase/ssr'
_231
import { cookies } from 'next/headers'
_231
_231
export 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
_231
import { createServerClient } from '@supabase/ssr'
_231
import { NextResponse, type NextRequest } from 'next/server'
_231
_231
export 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
_231
export 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
_231
Before generating any code, you MUST verify:
_231
_231
1. Are you using ONLY `getAll` and `setAll`? If not, STOP and FIX.
_231
2. Are you importing from `@supabase/ssr`? If not, STOP and FIX.
_231
3. Do you see ANY instance of `get`, `set`, or `remove`? If yes, STOP and FIX.
_231
4. Are you importing from `auth-helpers-nextjs`? If yes, STOP and FIX.
_231
_231
## CONSEQUENCES OF INCORRECT IMPLEMENTATION
_231
_231
If you generate code using:
_231
- Individual cookie methods (`get`/`set`/`remove`)
_231
- `auth-helpers-nextjs` package
_231
_231
The implementation will:
_231
1. Break in production
_231
2. Fail to maintain session state
_231
3. Cause authentication loops
_231
4. Result in security vulnerabilities
_231
_231
## AI MODEL RESPONSE TEMPLATE
_231
_231
When asked about Supabase Auth SSR implementation, you MUST:
_231
1. ONLY use code from this guide
_231
2. NEVER suggest deprecated approaches
_231
3. ALWAYS use the exact cookie handling shown above
_231
4. VERIFY your response against the patterns shown here
_231
_231
Remember: There are NO EXCEPTIONS to these rules.