docs: Update auth-helpers usage from examples (#43345)

## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES
This commit is contained in:
Chris Chinchilla authored and GitHub committed 2026-03-09 10:26:16 +01:00
1 parent 96ac1c2652
commit 579357089b
16 files changed
+166 -136

No files matched your search

@@ -0,0 +1,34 @@
import { createBrowserClient } from '@supabase/ssr'
import { User } from '@supabase/supabase-js'
import { createContext, useContext, useEffect, useState } from 'react'
const supabase = createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!
)
type SupabaseContextType = {
supabase: typeof supabase
user: User | null
}
const SupabaseContext = createContext<SupabaseContextType>({ supabase, user: null })
export function SupabaseProvider({ children }: { children: React.ReactNode }) {
const [user, setUser] = useState<User | null>(null)
useEffect(() => {
supabase.auth.getUser().then(({ data: { user } }) => setUser(user))
const {
data: { subscription },
} = supabase.auth.onAuthStateChange((_event, session) => setUser(session?.user ?? null))
return () => subscription.unsubscribe()
}, [])
return <SupabaseContext.Provider value={{ supabase, user }}>{children}</SupabaseContext.Provider>
}
export const useSupabaseClient = () => useContext(SupabaseContext).supabase
export const useUser = () => useContext(SupabaseContext).user
@@ -10,9 +10,8 @@
"format": "prettier --cache --write \"pages/**/*.{js,jsx,ts,tsx,css,md,json}\""
},
"dependencies": {
"@supabase/auth-helpers-nextjs": "^0.6.0",
"@supabase/auth-helpers-react": "^0.3.1",
"@supabase/auth-ui-react": "^0.2.7",
"@supabase/auth-ui-react": "^0.4.7",
"@supabase/ssr": "latest",
"@supabase/supabase-js": "^2.7.1",
"next": "^13.1.6",
"react": "^18.2.0",
@@ -1,23 +1,17 @@
import { createBrowserSupabaseClient, Session } from '@supabase/auth-helpers-nextjs'
import { SessionContextProvider } from '@supabase/auth-helpers-react'
import { SupabaseProvider, useSupabaseClient } from '@/lib/supabase-context'
import type { AppProps } from 'next/app'
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'
import { useEffect } from 'react'
import '../styles/globals.css'
function MyApp({
Component,
pageProps,
}: AppProps<{
initialSession: Session
}>) {
function MyAppInner({ Component, pageProps }: AppProps) {
const router = useRouter()
const [supabaseClient] = useState(() => createBrowserSupabaseClient())
const supabase = useSupabaseClient()
useEffect(() => {
const {
data: { subscription },
} = supabaseClient.auth.onAuthStateChange((event, session) => {
} = supabase.auth.onAuthStateChange((event) => {
switch (event) {
case 'SIGNED_IN':
router.push('/')
@@ -28,15 +22,16 @@ function MyApp({
}
})
return subscription.unsubscribe
}, [])
}, [supabase, router])
return <Component {...pageProps} />
}
function MyApp(props: AppProps) {
return (
<SessionContextProvider
supabaseClient={supabaseClient}
initialSession={pageProps.initialSession}
>
<Component {...pageProps} />
</SessionContextProvider>
<SupabaseProvider>
<MyAppInner {...props} />
</SupabaseProvider>
)
}
@@ -1,5 +1,6 @@
import { createServerSupabaseClient } from '@supabase/auth-helpers-nextjs'
import { useSupabaseClient, useUser } from '@supabase/auth-helpers-react'
import { useSupabaseClient, useUser } from '@/lib/supabase-context'
import { createServerClient } from '@supabase/ssr'
import { serialize } from 'cookie'
import { RealtimePresenceState } from '@supabase/supabase-js'
import type { GetServerSidePropsContext, NextPage } from 'next'
import { useEffect, useState } from 'react'
@@ -54,14 +55,35 @@ const HomePage: NextPage = () => {
}
export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
// Create authenticated Supabase Client
const supabase = createServerSupabaseClient(ctx)
// Check if we have a session
const {
data: { session },
} = await supabase.auth.getSession()
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!,
{
cookies: {
getAll() {
return Object.entries(ctx.req.cookies).map(([name, value]) => ({
name,
value: value ?? '',
}))
},
setAll(cookiesToSet) {
const existing = ctx.res.getHeader('Set-Cookie') ?? []
ctx.res.setHeader('Set-Cookie', [
...(Array.isArray(existing) ? existing : [String(existing)]),
...cookiesToSet.map(({ name, value, options }) =>
serialize(name, value, options)
),
])
},
},
}
)
if (!session)
const {
data: { user },
} = await supabase.auth.getUser()
if (!user)
return {
redirect: {
destination: '/login',
@@ -71,8 +93,7 @@ export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
return {
props: {
initialSession: session,
user: session.user,
user,
},
}
}
@@ -1,4 +1,4 @@
import { useSupabaseClient, useUser } from '@supabase/auth-helpers-react'
import { useSupabaseClient, useUser } from '@/lib/supabase-context'
import { Auth, ThemeSupa } from '@supabase/auth-ui-react'
import type { NextPage } from 'next'
import styles from '../styles/Home.module.css'
@@ -1,4 +1,6 @@
import { createServerSupabaseClient, User } from '@supabase/auth-helpers-nextjs'
import { createServerClient } from '@supabase/ssr'
import { serialize } from 'cookie'
import { User } from '@supabase/supabase-js'
import { GetServerSidePropsContext } from 'next'
import Link from 'next/link'
@@ -15,14 +17,35 @@ export default function Profile({ user }: { user: User }) {
}
export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
// Create authenticated Supabase Client
const supabase = createServerSupabaseClient(ctx)
// Check if we have a session
const {
data: { session },
} = await supabase.auth.getSession()
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!,
{
cookies: {
getAll() {
return Object.entries(ctx.req.cookies).map(([name, value]) => ({
name,
value: value ?? '',
}))
},
setAll(cookiesToSet) {
const existing = ctx.res.getHeader('Set-Cookie') ?? []
ctx.res.setHeader('Set-Cookie', [
...(Array.isArray(existing) ? existing : [String(existing)]),
...cookiesToSet.map(({ name, value, options }) =>
serialize(name, value, options)
),
])
},
},
}
)
if (!session)
const {
data: { user },
} = await supabase.auth.getUser()
if (!user)
return {
redirect: {
destination: '/login',
@@ -32,8 +55,7 @@ export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
return {
props: {
initialSession: session,
user: session.user,
user,
},
}
}
@@ -1,6 +1,7 @@
'use client'
import CreateRoomModal from '@/components/create-room-modal'
import { User, createClientComponentClient } from '@supabase/auth-helpers-nextjs'
import { createClient } from '@/utils/supabase/client'
import { User } from '@supabase/supabase-js'
import { RealtimeChannel } from '@supabase/supabase-js'
import { useState, useEffect, use } from 'react'
@@ -15,7 +16,7 @@ export default function Chat() {
const [showModal, setShowModal] = useState<boolean>(false)
const [error, setError] = useState<string | null>(null)
const supabase = createClientComponentClient()
const supabase = createClient()
const getChannels = async () => {
const channels = await supabase.from('rooms').select('topic')
@@ -9,7 +9,6 @@
"start": "next start"
},
"dependencies": {
"@supabase/auth-helpers-nextjs": "^0.9.0",
"@supabase/ssr": "latest",
"@supabase/supabase-js": "2.44.0",
"autoprefixer": "10.4.17",
@@ -1,60 +1,26 @@
import { createServerClient, type CookieOptions } from "@supabase/ssr";
import { createServerClient } from "@supabase/ssr";
import { type NextRequest, NextResponse } from "next/server";
export const updateSession = async (request: NextRequest) => {
// This `try/catch` block is only here for the interactive tutorial.
// Feel free to remove once you have Supabase connected.
try {
// Create an unmodified response
let response = NextResponse.next({
request: {
headers: request.headers,
},
});
let supabaseResponse = NextResponse.next({ request });
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!,
{
cookies: {
get(name: string) {
return request.cookies.get(name)?.value;
getAll() {
return request.cookies.getAll();
},
set(name: string, value: string, options: CookieOptions) {
// If the cookie is updated, update the cookies for the request and response
request.cookies.set({
name,
value,
...options,
});
response = NextResponse.next({
request: {
headers: request.headers,
},
});
response.cookies.set({
name,
value,
...options,
});
},
remove(name: string, options: CookieOptions) {
// If the cookie is removed, update the cookies for the request and response
request.cookies.set({
name,
value: "",
...options,
});
response = NextResponse.next({
request: {
headers: request.headers,
},
});
response.cookies.set({
name,
value: "",
...options,
});
setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value }) => request.cookies.set(name, value));
supabaseResponse = NextResponse.next({ request });
cookiesToSet.forEach(({ name, value, options }) =>
supabaseResponse.cookies.set(name, value, options)
);
},
},
},
@@ -64,15 +30,11 @@ export const updateSession = async (request: NextRequest) => {
// https://supabase.com/docs/guides/auth/server-side/nextjs
await supabase.auth.getUser();
return response;
return supabaseResponse;
} catch (e) {
// If you are here, a Supabase client could not be created!
// This is likely because you have not set up environment variables.
// Check out http://localhost:3000 for Next Steps.
return NextResponse.next({
request: {
headers: request.headers,
},
});
return NextResponse.next({ request });
}
};
@@ -1,4 +1,4 @@
import { createServerClient, type CookieOptions } from '@supabase/ssr'
import { createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'
export const createClient = async () => {
@@ -9,23 +9,16 @@ export const createClient = async () => {
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!,
{
cookies: {
get(name: string) {
return cookieStore.get(name)?.value
getAll() {
return cookieStore.getAll()
},
set(name: string, value: string, options: CookieOptions) {
setAll(cookiesToSet) {
try {
cookieStore.set({ name, value, ...options })
} catch (error) {
// The `set` method was called from a Server Component.
// This can be ignored if you have proxy refreshing
// user sessions.
}
},
remove(name: string, options: CookieOptions) {
try {
cookieStore.set({ name, value: '', ...options })
} catch (error) {
// The `delete` method was called from a Server Component.
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 proxy refreshing
// user sessions.
}
@@ -1,11 +1,11 @@
import { Database } from '@/lib/schema'
import { Session, useSupabaseClient } from '@supabase/auth-helpers-react'
import { supabase } from '@/lib/initSupabase'
import { Session } from '@supabase/supabase-js'
import { useEffect, useState } from 'react'
type Todos = Database['public']['Tables']['todos']['Row']
export default function TodoList({ session }: { session: Session }) {
const supabase = useSupabaseClient<Database>()
const [todos, setTodos] = useState<Todos[]>([])
const [newTaskText, setNewTaskText] = useState('')
const [errorText, setErrorText] = useState('')
@@ -24,7 +24,7 @@ export default function TodoList({ session }: { session: Session }) {
}
fetchTodos()
}, [supabase])
}, [])
const addTodo = async (taskText: string) => {
let task = taskText.trim()
@@ -90,7 +90,6 @@ export default function TodoList({ session }: { session: Session }) {
}
const Todo = ({ todo, onDelete }: { todo: Todos; onDelete: () => void }) => {
const supabase = useSupabaseClient<Database>()
const [isCompleted, setIsCompleted] = useState(todo.is_complete)
const toggle = async () => {
@@ -1,6 +1,6 @@
import { createClient } from '@supabase/supabase-js'
import { createBrowserClient } from '@supabase/ssr'
export const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL ?? '',
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY ?? ''
export const supabase = createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!
)
@@ -12,8 +12,8 @@
},
"dependencies": {
"@next/font": "13.1.6",
"@supabase/auth-helpers-react": "^0.3.1",
"@supabase/auth-ui-react": "^0.2.8",
"@supabase/auth-ui-react": "^0.4.7",
"@supabase/ssr": "latest",
"@supabase/supabase-js": "^2.8.0",
"@types/node": "18.14.0",
"@types/react": "18.0.28",
@@ -1,12 +1,6 @@
import { supabase } from '@/lib/initSupabase'
import '@/styles/app.css'
import { SessionContextProvider } from '@supabase/auth-helpers-react'
import type { AppProps } from 'next/app'
export default function App({ Component, pageProps }: AppProps) {
return (
<SessionContextProvider supabaseClient={supabase}>
<Component {...pageProps} />
</SessionContextProvider>
)
return <Component {...pageProps} />
}
@@ -1,11 +1,22 @@
import Head from 'next/head'
import { useSession, useSupabaseClient } from '@supabase/auth-helpers-react'
import { supabase } from '@/lib/initSupabase'
import { Auth, ThemeSupa } from '@supabase/auth-ui-react'
import TodoList from '@/components/TodoList'
import { Session } from '@supabase/supabase-js'
import { useEffect, useState } from 'react'
export default function Home() {
const session = useSession()
const supabase = useSupabaseClient()
const [session, setSession] = useState<Session | null>(null)
useEffect(() => {
supabase.auth.getSession().then(({ data: { session } }) => setSession(session))
const {
data: { subscription },
} = supabase.auth.onAuthStateChange((_event, session) => setSession(session))
return () => subscription.unsubscribe()
}, [])
return (
<>
@@ -5,8 +5,8 @@ This example will set you up for a very common situation: users can sign up or s
This demonstrates how to use:
- User signups using Supabase [Auth](https://supabase.com/auth).
- Supabase [Auth Helpers for Next.js](https://supabase.com/docs/guides/auth/auth-helpers/nextjs).
- Supabase [pre-built Auth UI for React](https://supabase.com/docs/guides/auth/auth-helpers/auth-ui).
- Supabase [SSR Auth for Next.js](https://supabase.com/docs/guides/auth/server-side/nextjs).
- Supabase [pre-built Auth UI for React](https://supabase.com/docs/guides/auth/auth-ui).
- User avatar images using Supabase [Storage](https://supabase.com/storage)
- Public profiles restricted with [Policies](https://supabase.com/docs/guides/auth#policies).
- Frontend using [Next.js](<[nextjs.org/](https://nextjs.org/)>).
@@ -16,8 +16,8 @@ This demonstrates how to use:
- Frontend:
- [Next.js](https://github.com/vercel/next.js) - a React framework for production.
- [Supabase.js](https://supabase.com/docs/library/getting-started) for user management and realtime data syncing.
- Supabase [Auth Helpers for Next.js](https://supabase.com/docs/guides/auth/auth-helpers/nextjs).
- Supabase [pre-built Auth UI for React](https://supabase.com/docs/guides/auth/auth-helpers/auth-ui).
- Supabase [`@supabase/ssr`](https://supabase.com/docs/guides/auth/server-side/nextjs) for SSR auth.
- Supabase [pre-built Auth UI for React](https://supabase.com/docs/guides/auth/auth-ui).
- Backend:
- [supabase.com/dashboard](https://supabase.com/dashboard/): hosted Postgres database with restful API for usage with Supabase.js.