diff --git a/apps/reference/docs/guides/auth/auth-helpers/index.mdx b/apps/reference/docs/guides/auth/auth-helpers/index.mdx index bcb52c6a759..ea3bb8222ee 100644 --- a/apps/reference/docs/guides/auth/auth-helpers/index.mdx +++ b/apps/reference/docs/guides/auth/auth-helpers/index.mdx @@ -46,6 +46,18 @@ A collection of framework-specific Auth utilities for working with Supabase. style={{ height: '100%' }} /> + {/* Remix */} +
+ +
diff --git a/apps/reference/docs/guides/auth/auth-helpers/remix.mdx b/apps/reference/docs/guides/auth/auth-helpers/remix.mdx new file mode 100644 index 00000000000..029b876d7b7 --- /dev/null +++ b/apps/reference/docs/guides/auth/auth-helpers/remix.mdx @@ -0,0 +1,910 @@ +--- +id: remix +title: Supabase Auth with Remix +description: Authentication helpers for loaders and actions in Remix. +sidebar_label: 'Remix' +--- + +import Tabs from '@theme/Tabs' +import TabItem from '@theme/TabItem' + +This submodule provides convenience helpers for implementing user authentication in Remix applications. + +## Install the Remix helper library + + + + + +```sh +npm install @supabase/auth-helpers-remix +``` + +This library supports the following tooling versions: + +- Remix: `>=1.7.2` + + + + +```sh +yarn add @supabase/auth-helpers-remix +``` + +This library supports the following tooling versions: + +- Remix: `>=1.7.2` + + + + +## Set up environment variables + +Retrieve your project URL and anon key in your project's [API settings](https://app.supabase.com/project/_/settings/api) in the Dashboard to set up the following environment variables. For local development you can set them in a `.env` file. See an [example](https://github.com/supabase/auth-helpers/blob/main/examples/remix/.env.example). + +```bash title=".env" +SUPABASE_URL=YOUR_SUPABASE_URL +SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY +``` + +## Loader + + + + +Loader functions run on the server immediately before the component is rendered. They respond to all GET requests on a route. You can create an authenticated Supabase client by calling the `createSupabaseClient` function and passing it your `SUPABASE_URL`, `SUPABASE_ANON_KEY`, and a `Request` and `Response`. + +```jsx +import { json } from '@remix-run/node' // change this import to whatever runtime you are using +import { createSupabaseClient } from '@supabase/auth-helpers-remix' + +export const loader = async ({ request }) => { + const response = new Response() + // an empty response is required for the auth helpers + // to set cookies to manage auth + + const supabaseClient = createSupabaseClient( + process.env.SUPABASE_URL, + process.env.SUPABASE_ANON_KEY, + { request, response } + ) + + const { data } = await supabaseClient.from('test').select('*') + + // in order for the set-cookie header to be set, + // headers must be returned as part of the loader response + return json( + { data }, + { + headers: response.headers, + } + ) +} +``` + +> Supabase will set cookie headers to manage the user's auth session, therefore, the `response.headers` must be returned from the `Loader` function. + + + + +Loader functions run on the server immediately before the component is rendered. You can create an authenticated Supabase client by calling the `createSupabaseClient` function and passing it your `SUPABASE_URL`, `SUPABASE_ANON_KEY`, and a `Request` and `Response`. + +```jsx +import { LoaderFunction, json } from '@remix-run/node' // change this import to whatever runtime you are using +import { createSupabaseClient } from '@supabase/auth-helpers-remix' + +export const loader: LoaderFunction = async ({ + request, +}: { + request: Request, +}) => { + const response = new Response() + const supabaseClient = createSupabaseClient( + process.env.SUPABASE_URL, + process.env.SUPABASE_ANON_KEY, + { request, response } + ) + + const { data } = await supabaseClient.from('test').select('*') + + return json( + { data }, + { + headers: response.headers, + } + ) +} +``` + +> Supabase will set cookie headers to manage the user's auth session, therefore, the `response.headers` must be returned from the `Loader` function. + + + + +## Action + + + + +Action functions run on the server and respond to HTTP requests to a route, other than GET - POST, PUT, PATCH, DELETE etc. You can create an authenticated Supabase client by calling the `createSupabaseClient` function and passing it your `SUPABASE_URL`, `SUPABASE_ANON_KEY`, and a `Request` and `Response`. + +```jsx +import { json } from '@remix-run/node' // change this import to whatever runtime you are using +import { createSupabaseClient } from '@supabase/auth-helpers-remix' + +export const action = async ({ request }) => { + const response = new Response() + + const supabaseClient = createSupabaseClient( + process.env.SUPABASE_URL, + process.env.SUPABASE_ANON_KEY, + { request, response } + ) + + const { data } = await supabaseClient.from('test').select('*') + + return json( + { data }, + { + headers: response.headers, + } + ) +} +``` + +> Supabase will set cookie headers to manage the user's auth session, therefore, the `response.headers` must be returned from the `Action` function. + + + + +Action functions run on the server and respond to HTTP requests to a route, other than GET - POST, PUT, PATCH, DELETE etc. You can create an authenticated Supabase client by calling the `createSupabaseClient` function and passing it your `SUPABASE_URL`, `SUPABASE_ANON_KEY`, and a `Request` and `Response`. + +```jsx +import { ActionFunction, json } from '@remix-run/node' // change this import to whatever runtime you are using +import { createSupabaseClient } from '@supabase/auth-helpers-remix' + +export const action: ActionFunction = async ({ + request, +}: { + request: Request, +}) => { + const response = new Response() + + const supabaseClient = createSupabaseClient( + process.env.SUPABASE_URL, + process.env.SUPABASE_ANON_KEY, + { request, response } + ) + + const { data } = await supabaseClient.from('test').select('*') + + return json( + { data }, + { + headers: response.headers, + } + ) +} +``` + +> Supabase will set cookie headers to manage the user's auth session, therefore, the `response.headers` must be returned from the `Action` function. + + + + +## Session and User + +You can determine if a user is authenticated by checking their session using the `getSession` function. + +```jsx +const { + data: { session }, +} = await supabaseClient.auth.getSession() +``` + +The session contains a user property. + +```jsx +const user = session?.user +``` + +> This is the recommended way for accessing the logged in user. There is also a `getUser()` function but this does not refresh the session if it has expired. + +## Client-side + + + + +In order to use the Supabase client in the browser - fetching data in `useEffect` or subscribing to realtime events - we need to do a little more plumbing. Remix does not include a way to make environment variables available to the browser, so we need to pipe them through from a `loader` function in our `root.jsx` route and attach them to the `window`. + +```jsx title="app/root.jsx" +export const loader = () => { + const { SUPABASE_URL, SUPABASE_ANON_KEY } = process.env + return json({ + env: { + SUPABASE_URL, + SUPABASE_ANON_KEY, + }, + }) +} +``` + +> These may not be stored in `process.env` for environments other than Node. + +Next, we call the `useLoaderData` hook in our component to get the `env` object. + +```jsx title="app/root.jsx" +const { env } = useLoaderData() +``` + +And then, add a `