Skip to content

Latest commit

 

History

History
379 lines (190 loc) · 7.52 KB

File metadata and controls

379 lines (190 loc) · 7.52 KB

---

description: Guidelines for writing Next.js apps with Supabase Auth

globs: "**/*.ts, **/*.tsx, **/*.js, **/*.jsx"

---

# Bootstrap Next.js app with Supabase Auth

## Overview of implementing Supabase Auth SSR

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

## 🚨 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 APPLICATION

import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs'  // ❌ BREAKS APPLICATION

import { 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 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 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

```typescript

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, 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 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.