diff --git a/examples/prompts/nextjs-supabase-auth.md b/examples/prompts/nextjs-supabase-auth.md index 74942542cf2..8e1b4f40496 100644 --- a/examples/prompts/nextjs-supabase-auth.md +++ b/examples/prompts/nextjs-supabase-auth.md @@ -6,53 +6,124 @@ globs: "**/*.ts, **/*.tsx, **/*.js, **/*.jsx" # Bootstrap Next.js app with Supabase Auth -Create a Next.js app that uses App Router with Supabase Auth. +## Overview of implementing Supabase Auth SSR -Follow Supabase's guidelines for using the `@supabase/ssr` package and Server-Side Auth. Specifically, there should be: +1. 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 -- A utility function to create a client on the client side -- A utility function create a client on the server side, using the Next.js `cookies` API to access the cookies. Use the latest version of the API, where `cookies` must be awaited. -- A utility function to handle refreshing the user session in middleware. +## 🚨 CRITICAL INSTRUCTIONS FOR AI LANGUAGE MODELS 🚨 -## Working with cookies +As an AI language model, you MUST NOT generate any of the following code patterns, as they are DEPRECATED and will BREAK the application: -Use the latest version of `@supabase/ssr`, where cookie options are defined with the `getAll` and `setAll` functions, like so: +```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 APPLICATION +import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs' // ❌ BREAKS APPLICATION +import { createClientComponentClient } from '@supabase/auth-helpers-nextjs' // ❌ BREAKS APPLICATION ``` -const supabase = createServerClient( + +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 GENERATION + +1. 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 + +```typescript +import { createBrowserClient } from '@supabase/ssr' + +export function createClient() { + return createBrowserClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! + ) +} +``` + +## CORRECT SERVER CLIENT IMPLEMENTATION + +```typescript +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 request.cookies.getAll() + return cookieStore.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) - ) + 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. + } }, }, } ) +} ``` -No other cookie options should be provided. +## CORRECT MIDDLEWARE IMPLEMENTATION -## Middleware - -The middleware should use the following `updateSession` function: - -``` +```typescript import { createServerClient } from '@supabase/ssr' import { NextResponse, type NextRequest } from 'next/server' -export async function updateSession(request: NextRequest) { - let supabaseResponse = NextResponse.next({ +export async function middleware(request: NextRequest) { + let supabaseResponse = NextResponse.next({ request, }) @@ -77,10 +148,12 @@ export async function updateSession(request: NextRequest) { } ) - // IMPORTANT: Avoid writing any logic between createServerClient and + // 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() @@ -96,8 +169,8 @@ export async function updateSession(request: NextRequest) { 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: + // 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: @@ -111,4 +184,48 @@ export async function updateSession(request: NextRequest) { 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 STEPS + +Before 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 IMPLEMENTATION + +If you generate code using: +- Individual cookie methods (`get`/`set`/`remove`) +- `auth-helpers-nextjs` package + +The implementation will: +1. Break in production +2. Fail to maintain session state +3. Cause authentication loops +4. Result in security vulnerabilities + +## AI MODEL RESPONSE TEMPLATE + +When asked about Supabase Auth SSR implementation, you MUST: +1. ONLY use code from this guide +2. NEVER suggest deprecated approaches +3. ALWAYS use the exact cookie handling shown above +4. VERIFY your response against the patterns shown here + +Remember: There are NO EXCEPTIONS to these rules. \ No newline at end of file