mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
Update
This commit is contained in:
1 parent
994c4f2718
commit
ce39d131b4
44 files changed
+256
-1287
No files matched your search
@@ -45,7 +45,7 @@ export function getDocsBySlug(slug: string) {
|
||||
// if no match, 404
|
||||
if (!fs.existsSync(fullPath)) {
|
||||
console.log(`\nfile ${fullPath} not found, redirect to 404\n`)
|
||||
fullPath = join(docsDirectory, 'docs/404.mdx')
|
||||
fullPath = join(docsDirectory, 'pages/404.mdx')
|
||||
}
|
||||
|
||||
const fileContents = fs.readFileSync(fullPath, 'utf8')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: '404'
|
||||
description: 'Page not found'
|
||||
---
|
||||
export const meta = {
|
||||
title: '404',
|
||||
description: 'Page not found',
|
||||
}
|
||||
|
||||
# Page not found
|
||||
@@ -47,7 +47,6 @@ export async function getStaticProps({ params }: { params: { slug: string[] } })
|
||||
let doc = getDocsBySlug(slug)
|
||||
const content = await serialize(doc.content || '')
|
||||
|
||||
console.log(doc.content)
|
||||
return {
|
||||
props: {
|
||||
...doc,
|
||||
|
||||
@@ -1,281 +0,0 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'auth-ui',
|
||||
title: 'Auth UI',
|
||||
description: 'A prebuilt, customizable React component for authenticating users.',
|
||||
}
|
||||
|
||||
Auth UI is a pre-built React component for authenticating users.
|
||||
It supports custom themes and extensible styles to match your brand and aesthetic.
|
||||
|
||||
<video width="99%" muted playsInline controls="true">
|
||||
<source
|
||||
src="https://supabase.com/images/blog/lw5-one-more/auth-ui-demo.mp4"
|
||||
type="video/mp4"
|
||||
muted
|
||||
playsInline
|
||||
/>
|
||||
</video>
|
||||
|
||||
## Set up Auth UI
|
||||
|
||||
Install the latest version of [supabase-js](/docs/reference/javascript) and the Auth UI package:
|
||||
|
||||
```bash
|
||||
npm install @supabase/supabase-js @supabase/auth-ui-react
|
||||
```
|
||||
|
||||
### Import the Auth component
|
||||
|
||||
Pass `supabaseClient` from `@supabase/supabase-js` as a prop to the component.
|
||||
|
||||
```js title=/src/index.js
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import { Auth } from '@supabase/auth-ui-react'
|
||||
|
||||
const supabase = createClient('<INSERT PROJECT URL>', '<INSERT PROJECT ANON API KEY>')
|
||||
|
||||
const App = () => <Auth supabaseClient={supabase} />
|
||||
```
|
||||
|
||||
This renders the Auth component without any styling.
|
||||
We recommend using one of the predefined themes to style the UI.
|
||||
Import the theme you want to use and pass it to the `appearence.theme` prop.
|
||||
|
||||
```js lines=4,11 title=/src/index.js
|
||||
import {
|
||||
Auth,
|
||||
// Import predefined theme
|
||||
ThemeSupa,
|
||||
} from '@supabase/auth-ui-react'
|
||||
|
||||
const App = () => (
|
||||
<Auth
|
||||
supabaseClient={supabase}
|
||||
{/* Apply predefined theme */}
|
||||
appearance={{ theme: ThemeSupa }}
|
||||
/>
|
||||
)
|
||||
```
|
||||
|
||||
## Customization
|
||||
|
||||
There are several ways to customize Auth UI:
|
||||
|
||||
- Use one of the [predefined themes](#predefined-themes) that comes with Auth UI
|
||||
- Extend a theme by [overriding the variable tokens](#override-themes) in a theme
|
||||
- [Create your own theme](#create-theme)
|
||||
- [Use your own CSS classes](#custom-css-classes)
|
||||
- [Use inline styles](#custom-inline-styles)
|
||||
- [Use your own labels](#custom-labels)
|
||||
|
||||
### Predefined themes
|
||||
|
||||
Auth UI comes with several themes to customize the appearance. Each predefined theme comes with at least two variations, a `default` variation, and a `dark` variation. You can switch between these themes using the `theme` prop. Import the theme you want to use and pass it to the `appearence.theme` prop.
|
||||
|
||||
```js lines=2,10 title=/src/index.js
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import { Auth, ThemeSupa } from '@supabase/auth-ui-react'
|
||||
|
||||
const supabase = createClient('<INSERT PROJECT URL>', '<INSERT PROJECT ANON API KEY>')
|
||||
|
||||
const App = () => (
|
||||
<Auth
|
||||
supabaseClient={supabase}
|
||||
{/* Apply predefined theme */}
|
||||
appearance={{ theme: ThemeSupa }}
|
||||
/>
|
||||
)
|
||||
```
|
||||
|
||||
<Admonition type="info">
|
||||
|
||||
Currently there is only one predefined theme available, but we plan to add more.
|
||||
|
||||
</Admonition>
|
||||
|
||||
### Switch theme variations
|
||||
|
||||
Auth UI comes with two theme variations: `default` and `dark`. You can switch between these themes with the `theme` prop.
|
||||
|
||||
```js lines=11 title=/src/index.js
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import { Auth, ThemeSupa } from '@supabase/auth-ui-react'
|
||||
|
||||
const supabase = createClient('<INSERT PROJECT URL>', '<INSERT PROJECT ANON API KEY>')
|
||||
|
||||
const App = () => (
|
||||
<Auth
|
||||
supabaseClient={supabase}
|
||||
appearance={{ theme: ThemeSupa }}
|
||||
{/* Set theme to dark */}
|
||||
theme="dark"
|
||||
/>
|
||||
)
|
||||
```
|
||||
|
||||
If you don't pass a value to `theme` it uses the `"default"` theme. You can pass `"dark"` to the theme prop to switch to the `dark` theme. If your theme has other variations, use the name of the variation in this prop.
|
||||
|
||||
### Override themes
|
||||
|
||||
Auth UI themes can be overridden using variable tokens. See the [list of variable tokens](https://github.com/supabase-community/auth-ui/blob/main/packages/react/common/theming/Themes.tsx).
|
||||
|
||||
```js lines=11-18 title=/src/index.js
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import { Auth, ThemeSupa } from '@supabase/auth-ui-react'
|
||||
|
||||
const supabase = createClient('<INSERT PROJECT URL>', '<INSERT PROJECT ANON API KEY>')
|
||||
|
||||
const App = () => (
|
||||
<Auth
|
||||
supabaseClient={supabase}
|
||||
appearance={{
|
||||
theme: ThemeSupa,
|
||||
variables: {
|
||||
default: {
|
||||
colors: {
|
||||
brand: 'red',
|
||||
brandAccent: 'darkred',
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)
|
||||
```
|
||||
|
||||
If you created your own theme, you may not need to override any of the them.
|
||||
|
||||
### Create your own theme {#create-theme}
|
||||
|
||||
You can create your own theme by following the same structure within a `appearance.theme` property.
|
||||
See the list of [tokens within a theme](https://github.com/supabase-community/auth-ui/blob/main/packages/react/common/theming/Themes.tsx).
|
||||
|
||||
```js title=/src/index.js
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import { Auth } from '@supabase/auth-ui-react'
|
||||
|
||||
const supabase = createClient(
|
||||
'<INSERT PROJECT URL>',
|
||||
'<INSERT PROJECT ANON API KEY>'
|
||||
)
|
||||
|
||||
const customTheme = {
|
||||
default: {
|
||||
colors: {
|
||||
brand: 'hsl(153 60.0% 53.0%)',
|
||||
brandAccent: 'hsl(154 54.8% 45.1%)',
|
||||
brandButtonText: 'white',
|
||||
// ..
|
||||
},
|
||||
dark: {
|
||||
colors: {
|
||||
brandButtonText: 'white',
|
||||
defaultButtonBackground: '#2e2e2e',
|
||||
defaultButtonBackgroundHover: '#3e3e3e',
|
||||
//..
|
||||
},
|
||||
},
|
||||
// You can also add more theme variations with different names.
|
||||
evenDarker: {
|
||||
colors: {
|
||||
brandButtonText: 'white',
|
||||
defaultButtonBackground: '#1e1e1e',
|
||||
defaultButtonBackgroundHover: '#2e2e2e',
|
||||
//..
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const App = () => (
|
||||
<Auth
|
||||
supabaseClient={supabase}
|
||||
theme="default" // can also be "dark" or "evenDarker"
|
||||
appearance={{ theme: customTheme}}
|
||||
/>
|
||||
)
|
||||
```
|
||||
|
||||
You can swich between different variations of your theme with the ["theme" prop](#switch-theme-variations).
|
||||
|
||||
### Custom CSS classes {#custom-css-classes}
|
||||
|
||||
You can use custom CSS classes for the following elements:
|
||||
`"button"`, `"container"`, `"anchor"`, `"divider"`, `"label"`, `"input"`, `"loader"`, `"message"`.
|
||||
|
||||
```js title=/src/index.js
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import { Auth } from '@supabase/auth-ui-react'
|
||||
|
||||
const supabase = createClient('<INSERT PROJECT URL>', '<INSERT PROJECT ANON API KEY>')
|
||||
|
||||
const App = () => (
|
||||
<Auth
|
||||
supabaseClient={supabase}
|
||||
appearance={{
|
||||
className: {
|
||||
anchor: 'my-awesome-anchor',
|
||||
button: 'my-awesome-button',
|
||||
//..
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)
|
||||
```
|
||||
|
||||
### Custom inline CSS {#custom-inline-styles}
|
||||
|
||||
You can use custom CSS inline styles for the following elements:
|
||||
`"button"`, `"container"`, `"anchor"`, `"divider"`, `"label"`, `"input"`, `"loader"`, `"message"`.
|
||||
|
||||
```js title=/src/index.js
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import { Auth } from '@supabase/auth-ui-react'
|
||||
|
||||
const supabase = createClient('<INSERT PROJECT URL>', '<INSERT PROJECT ANON API KEY>')
|
||||
|
||||
const App = () => (
|
||||
<Auth
|
||||
supabaseClient={supabase}
|
||||
appearance={{
|
||||
style: {
|
||||
button: { background: 'red', color: 'white' },
|
||||
anchor: { color: 'blue' },
|
||||
//..
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)
|
||||
```
|
||||
|
||||
### Custom labels {#custom-labels}
|
||||
|
||||
You can use custom labels with `localization.variables`. See the [list of labels](https://github.com/supabase-community/auth-ui/blob/main/packages/react/common/lib/Localization/en.json) that can be overwritten.
|
||||
|
||||
```js title=/src/index.js
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import { Auth } from '@supabase/auth-ui-react'
|
||||
|
||||
const supabase = createClient('<INSERT PROJECT URL>', '<INSERT PROJECT ANON API KEY>')
|
||||
|
||||
const App = () => (
|
||||
<Auth
|
||||
supabaseClient={supabase}
|
||||
//highlight-start
|
||||
localization={{
|
||||
variables: {
|
||||
sign_in: {
|
||||
email_label: 'Your email address',
|
||||
password_label: 'Your strong password',
|
||||
},
|
||||
},
|
||||
}}
|
||||
//highlight-end
|
||||
/>
|
||||
)
|
||||
```
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,843 +0,0 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'nextjs',
|
||||
title: 'Supabase Auth with Next.js',
|
||||
description: 'Authentication helpers for Next.js API routes, middleware, and SSR.',
|
||||
sidebar_label: 'Next.js',
|
||||
}
|
||||
|
||||
This submodule provides convenience helpers for implementing user authentication in Next.js applications.
|
||||
|
||||
## Install the Next.js helper library
|
||||
|
||||
<Tabs
|
||||
scrollable
|
||||
size="small"
|
||||
type="underlined"
|
||||
defaultActiveId="npm"
|
||||
>
|
||||
<TabPanel id="npm" label="npm">
|
||||
|
||||
```sh
|
||||
npm install @supabase/auth-helpers-nextjs
|
||||
```
|
||||
|
||||
This library supports the following tooling versions:
|
||||
|
||||
- Node.js: `^10.13.0 || >=12.0.0`
|
||||
- Next.js: `>=10`
|
||||
- Note: Next.js 13 is supported except for the new `app` directory approach. We're working on adding support for this and you can follow along [here](https://github.com/supabase/auth-helpers/issues/341).
|
||||
|
||||
Additionally, install the **React Auth Helpers** for components and hooks that can be used across all React-based frameworks.
|
||||
|
||||
```sh
|
||||
npm install @supabase/auth-helpers-react
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
<TabPanel id="yarn" label="Yarn">
|
||||
|
||||
```sh
|
||||
yarn add @supabase/auth-helpers-nextjs
|
||||
```
|
||||
|
||||
This library supports the following tooling versions:
|
||||
|
||||
- Node.js: `^10.13.0 || >=12.0.0`
|
||||
- Next.js: `>=10`
|
||||
- Note: Next.js 13 is supported except for the new `app` directory approach. We're working on adding support for this and you can follow along [here](https://github.com/supabase/auth-helpers/issues/341).
|
||||
|
||||
Additionally, install the **React Auth Helpers** for components and hooks that can be used across all React-based frameworks.
|
||||
|
||||
```sh
|
||||
yarn add @supabase/auth-helpers-react
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
|
||||
## 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.local` file. See an [example](https://github.com/supabase/auth-helpers/blob/main/examples/nextjs/.env.local.example).
|
||||
|
||||
```bash title=.env.local
|
||||
NEXT_PUBLIC_SUPABASE_URL=YOUR_SUPABASE_URL
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY
|
||||
```
|
||||
|
||||
## Basic Setup
|
||||
|
||||
<Tabs
|
||||
scrollable
|
||||
size="small"
|
||||
type="underlined"
|
||||
defaultActiveId="js"
|
||||
>
|
||||
<TabPanel id="js" label="JavaScript">
|
||||
|
||||
Wrap your `pages/_app.js` component with the `SessionContextProvider` component:
|
||||
|
||||
```jsx title=pages/_app.js
|
||||
import { createBrowserSupabaseClient } from '@supabase/auth-helpers-nextjs'
|
||||
import { SessionContextProvider } from '@supabase/auth-helpers-react'
|
||||
|
||||
function MyApp({ Component, pageProps }) {
|
||||
const router = useRouter()
|
||||
// Create a new supabase browser client on every first render.
|
||||
const [supabaseClient] = useState(() => createBrowserSupabaseClient())
|
||||
|
||||
return (
|
||||
<SessionContextProvider
|
||||
supabaseClient={supabaseClient}
|
||||
initialSession={pageProps.initialSession}
|
||||
>
|
||||
<Component {...pageProps} />
|
||||
</SessionContextProvider>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
<TabPanel id="ts" label="TypeScript">
|
||||
|
||||
Wrap your `pages/_app.tsx` component with the `SessionContextProvider` component:
|
||||
|
||||
```tsx lines=2,8 title=pages/_app.tsx
|
||||
import { createBrowserSupabaseClient } from '@supabase/auth-helpers-nextjs'
|
||||
import { SessionContextProvider, Session } from '@supabase/auth-helpers-react'
|
||||
|
||||
function MyApp({
|
||||
Component,
|
||||
pageProps,
|
||||
}: AppProps<{
|
||||
initialSession: Session
|
||||
}>) {
|
||||
// Create a new supabase browser client on every first render.
|
||||
const [supabaseClient] = useState(() => createBrowserSupabaseClient())
|
||||
|
||||
return (
|
||||
<SessionContextProvider
|
||||
supabaseClient={supabaseClient}
|
||||
initialSession={pageProps.initialSession}
|
||||
>
|
||||
<Component {...pageProps} />
|
||||
</SessionContextProvider>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
|
||||
You can now determine if a user is authenticated by checking that the `user` object returned by the `useUser()` hook is defined.
|
||||
|
||||
## Usage with TypeScript
|
||||
|
||||
You can pass types that were [generated with the Supabase CLI](/docs/reference/javascript/typescript-support#generating-types) to the Supabase Client to get enhanced type safety and auto completion:
|
||||
|
||||
### Browser client
|
||||
|
||||
Creating a new supabase client object:
|
||||
|
||||
```tsx
|
||||
import { createBrowserSupabaseClient } from '@supabase/auth-helpers-nextjs'
|
||||
import { Database } from '../database.types'
|
||||
|
||||
const supabaseClient = createBrowserSupabaseClient<Database>()
|
||||
```
|
||||
|
||||
Retrieving a supabase client object from the SessionContext:
|
||||
|
||||
```tsx
|
||||
import { useSupabaseClient } from '@supabase/auth-helpers-react'
|
||||
import { Database } from '../database.types'
|
||||
|
||||
const supabaseClient = useSupabaseClient<Database>()
|
||||
```
|
||||
|
||||
### Server client
|
||||
|
||||
```tsx
|
||||
// Creating a new supabase server client object (e.g. in API route):
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
import type { Database } from 'types_db'
|
||||
|
||||
export default async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const supabaseServerClient = createServerSupabaseClient<Database>({
|
||||
req,
|
||||
res,
|
||||
})
|
||||
const {
|
||||
data: { user },
|
||||
} = await supabaseServerClient.auth.getUser()
|
||||
|
||||
res.status(200).json({ name: user?.name ?? '' })
|
||||
}
|
||||
```
|
||||
|
||||
## Client-side data fetching with RLS
|
||||
|
||||
For [row level security](/docs/learn/auth-deep-dive/auth-row-level-security) to work properly when fetching data client-side, you need to make sure to use the `supabaseClient` from the `useSupabaseClient` hook and only run your query once the user is defined client-side in the `useUser()` hook:
|
||||
|
||||
```jsx lines=10-17
|
||||
import { Auth, ThemeSupa } from '@supabase/auth-ui-react'
|
||||
import { useUser, useSupabaseClient } from '@supabase/auth-helpers-react'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
const LoginPage = () => {
|
||||
const supabaseClient = useSupabaseClient()
|
||||
const user = useUser()
|
||||
const [data, setData] = useState()
|
||||
|
||||
useEffect(() => {
|
||||
async function loadData() {
|
||||
const { data } = await supabaseClient.from('test').select('*')
|
||||
setData(data)
|
||||
}
|
||||
// Only run query once user is logged in.
|
||||
if (user) loadData()
|
||||
}, [user])
|
||||
|
||||
if (!user)
|
||||
return (
|
||||
<Auth
|
||||
redirectTo="http://localhost:3000/"
|
||||
appearance={{ theme: ThemeSupa }}
|
||||
supabaseClient={supabaseClient}
|
||||
providers={['google', 'github']}
|
||||
socialLayout="horizontal"
|
||||
/>
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
<button onClick={() => supabaseClient.auth.signOut()}>Sign out</button>
|
||||
<p>user:</p>
|
||||
<pre>{JSON.stringify(user, null, 2)}</pre>
|
||||
<p>client-side data fetching with RLS</p>
|
||||
<pre>{JSON.stringify(data, null, 2)}</pre>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default LoginPage
|
||||
```
|
||||
|
||||
## Server-side rendering (SSR)
|
||||
|
||||
Create a server supabase client to retrieve the logged in user's session:
|
||||
|
||||
```jsx title=pages/profile.js
|
||||
import { createServerSupabaseClient } from '@supabase/auth-helpers-nextjs'
|
||||
|
||||
export default function Profile({ user }) {
|
||||
return <div>Hello {user.name}</div>
|
||||
}
|
||||
|
||||
export const getServerSideProps = async (ctx) => {
|
||||
// Create authenticated Supabase Client
|
||||
const supabase = createServerSupabaseClient(ctx)
|
||||
// Check if we have a session
|
||||
const {
|
||||
data: { session },
|
||||
} = await supabase.auth.getSession()
|
||||
|
||||
if (!session)
|
||||
return {
|
||||
redirect: {
|
||||
destination: '/',
|
||||
permanent: false,
|
||||
},
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
initialSession: session,
|
||||
user: session.user,
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Server-side data fetching with RLS
|
||||
|
||||
You can use the server supabase client to run [row level security](/docs/learn/auth-deep-dive/auth-row-level-security) authenticated queries server-side:
|
||||
|
||||
<Tabs
|
||||
scrollable
|
||||
size="small"
|
||||
type="underlined"
|
||||
defaultActiveId="js"
|
||||
>
|
||||
<TabPanel id="js" label="JavaScript">
|
||||
|
||||
```jsx
|
||||
import { createServerSupabaseClient } from '@supabase/auth-helpers-nextjs'
|
||||
|
||||
export default function ProtectedPage({ user, data }) {
|
||||
return (
|
||||
<>
|
||||
<div>Protected content for {user.email}</div>
|
||||
<pre>{JSON.stringify(data, null, 2)}</pre>
|
||||
<pre>{JSON.stringify(user, null, 2)}</pre>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export const getServerSideProps = async (ctx) => {
|
||||
// Create authenticated Supabase Client
|
||||
const supabase = createServerSupabaseClient(ctx)
|
||||
// Check if we have a session
|
||||
const {
|
||||
data: { session },
|
||||
} = await supabase.auth.getSession()
|
||||
|
||||
if (!session)
|
||||
return {
|
||||
redirect: {
|
||||
destination: '/',
|
||||
permanent: false,
|
||||
},
|
||||
}
|
||||
|
||||
// Run queries with RLS on the server
|
||||
const { data } = await supabase.from('users').select('*')
|
||||
|
||||
return {
|
||||
props: {
|
||||
initialSession: session,
|
||||
user: session.user,
|
||||
data: data ?? [],
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
<TabPanel id="ts" label="TypeScript">
|
||||
|
||||
```tsx
|
||||
import { User, createServerSupabaseClient } from '@supabase/auth-helpers-nextjs'
|
||||
import { GetServerSidePropsContext } from 'next'
|
||||
|
||||
export default function ProtectedPage({ user, data }: { user: User; data: any }) {
|
||||
return (
|
||||
<>
|
||||
<div>Protected content for {user.email}</div>
|
||||
<pre>{JSON.stringify(data, null, 2)}</pre>
|
||||
<pre>{JSON.stringify(user, null, 2)}</pre>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
if (!session)
|
||||
return {
|
||||
redirect: {
|
||||
destination: '/',
|
||||
permanent: false,
|
||||
},
|
||||
}
|
||||
|
||||
// Run queries with RLS on the server
|
||||
const { data } = await supabase.from('users').select('*')
|
||||
|
||||
return {
|
||||
props: {
|
||||
initialSession: session,
|
||||
user: session.user,
|
||||
data: data ?? [],
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
|
||||
## Server-side data fetching to OAuth APIs using `provider token` {#oauth-provider-token}
|
||||
|
||||
When using third-party auth providers, sessions are initiated with an additional `provider_token` field which is persisted in the auth cookie and can be accessed within the session object. The `provider_token` can be used to make API requests to the OAuth provider's API endpoints on behalf of the logged-in user.
|
||||
|
||||
<Tabs
|
||||
scrollable
|
||||
size="small"
|
||||
type="underlined"
|
||||
defaultActiveId="js"
|
||||
>
|
||||
<TabPanel id="js" label="JavaScript">
|
||||
|
||||
```jsx
|
||||
import { createServerSupabaseClient } from '@supabase/auth-helpers-nextjs'
|
||||
|
||||
export default function ProtectedPage({ user, allRepos }) {
|
||||
return (
|
||||
<>
|
||||
<div>Protected content for {user.email}</div>
|
||||
<p>Data fetched with provider token:</p>
|
||||
<pre>{JSON.stringify(allRepos, null, 2)}</pre>
|
||||
<p>user:</p>
|
||||
<pre>{JSON.stringify(user, null, 2)}</pre>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export const getServerSideProps = async (ctx) => {
|
||||
// Create authenticated Supabase Client
|
||||
const supabase = createServerSupabaseClient(ctx)
|
||||
// Check if we have a session
|
||||
const {
|
||||
data: { session },
|
||||
} = await supabase.auth.getSession()
|
||||
|
||||
if (!session)
|
||||
return {
|
||||
redirect: {
|
||||
destination: '/',
|
||||
permanent: false,
|
||||
},
|
||||
}
|
||||
|
||||
// Retrieve provider_token & logged in user's third-party id from metadata
|
||||
const { provider_token, user } = session
|
||||
const userId = user.user_metadata.user_name
|
||||
|
||||
const allRepos = await (
|
||||
await fetch(`https://api.github.com/search/repositories?q=user:${userId}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Authorization: `token ${provider_token}`,
|
||||
},
|
||||
})
|
||||
).json()
|
||||
|
||||
return { props: { user, allRepos } }
|
||||
}
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
<TabPanel id="ts" label="TypeScript">
|
||||
|
||||
```tsx
|
||||
import { User, createServerSupabaseClient } from '@supabase/auth-helpers-nextjs'
|
||||
import { GetServerSidePropsContext } from 'next'
|
||||
|
||||
export default function ProtectedPage({ user, allRepos }: { user: User; allRepos: any }) {
|
||||
return (
|
||||
<>
|
||||
<div>Protected content for {user.email}</div>
|
||||
<p>Data fetched with provider token:</p>
|
||||
<pre>{JSON.stringify(allRepos, null, 2)}</pre>
|
||||
<p>user:</p>
|
||||
<pre>{JSON.stringify(user, null, 2)}</pre>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
if (!session)
|
||||
return {
|
||||
redirect: {
|
||||
destination: '/',
|
||||
permanent: false,
|
||||
},
|
||||
}
|
||||
|
||||
// Retrieve provider_token & logged in user's third-party id from metadata
|
||||
const { provider_token, user } = session
|
||||
const userId = user.user_metadata.user_name
|
||||
|
||||
const allRepos = await (
|
||||
await fetch(`https://api.github.com/search/repositories?q=user:${userId}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Authorization: `token ${provider_token}`,
|
||||
},
|
||||
})
|
||||
).json()
|
||||
|
||||
return { props: { user, allRepos } }
|
||||
}
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
|
||||
## Protecting API routes
|
||||
|
||||
Create a server supabase client to retrieve the logged in user's session:
|
||||
|
||||
<Tabs
|
||||
scrollable
|
||||
size="small"
|
||||
type="underlined"
|
||||
defaultActiveId="js"
|
||||
>
|
||||
<TabPanel id="js" label="JavaScript">
|
||||
|
||||
```jsx title=pages/api/protected-route.js
|
||||
import { createServerSupabaseClient } from '@supabase/auth-helpers-nextjs'
|
||||
|
||||
const ProtectedRoute = async (req, res) => {
|
||||
// Create authenticated Supabase Client
|
||||
const supabase = createServerSupabaseClient({ req, res })
|
||||
// Check if we have a session
|
||||
const {
|
||||
data: { session },
|
||||
} = await supabase.auth.getSession()
|
||||
|
||||
if (!session)
|
||||
return res.status(401).json({
|
||||
error: 'not_authenticated',
|
||||
description: 'The user does not have an active session or is not authenticated',
|
||||
})
|
||||
|
||||
// Run queries with RLS on the server
|
||||
const { data } = await supabase.from('test').select('*')
|
||||
res.json(data)
|
||||
}
|
||||
|
||||
export default ProtectedRoute
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
<TabPanel id="ts" label="TypeScript">
|
||||
|
||||
```tsx title=pages/api/protected-route.ts
|
||||
import { NextApiHandler } from 'next'
|
||||
import { createServerSupabaseClient } from '@supabase/auth-helpers-nextjs'
|
||||
|
||||
const ProtectedRoute: NextApiHandler = async (req, res) => {
|
||||
// Create authenticated Supabase Client
|
||||
const supabase = createServerSupabaseClient({ req, res })
|
||||
// Check if we have a session
|
||||
const {
|
||||
data: { session },
|
||||
} = await supabase.auth.getSession()
|
||||
|
||||
if (!session)
|
||||
return res.status(401).json({
|
||||
error: 'not_authenticated',
|
||||
description: 'The user does not have an active session or is not authenticated',
|
||||
})
|
||||
|
||||
// Run queries with RLS on the server
|
||||
const { data } = await supabase.from('test').select('*')
|
||||
res.json(data)
|
||||
}
|
||||
|
||||
export default ProtectedRoute
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
|
||||
## Auth with Next.js Middleware
|
||||
|
||||
As an alternative to protecting individual pages you can use a [Next.js Middleware](https://nextjs.org/docs/middleware) to protect the entire directory or those that match the config object. In the following example, all requests to `/middleware-protected/*` will check whether a user is signed in, if successful the request will be forwarded to the destination route, otherwise the user will be redirected:
|
||||
|
||||
```ts title=middleware.ts
|
||||
import { createMiddlewareSupabaseClient } from '@supabase/auth-helpers-nextjs'
|
||||
import { NextResponse } from 'next/server'
|
||||
import type { NextRequest } from 'next/server'
|
||||
|
||||
export async function middleware(req: NextRequest) {
|
||||
// We need to create a response and hand it to the supabase client to be able to modify the response headers.
|
||||
const res = NextResponse.next()
|
||||
// Create authenticated Supabase Client.
|
||||
const supabase = createMiddlewareSupabaseClient({ req, res })
|
||||
// Check if we have a session
|
||||
const {
|
||||
data: { session },
|
||||
} = await supabase.auth.getSession()
|
||||
|
||||
// Check auth condition
|
||||
if (session?.user.email?.endsWith('@gmail.com')) {
|
||||
// Authentication successful, forward request to protected route.
|
||||
return res
|
||||
}
|
||||
|
||||
// Auth condition not met, redirect to home page.
|
||||
const redirectUrl = req.nextUrl.clone()
|
||||
redirectUrl.pathname = '/'
|
||||
redirectUrl.searchParams.set(`redirectedFrom`, req.nextUrl.pathname)
|
||||
return NextResponse.redirect(redirectUrl)
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: '/middleware-protected',
|
||||
}
|
||||
```
|
||||
|
||||
## Migration Guide
|
||||
|
||||
### Migrating to v0.5.X
|
||||
|
||||
To make these helpers more flexible as well as more maintainable and easier to upgrade for new versions of Next.js, we're stripping them down to the most useful part which is managing the cookies and giving you an authenticated supabase-js client in any environment (client, server, middleware/edge).
|
||||
|
||||
Therefore we're marking the `withApiAuth`, `withPageAuth`, and `withMiddlewareAuth` higher order functions as deprectaed and they will be removed in the next **minor** release (v0.6.X).
|
||||
|
||||
Please follow the steps below to update your API routes, pages, and middleware handlers. Thanks!
|
||||
|
||||
#### `withApiAuth` deprecated!
|
||||
|
||||
Use `createServerSupabaseClient` within your `NextApiHandler`:
|
||||
|
||||
<Tabs
|
||||
scrollable
|
||||
size="small"
|
||||
type="underlined"
|
||||
defaultActiveId="before"
|
||||
>
|
||||
<TabPanel id="before" label="Before">
|
||||
|
||||
```tsx title=pages/api/protected-route.ts
|
||||
import { withApiAuth } from '@supabase/auth-helpers-nextjs'
|
||||
|
||||
export default withApiAuth(async function ProtectedRoute(req, res, supabase) {
|
||||
// Run queries with RLS on the server
|
||||
const { data } = await supabase.from('test').select('*')
|
||||
res.json(data)
|
||||
})
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
<TabPanel id="after" label="After">
|
||||
|
||||
```tsx title=pages/api/protected-route.ts
|
||||
import { NextApiHandler } from 'next'
|
||||
import { createServerSupabaseClient } from '@supabase/auth-helpers-nextjs'
|
||||
|
||||
const ProtectedRoute: NextApiHandler = async (req, res) => {
|
||||
// Create authenticated Supabase Client
|
||||
const supabase = createServerSupabaseClient({ req, res })
|
||||
// Check if we have a session
|
||||
const {
|
||||
data: { session },
|
||||
} = await supabase.auth.getSession()
|
||||
|
||||
if (!session)
|
||||
return res.status(401).json({
|
||||
error: 'not_authenticated',
|
||||
description: 'The user does not have an active session or is not authenticated',
|
||||
})
|
||||
|
||||
// Run queries with RLS on the server
|
||||
const { data } = await supabase.from('test').select('*')
|
||||
res.json(data)
|
||||
}
|
||||
|
||||
export default ProtectedRoute
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
|
||||
#### `withPageAuth` deprecated!
|
||||
|
||||
Use `createServerSupabaseClient` within `getServerSideProps`:
|
||||
|
||||
<Tabs
|
||||
scrollable
|
||||
size="small"
|
||||
type="underlined"
|
||||
defaultActiveId="before"
|
||||
>
|
||||
<TabPanel id="before" label="Before">
|
||||
|
||||
```tsx title=pages/profile.tsx
|
||||
import { withPageAuth, User } from '@supabase/auth-helpers-nextjs'
|
||||
|
||||
export default function Profile({ user }: { user: User }) {
|
||||
return <pre>{JSON.stringify(user, null, 2)}</pre>
|
||||
}
|
||||
|
||||
export const getServerSideProps = withPageAuth({ redirectTo: '/' })
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
<TabPanel id="after" label="After">
|
||||
|
||||
```tsx title=pages/profile.js
|
||||
import { createServerSupabaseClient, User } from '@supabase/auth-helpers-nextjs'
|
||||
import { GetServerSidePropsContext } from 'next'
|
||||
|
||||
export default function Profile({ user }: { user: User }) {
|
||||
return <pre>{JSON.stringify(user, null, 2)}</pre>
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
if (!session)
|
||||
return {
|
||||
redirect: {
|
||||
destination: '/',
|
||||
permanent: false,
|
||||
},
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
initialSession: session,
|
||||
user: session.user,
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
|
||||
#### `withMiddlewareAuth` deprecated!
|
||||
|
||||
<Tabs
|
||||
scrollable
|
||||
size="small"
|
||||
type="underlined"
|
||||
defaultActiveId="before"
|
||||
>
|
||||
<TabPanel id="before" label="Before">
|
||||
|
||||
```tsx title=middleware.ts
|
||||
import { withMiddlewareAuth } from '@supabase/auth-helpers-nextjs'
|
||||
|
||||
export const middleware = withMiddlewareAuth({
|
||||
redirectTo: '/',
|
||||
authGuard: {
|
||||
isPermitted: async (user) => {
|
||||
return user.email?.endsWith('@gmail.com') ?? false
|
||||
},
|
||||
redirectTo: '/insufficient-permissions',
|
||||
},
|
||||
})
|
||||
|
||||
export const config = {
|
||||
matcher: '/middleware-protected',
|
||||
}
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
<TabPanel id="after" label="After">
|
||||
|
||||
```tsx title=middleware.ts
|
||||
import { createMiddlewareSupabaseClient } from '@supabase/auth-helpers-nextjs'
|
||||
import { NextResponse } from 'next/server'
|
||||
import type { NextRequest } from 'next/server'
|
||||
|
||||
export async function middleware(req: NextRequest) {
|
||||
// We need to create a response and hand it to the supabase client to be able to modify the response headers.
|
||||
const res = NextResponse.next()
|
||||
// Create authenticated Supabase Client.
|
||||
const supabase = createMiddlewareSupabaseClient({ req, res })
|
||||
// Check if we have a session
|
||||
const {
|
||||
data: { session },
|
||||
} = await supabase.auth.getSession()
|
||||
|
||||
// Check auth condition
|
||||
if (session?.user.email?.endsWith('@gmail.com')) {
|
||||
// Authentication successful, forward request to protected route.
|
||||
return res
|
||||
}
|
||||
|
||||
// Auth condition not met, redirect to home page.
|
||||
const redirectUrl = req.nextUrl.clone()
|
||||
redirectUrl.pathname = '/'
|
||||
redirectUrl.searchParams.set(`redirectedFrom`, req.nextUrl.pathname)
|
||||
return NextResponse.redirect(redirectUrl)
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: '/middleware-protected',
|
||||
}
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
|
||||
### Migrating to v0.4.X and supabase-js v2
|
||||
|
||||
With the update to `supabase-js` v2 the `auth` API routes are no longer required, therefore you can go ahead and delete your `auth` directory under the `/pages/api/` directory. Please refer to the [v2 migration guide](/docs/reference/javascript/upgrade-guide) for the full set of changes within supabase-js.
|
||||
|
||||
The `/api/auth/logout` API route has been removed, please use the `signout` method instead:
|
||||
|
||||
```jsx
|
||||
<button
|
||||
onClick={async () => {
|
||||
await supabaseClient.auth.signOut()
|
||||
router.push('/')
|
||||
}}
|
||||
>
|
||||
Logout
|
||||
</button>
|
||||
```
|
||||
|
||||
The `supabaseClient` and `supabaseServerClient` have been removed in favor of the `createBrowserSupabaseClient` and `createServerSupabaseClient` methods. This allows you to provide the CLI-generated types to the client:
|
||||
|
||||
```tsx
|
||||
// client-side
|
||||
import type { Database } from 'types_db'
|
||||
const [supabaseClient] = useState(() => createBrowserSupabaseClient<Database>())
|
||||
|
||||
// server-side API route
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
import type { Database } from 'types_db'
|
||||
|
||||
export default async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const supabaseServerClient = createServerSupabaseClient<Database>({
|
||||
req,
|
||||
res,
|
||||
})
|
||||
const {
|
||||
data: { user },
|
||||
} = await supabaseServerClient.auth.getUser()
|
||||
|
||||
res.status(200).json({ name: user?.name ?? '' })
|
||||
}
|
||||
```
|
||||
|
||||
- The `UserProvider` has been replaced by the `SessionContextProvider`. Make sure to wrap your `pages/_app.js` componenent with the `SessionContextProvider`. Then, throughout your application you can use the `useSessionContext` hook to get the `session` and the `useSupabaseClient` hook to get an authenticated `supabaseClient`.
|
||||
- The `useUser` hook now returns the `user` object or `null`.
|
||||
- Usage with TypeScript: You can pass types that were [generated with the Supabase CLI](/docs/reference/javascript/typescript-support#generating-types) to the Supabase Client to get enhanced type safety and auto completion:
|
||||
|
||||
Creating a new supabase client object:
|
||||
|
||||
```tsx
|
||||
import { Database } from '../database.types'
|
||||
|
||||
const [supabaseClient] = useState(() => createBrowserSupabaseClient<Database>())
|
||||
```
|
||||
|
||||
Retrieving a supabase client object from the SessionContext:
|
||||
|
||||
```tsx
|
||||
import { useSupabaseClient } from '@supabase/auth-helpers-react'
|
||||
import { Database } from '../database.types'
|
||||
|
||||
const supabaseClient = useSupabaseClient<Database>()
|
||||
```
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,10 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: faq
|
||||
title: FAQs
|
||||
description: 'Most frequently asked questions regarding Supabase'
|
||||
---
|
||||
id: 'faq',
|
||||
title: 'FAQs',
|
||||
description: 'Most frequently asked questions regarding Supabase',
|
||||
}
|
||||
|
||||
### Where do I find support?
|
||||
|
||||
@@ -38,3 +38,7 @@ We only support PostgreSQL. It's unlikely we'll ever move away from Postgres; ho
|
||||
We officially support [JavaScript](/docs/reference/javascript/installing) and [Flutter](/docs/reference/dart/installing).
|
||||
|
||||
You can find community-supported libraries in our [GitHub Community](https://github.com/supabase-community), and you can also help us to identify the most popular languages by [voting for a new client library](https://github.com/supabase/supabase/discussions/5).
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: docker
|
||||
title: Self-hosting with Docker
|
||||
description: How to configure and deploy Supabase.
|
||||
sidebar_label: Docker
|
||||
---
|
||||
id: 'docker',
|
||||
title: 'Self-hosting with Docker',
|
||||
description: 'How to configure and deploy Supabase.',
|
||||
sidebar_label: 'Docker',
|
||||
}
|
||||
|
||||
Docker is the easiest way to get started with self-hosted Supabase.
|
||||
|
||||
@@ -114,3 +114,7 @@ See the following guides to deploy Docker Compose setup using your preferred too
|
||||
|
||||
- Got a question? [Ask here](https://github.com/supabase/supabase/discussions).
|
||||
- Sign in: [app.supabase.com](https://app.supabase.com)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: overview
|
||||
title: Self Hosting
|
||||
sidebar_label: Overview
|
||||
description: Getting started with Self Hosting.
|
||||
---
|
||||
id: 'overview',
|
||||
title: 'Self Hosting',
|
||||
sidebar_label: 'Overview',
|
||||
description: 'Getting started with Self Hosting.',
|
||||
}
|
||||
|
||||
There are several ways to use Supabase:
|
||||
|
||||
@@ -155,3 +155,7 @@ While Supabase officially supports Docker, we have several other deployment stra
|
||||
- [supabase-kubernetes](https://github.com/supabase-community/supabase-kubernetes) (Unofficial)
|
||||
- [supabase-terraform](https://github.com/supabase-community/supabase-terraform) (Unofficial)
|
||||
- [supabase-traefik](https://github.com/supabase-community/supabase-traefik) (Unofficial)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: appsmith
|
||||
title: 'Appsmith'
|
||||
description: 'Get started with Supabase and Appsmith, an open-source framework for building internal tools.'
|
||||
---
|
||||
id: 'appsmith',
|
||||
title: 'Appsmith',
|
||||
description:
|
||||
'Get started with Supabase and Appsmith, an open-source framework for building internal tools.',
|
||||
}
|
||||
|
||||
This guide explains how to quickly build a Support Dashboard by connecting a Supabase back-end to an Appsmith front-end.
|
||||
|
||||
@@ -166,3 +167,7 @@ SELECT * FROM public."tickets";
|
||||
- [Appsmith](https://www.appsmith.com/) official website.
|
||||
- [Appsmith GitHub](https://github.com/appsmithorg).
|
||||
- [Appsmith](https://docs.appsmith.com/) documentation.
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: auth0
|
||||
title: 'Auth0'
|
||||
description: 'Swap out Supabase authentication with Auth0. Let Auth0 handle tokens and signing users in and out, while Supabase enforces authorization policies with Row Level Security (RLS).'
|
||||
---
|
||||
id: 'auth0',
|
||||
title: 'Auth0',
|
||||
description:
|
||||
'Swap out Supabase authentication with Auth0. Let Auth0 handle tokens and signing users in and out, while Supabase enforces authorization policies with Row Level Security (RLS).',
|
||||
}
|
||||
|
||||
This guide steps through building a Next.js application with Auth0 and Supabase. We configure Auth0 to handle authenticating users and managing tokens, while writing our authorization logic in Supabase - using Row Level Security policies.
|
||||
|
||||
@@ -463,3 +464,7 @@ Now when we refresh our application, we should finally see our list of `todos`!
|
||||
- [Using Next.js and Auth0 with Supabase article](https://auth0.com/blog/using-nextjs-and-auth0-with-supabase/).
|
||||
- [Auth0 community](https://community.auth0.com/).
|
||||
- [Auth0 documentation](https://auth0.com/docs/).
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: authsignal
|
||||
title: 'Authsignal'
|
||||
description: 'Add an MFA step after sign-in. Use Supabase Auth to sign in with email and password and Authsignal to initiate an Authenticator App challenge.'
|
||||
---
|
||||
id: 'authsignal',
|
||||
title: 'Authsignal',
|
||||
description:
|
||||
'Add an MFA step after sign-in. Use Supabase Auth to sign in with email and password and Authsignal to initiate an Authenticator App challenge.',
|
||||
}
|
||||
|
||||
This guide shows how to integrate [Authsignal](https://www.authsignal.com/) with [Next.js](https://nextjs.org/) and [Supabase](https://supabase.com/) in order to add an MFA step after sign-in.
|
||||
|
||||
@@ -582,3 +583,7 @@ Then if you sign out, you'll be prompted to complete an MFA challenge when signi
|
||||
|
||||
- To learn more about Authsignal take a look at the [API Documentation](https://docs.authsignal.com/).
|
||||
- You can customize the look and feel of the Authsignal Prebuilt MFA page [here](https://portal.authsignal.com/organisations/tenants/customizations).
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: clerk
|
||||
title: 'Clerk'
|
||||
description: 'This guide explains how to connect your Supabase database with Clerk, a powerful authentication provider built for the modern web.'
|
||||
---
|
||||
id: 'clerk',
|
||||
title: 'Clerk',
|
||||
description:
|
||||
'This guide explains how to connect your Supabase database with Clerk, a powerful authentication provider built for the modern web.',
|
||||
}
|
||||
|
||||
This guide explains how to connect your Supabase database with [Clerk](https://clerk.dev), an authentication provider built for the modern web.
|
||||
|
||||
@@ -184,3 +185,7 @@ If you would like the requesting user ID from the JWT to automatically populate
|
||||
- [Next.js + Supabase + Clerk tutorial](https://clerk.dev/blog/nextjs-supabase-todos-with-multifactor-authentication)
|
||||
- [Clerk guide for Next.js Authentication](https://docs.clerk.dev/get-started/nextjs)
|
||||
- [Clerk Community Discord channel](https://discord.com/invite/b5rXHjAg7A)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,10 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: dashibase
|
||||
title: 'Dashibase'
|
||||
description: 'Create an internal CRUD dashboard with Supabase and Dashibase in 15 mins.'
|
||||
---
|
||||
id: 'dashibase',
|
||||
title: 'Dashibase',
|
||||
description: 'Create an internal CRUD dashboard with Supabase and Dashibase in 15 mins.',
|
||||
}
|
||||
|
||||
Are you tired of building admin panels? [Dashibase](https://dashibase.com/) is a super fast way to build internal CRUD dashboards with a Notion-like UI.
|
||||
|
||||
@@ -99,3 +99,7 @@ P.S. How long did we take? :)
|
||||
- [Dashibase open-source repo](https://github.com/dashibase)
|
||||
- [Dashibase Twitter](https://twitter.com/dashibase)
|
||||
- [Dashibase Discord](https://discord.gg/crhDFYvbbq)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,13 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: dhiwise
|
||||
title: 'DhiWise'
|
||||
description: 'Get started with Supabase and DhiWise. Convert your Figma designs into Flutter apps, store data, and authenticate your users'
|
||||
---
|
||||
|
||||
import select from '/docs/img/guides/integrations/dhiwise/select.png'
|
||||
import create from '/docs/img/guides/integrations/dhiwise/create.png'
|
||||
id: 'dhiwise',
|
||||
title: 'DhiWise',
|
||||
description:
|
||||
'Get started with Supabase and DhiWise. Convert your Figma designs into Flutter apps, store data, and authenticate your users',
|
||||
}
|
||||
|
||||
This guide explains how to connect Supabase backend to DhiWise Flutter application quickly.
|
||||
|
||||
@@ -66,7 +64,9 @@ After downloading the application source code,
|
||||
|
||||
When you first integrate Supabase in your DhiWise Flutter application, You will be asked to add [Supabase auth key and URL](##step-3-find-the-api-key-and-url). When you add them, all the tables available in your Supabase project will be synced in DhiWise. You can integrate Select and Create queries on your Flutter screen for a particular table in DhiWise.
|
||||
|
||||
<h3> Select records </h3>
|
||||
### Select records
|
||||
|
||||

|
||||
|
||||
#### **Step 1:**
|
||||
|
||||
@@ -197,3 +197,7 @@ Finally, you have added Supabase to your application to create records from your
|
||||
|
||||
- [DhiWise Official Website](https://dhiwise.com)
|
||||
- [DhiWise Documentation](https://docs.dhiwise.com)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: directus
|
||||
title: 'Directus'
|
||||
description: 'In this guide, we will show you how to create a Supabase project, install the Directus platform locally and configure the two to connect.'
|
||||
---
|
||||
id: 'directus',
|
||||
title: 'Directus',
|
||||
description:
|
||||
'In this guide, we will show you how to create a Supabase project, install the Directus platform locally and configure the two to connect.',
|
||||
}
|
||||
|
||||
In this guide, we will demonstrate how to create a new Supabase project, install a fresh instance of the Directus platform, then configure the two to work together seamlessly. If you're unfamiliar with either of these systems, don't worry! We'll start off with an overview of each platform and explain how they complement each other, noting any overlap in capabilities.
|
||||
|
||||
@@ -18,8 +19,7 @@ In this guide, we will demonstrate how to create a new Supabase project, install
|
||||
|
||||
[Directus](https://directus.io/) is an open-source data platform that layers on top of any SQL database, providing a powerful suite of tools. The Directus Engine provides dynamic REST and GraphQL APIs based on your schema, hooks and automation, authentication and access control, and file transformations. Directus Studio enables engineers and non-technical users alike to browse, manage, and visualize database content through a no-code app.
|
||||
|
||||
---
|
||||
|
||||
}
|
||||
Supabase is a suite of open-source tools making Postgres databases, file storage, authentication, and edge functions more accessible to developers of all skill levels. Directus is also developer tooling and additionally provides a Data Studio that is safe and intuitive enough for anyone, including non-technical users, to use. This is the crucial bit that gives the two platforms such a strong “network effect.”
|
||||
|
||||
When these two systems are brought together, you get a scalable datastore, limitless connectivity options, and a no-code app that allows your technical and business teams to collaborate together efficiently.
|
||||
@@ -131,3 +131,7 @@ Below are some additional resources to dive in and start exploring these two pla
|
||||
|
||||
- Explore the [Supabase documentation](https://supabase.com/docs)
|
||||
- Join the Supabase community on [Discord](https://discord.supabase.com/)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,10 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: draftbit
|
||||
title: 'Draftbit'
|
||||
description: 'Connect your Supabase postgres database to your Low-code mobile app.'
|
||||
---
|
||||
id: 'draftbit',
|
||||
title: 'Draftbit',
|
||||
description: 'Connect your Supabase postgres database to your Low-code mobile app.',
|
||||
}
|
||||
|
||||
This guide explains how to connect a Supabase back-end to a Draftbit front-end and then configure all CRUD operations necessary to build a simple mobile app.
|
||||
|
||||
@@ -231,3 +231,7 @@ In the API Request action:
|
||||
- [Draftbit](https://draftb.it/3Fkbask) official website.
|
||||
- [Draftbit Community](https://community.draftbit.com/home).
|
||||
- [Draftbit](https://docs.draftbit.com/) documentation.
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,10 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: fezto
|
||||
title: 'Frontend Zero to One'
|
||||
description: 'Create an app automatically from your Supabase Postgres using OpenAPI'
|
||||
---
|
||||
id: 'fezto',
|
||||
title: 'Frontend Zero to One',
|
||||
description: 'Create an app automatically from your Supabase Postgres using OpenAPI',
|
||||
}
|
||||
|
||||
[Frontend Zero to One is](https://www.fezto.xyz) is a service which creates an app for your Supabase Postgres database on-the-fly without any drag and drop, using the OpenAPI spec provided by PostgREST.
|
||||
|
||||
@@ -27,3 +27,7 @@ You will need:
|
||||
|
||||
Paste both into the [FEZTO Supabase setup page](https://www.fezto.xyz/#/supabase) and click Launch.
|
||||
You can now share and bookmark the browser URL which includes the projectID and anon key with others to launch the same app.
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,10 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: integrations
|
||||
title: 'Supabase Marketplace'
|
||||
description: 'Integrations and Partners'
|
||||
---
|
||||
id: 'integrations',
|
||||
title: 'Supabase Marketplace',
|
||||
description: 'Integrations and Partners',
|
||||
}
|
||||
|
||||
The Supabase Marketplace brings together all the tools you need to extend your Supabase project. This includes:
|
||||
|
||||
@@ -34,3 +34,7 @@ Integrations are assessed on the following criteria:
|
||||
All listings are required to have their own Terms and Conditions, Privacy Policy, and Acceptable Use Policy, and the company must have resources to meet their SLAs.
|
||||
- **Maintainability**
|
||||
All integrations are required to be maintained and functional with Supabase, and the company may be assessed on your ability to remain functional over a long time horizon.
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: keyri
|
||||
title: 'Keyri'
|
||||
description: 'QR authentication for an easy and flexible biometric solution across all platforms.'
|
||||
---
|
||||
id: 'keyri',
|
||||
title: 'Keyri',
|
||||
description:
|
||||
'QR authentication for an easy and flexible biometric solution across all platforms.',
|
||||
}
|
||||
|
||||
Keyri can be used to incorporate sign-in-with-QR functionality into your Supabase app, allowing users to scan a QR code on your web app with your mobile app and be instantly logged into the web app without having to input any credentials.
|
||||
|
||||
@@ -140,3 +141,7 @@ if (response.error != null) {
|
||||
.catchError((error, stackTrace) => _onError(error));
|
||||
}
|
||||
```
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: pgmustard
|
||||
title: 'pgMustard'
|
||||
description: 'Troubleshoot slow queries on Supabase with pgMustard, a visualization tool that also gives advice.'
|
||||
---
|
||||
id: 'pgmustard',
|
||||
title: 'pgMustard',
|
||||
description:
|
||||
'Troubleshoot slow queries on Supabase with pgMustard, a visualization tool that also gives advice.',
|
||||
}
|
||||
|
||||
This guide explains how to troubleshoot slow queries on Supabase using `explain` and pgMustard.
|
||||
|
||||
@@ -66,3 +67,7 @@ We could look into why Postgres isn’t choosing to do an index-only scan here,
|
||||
|
||||
- [pgMustard](https://www.pgmustard.com) official website.
|
||||
- [pgMustard explain glossary](https://www.pgmustard.com/docs/explain).
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: plasmic
|
||||
title: 'Plasmic'
|
||||
description: 'Get started with Supabase and Plasmic, an open-source framework for building internal tools.'
|
||||
---
|
||||
id: 'plasmic',
|
||||
title: 'Plasmic',
|
||||
description:
|
||||
'Get started with Supabase and Plasmic, an open-source framework for building internal tools.',
|
||||
}
|
||||
|
||||
In this guide, we will show you how to build a crowd-sourced Pokemon Pokedex, by connecting **Supabase**, an open source Firebase backend alternative, with **Plasmic**, a visual builder for the web. While many users leverage Plasmic to quickly launch and iterate on landing pages, in this tutorial we’ll show just how powerful Plasmic can be as a general-purpose visual builder for React, which can be used to design and implement fully featured read-write applications.
|
||||
|
||||
@@ -312,3 +313,7 @@ export function SupabaseTextField({ name, className }: { name?: string; classNam
|
||||
```
|
||||
|
||||
In summary, by populating state into React contexts, we can store and retrieve data for use in other code components, which can be used for arbitrarily powerful interactions in Plasmic Studio.
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: polyscale
|
||||
title: 'PolyScale'
|
||||
description: 'The easiest way to get low-latency reads from your Supabase database for multi-region applications is by using PolyScale, a code-free global caching service.'
|
||||
---
|
||||
id: 'polyscale',
|
||||
title: 'PolyScale',
|
||||
description:
|
||||
'The easiest way to get low-latency reads from your Supabase database for multi-region applications is by using PolyScale, a code-free global caching service.',
|
||||
}
|
||||
|
||||
[PolyScale](https://polyscale.ai) is an intelligent, serverless database caching engine which allows low-latency reads from Supabase globally, no coding required. Supabase can be connected to PolyScale in minutes, providing you fast access to your Supabase data around the globe.
|
||||
|
||||
@@ -63,3 +64,7 @@ That's it.
|
||||
## All done!
|
||||
|
||||
You can read more about PolyScale [here](https://www.polyscale.ai/) or check out our [documentation](https://docs.polyscale.ai/).
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,10 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: prisma
|
||||
title: 'Prisma'
|
||||
description: 'Connect your Supabase postgres database to your Prisma project.'
|
||||
---
|
||||
id: 'prisma',
|
||||
title: 'Prisma',
|
||||
description: 'Connect your Supabase postgres database to your Prisma project.',
|
||||
}
|
||||
|
||||
This guide explains how to quickly connect the Postgres database provided by Supabase to a Prisma project.
|
||||
|
||||
@@ -162,3 +162,7 @@ alter default privileges in schema public grant all on sequences to postgres, an
|
||||
- [Prisma](https://prisma.io) official website.
|
||||
- [Prisma GitHub](https://github.com/prisma/prisma).
|
||||
- [Prisma](https://www.prisma.io/docs/) documentation.
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: sequin
|
||||
title: 'Sequin'
|
||||
description: 'Sync platforms like Stripe and Salesforce with your Supabase database in real-time using Sequin.'
|
||||
---
|
||||
id: 'sequin',
|
||||
title: 'Sequin',
|
||||
description:
|
||||
'Sync platforms like Stripe and Salesforce with your Supabase database in real-time using Sequin.',
|
||||
}
|
||||
|
||||
This guide explains how to quickly setup a sync between Sequin and a Supabase Postgres database.
|
||||
|
||||
@@ -84,3 +85,7 @@ You'll use this client to query for data in your synced schema.
|
||||
- [Sequin Console](https://app.sequin.io*).
|
||||
- [Sequin](https://docs.sequin.io/welcome) documentation.
|
||||
- [Sequin + Supabase + Stripe Tutorial](https://github.com/sequin-io/build-a-saas-with-next-js-supabase-stripe-and-sequin)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: snaplet
|
||||
title: 'Snaplet'
|
||||
description: 'Get started with Supabase and Snaplet, a developer tool for working with safe, versioned, up-to-date production-like data'
|
||||
---
|
||||
id: 'snaplet',
|
||||
title: 'Snaplet',
|
||||
description:
|
||||
'Get started with Supabase and Snaplet, a developer tool for working with safe, versioned, up-to-date production-like data',
|
||||
}
|
||||
|
||||
This step-by-step guide explains how to use Snaplet to clone your production Supabase project into another development database.
|
||||
|
||||
@@ -116,3 +117,7 @@ Once completed, you will be presented with a list of databases that are connecte
|
||||
As a Supabase user, you can see how this solves an issue developers all typically experience when attempting to create multiple development environments and populating each of those environments with data that can be worked with. Snaplet simplifies this process down to creating the respective Supabase projects, connecting the data source (The production database) to Snaplet and telling Snaplet where to restore that data (staging and development databases).
|
||||
|
||||
If you want to learn more about Snaplet, you can explore the Snaplet [docs](https://docs.snaplet.dev/). If you have any questions, feel free to [reach out on Discord](https://discord.com/invite/6HUuajc866).
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: stytch
|
||||
title: 'Stytch'
|
||||
description: "Build a Next.js application powered by password-less authentication from Stytch, and Supabase's Row Level Security (RLS)."
|
||||
---
|
||||
id: 'stytch',
|
||||
title: 'Stytch',
|
||||
description:
|
||||
"Build a Next.js application powered by password-less authentication from Stytch, and Supabase's Row Level Security (RLS).",
|
||||
}
|
||||
|
||||
In this guide we will build a simple expense tracker web application using Stytch, Supabase, and Next.js.
|
||||
|
||||
@@ -656,3 +657,7 @@ With these two changes you will now have a working Google One Tap authentication
|
||||
|
||||
- [Stytch blog](https://stytch.com/blog?utm_source=supabase&utm_medium=guide)
|
||||
- [Stytch documentation](https://stytch.com/docs?utm_source=supabase&utm_medium=guide)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: supertokens
|
||||
title: 'SuperTokens'
|
||||
description: 'Create a Next.js application secured by SuperTokens and PostgreSQL Row Level Security.'
|
||||
---
|
||||
id: 'supertokens',
|
||||
title: 'SuperTokens',
|
||||
description:
|
||||
'Create a Next.js application secured by SuperTokens and PostgreSQL Row Level Security.',
|
||||
}
|
||||
|
||||
[SuperTokens](https://www.supertokens.com) is an open source authentication solution which provides many stratergies for authenticating and managing users. You can use the managed service for easy setup or you can self host the solution to have complete control over your data.
|
||||
|
||||
@@ -399,3 +400,7 @@ If you navigate to your table you should see a new row with the user's `user_id`
|
||||
- [SuperTokens](https://supertokens.com/) official website.
|
||||
- [SuperTokens community](https://supertokens.com/discord).
|
||||
- [SuperTokens documentation](https://supertokens.com/docs/guides).
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: vercel
|
||||
title: 'Vercel'
|
||||
description: The fastest way to get up and running with an application that uses Supabase is with Vercel's Next.js starter and Supabase integration.
|
||||
---
|
||||
id: 'vercel',
|
||||
title: 'Vercel',
|
||||
description:
|
||||
"The fastest way to get up and running with an application that uses Supabase is with Vercel's Next.js starter and Supabase integration.",
|
||||
}
|
||||
|
||||
This guide steps through using Vercel's dashboard to create a Next.js project integrated with Supabase. To further streamline the process, we will be using the Next.js starter template, which can be automatically forked to a new GitHub repo, without leaving the dashboard!
|
||||
|
||||
@@ -241,3 +242,7 @@ export default function Home() {
|
||||
- [Vercel blog](https://vercel.com/blog).
|
||||
- [Vercel docs](https://vercel.com/docs).
|
||||
- [Vercel Integration docs](https://vercel.com/docs/integrations)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: firebase-auth
|
||||
title: 'Firebase Auth Migration'
|
||||
description: 'Migrate Firebase auth users to a Supabase project.'
|
||||
sidebar_label: Firebase Auth
|
||||
---
|
||||
id: 'firebase-auth',
|
||||
title: 'Firebase Auth Migration',
|
||||
description: 'Migrate Firebase auth users to a Supabase project.',
|
||||
sidebar_label: 'Firebase Auth',
|
||||
}
|
||||
|
||||
Supabase provides several [tools](https://github.com/supabase-community/firebase-to-supabase/tree/main/auth) to help migrate auth users from a Firebase project to a Supabase project. There are two parts to the migration process:
|
||||
|
||||
@@ -87,3 +87,7 @@ For more advanced migrations, including the use of a middleware server component
|
||||
- [Supabase vs Firebase](https://supabase.com/alternatives/supabase-vs-firebase)
|
||||
- [Firestore Data Migration](/docs/guides/migrations/firestore-data)
|
||||
- [Firestore Storage Migration](/docs/guides/migrations/firebase-storage)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: firebase-storage
|
||||
title: 'Firebase Storage Migration'
|
||||
description: 'Migrate Firebase Storage files to Supabase Storage.'
|
||||
sidebar_label: Firebase Storage
|
||||
---
|
||||
id: 'firebase-storage',
|
||||
title: 'Firebase Storage Migration',
|
||||
description: 'Migrate Firebase Storage files to Supabase Storage.',
|
||||
sidebar_label: 'Firebase Storage',
|
||||
}
|
||||
|
||||
Supabase provides several [tools](https://github.com/supabase-community/firebase-to-supabase/tree/main/storage) to convert storage files from Firebase Storage to Supabase Storage. Conversion is a two-step process:
|
||||
|
||||
@@ -66,3 +66,7 @@ If the bucket doesn't exist, it's created as a `non-public` bucket. You must set
|
||||
- [Supabase vs Firebase](https://supabase.com/alternatives/supabase-vs-firebase)
|
||||
- [Firestore Data Migration](/docs/guides/migrations/firestore-data)
|
||||
- [Firebase Auth Migration](/docs/guides/migrations/firebase-auth)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: firestore-data
|
||||
title: 'Firestore Data Migration'
|
||||
description: 'Migrate your Firebase Firestore database to a Supabase Postgres database.'
|
||||
sidebar_label: Firestore Data
|
||||
---
|
||||
id: 'firestore-data',
|
||||
title: 'Firestore Data Migration',
|
||||
description: 'Migrate your Firebase Firestore database to a Supabase Postgres database.',
|
||||
sidebar_label: 'Firestore Data',
|
||||
}
|
||||
|
||||
Supabase provides several [tools](https://github.com/supabase-community/firebase-to-supabase/tree/main/firestore) to convert data from a Firebase Firestore database to a Supabase PostgreSQL database. The process copies the entire contents of a single Firestore `collection` to a single PostgreSQL `table`.
|
||||
|
||||
@@ -210,3 +210,7 @@ The result is two separate JSON files:
|
||||
- [Supabase vs Firebase](https://supabase.com/alternatives/supabase-vs-firebase)
|
||||
- [Firestore Storage Migration](/docs/guides/migrations/firebase-storage)
|
||||
- [Firebase Auth Migration](/docs/guides/migrations/firebase-auth)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: heroku
|
||||
title: 'Migrate from Heroku to Supabase'
|
||||
description: 'Migrate your Heroku Postgres database to Supabase.'
|
||||
sidebar_label: Heroku
|
||||
---
|
||||
id: 'heroku',
|
||||
title: 'Migrate from Heroku to Supabase',
|
||||
description: 'Migrate your Heroku Postgres database to Supabase.',
|
||||
sidebar_label: 'Heroku',
|
||||
}
|
||||
|
||||
Supabase is one of the best [free alternatives to Heroku Postgres](https://supabase.com/alternatives/supabase-vs-heroku-postgres). This guide shows how to migrate your Heroku Postgres database to Supabase. This migration requires the [pg_dump](https://www.postgresql.org/docs/current/app-pgdump.html) and [psql](https://www.postgresql.org/docs/current/app-psql.html) CLI tools, which are installed automatically as part of the complete PostgreSQL installation package.
|
||||
|
||||
@@ -65,3 +65,7 @@ psql -h $SUPABASE_HOST -U postgres -f heroku_dump.sql
|
||||
- To exclude a table: `--exclude-table=PATTERN`.
|
||||
|
||||
Run `pg_dump --help` for a full list of options.
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -7,9 +7,6 @@ export const meta = {
|
||||
sidebar_label: 'Angular',
|
||||
}
|
||||
|
||||
import QuickstartIntro from '/components/MDX/quickstart_intro.mdx'
|
||||
import ProjectSetup from '/components/MDX/project_setup.mdx'
|
||||
|
||||
<QuickstartIntro />
|
||||
|
||||

|
||||
|
||||
@@ -7,9 +7,6 @@ export const meta = {
|
||||
sidebar_label: 'Ionic Vue',
|
||||
}
|
||||
|
||||
import QuickstartIntro from '/components/MDX/quickstart_intro.mdx'
|
||||
import ProjectSetup from '/components/MDX/project_setup.mdx'
|
||||
|
||||
<QuickstartIntro />
|
||||
|
||||

|
||||
|
||||
@@ -7,9 +7,6 @@ export const meta = {
|
||||
sidebar_label: 'Next.js',
|
||||
}
|
||||
|
||||
import QuickstartIntro from '/components/MDX/quickstart_intro.mdx'
|
||||
import ProjectSetup from '/components/MDX/project_setup.mdx'
|
||||
|
||||
<QuickstartIntro />
|
||||
|
||||

|
||||
|
||||
@@ -7,9 +7,6 @@ export const meta = {
|
||||
sidebar_label: 'Nuxt 3',
|
||||
}
|
||||
|
||||
import QuickstartIntro from '/components/MDX/quickstart_intro.mdx'
|
||||
import ProjectSetup from '/components/MDX/project_setup.mdx'
|
||||
|
||||
<QuickstartIntro />
|
||||
|
||||

|
||||
|
||||
@@ -7,9 +7,6 @@ export const meta = {
|
||||
sidebar_label: 'React',
|
||||
}
|
||||
|
||||
import QuickstartIntro from '/components/MDX/quickstart_intro.mdx'
|
||||
import ProjectSetup from '/components/MDX/project_setup.mdx'
|
||||
|
||||
<QuickstartIntro />
|
||||
|
||||

|
||||
|
||||
@@ -7,9 +7,6 @@ export const meta = {
|
||||
sidebar_label: 'SolidJS',
|
||||
}
|
||||
|
||||
import QuickstartIntro from '/components/MDX/quickstart_intro.mdx'
|
||||
import ProjectSetup from '/components/MDX/project_setup.mdx'
|
||||
|
||||
<QuickstartIntro />
|
||||
|
||||

|
||||
|
||||
@@ -7,9 +7,6 @@ export const meta = {
|
||||
sidebar_label: 'Svelte',
|
||||
}
|
||||
|
||||
import QuickstartIntro from '/components/MDX/quickstart_intro.mdx'
|
||||
import ProjectSetup from '/components/MDX/project_setup.mdx'
|
||||
|
||||
<QuickstartIntro />
|
||||
|
||||

|
||||
|
||||
@@ -7,9 +7,6 @@ export const meta = {
|
||||
sidebar_label: 'SvelteKit',
|
||||
}
|
||||
|
||||
import QuickstartIntro from '/components/MDX/quickstart_intro.mdx'
|
||||
import ProjectSetup from '/components/MDX/project_setup.mdx'
|
||||
|
||||
<QuickstartIntro />
|
||||
|
||||

|
||||
|
||||
@@ -7,9 +7,6 @@ export const meta = {
|
||||
sidebar_label: 'Vue 3',
|
||||
}
|
||||
|
||||
import QuickstartIntro from '/components/MDX/quickstart_intro.mdx'
|
||||
import ProjectSetup from '/components/MDX/project_setup.mdx'
|
||||
|
||||
<QuickstartIntro />
|
||||
|
||||

|
||||
|
||||
@@ -22,7 +22,7 @@ export default function Home({
|
||||
)
|
||||
}
|
||||
export async function getStaticProps() {
|
||||
const doc = getDocsBySlug('docs/introduction')
|
||||
const doc = getDocsBySlug('pages/introduction')
|
||||
const content = await serialize(doc.content || '')
|
||||
return {
|
||||
props: {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: reference
|
||||
title: Reference Documentation
|
||||
sidebar_label: Reference Documentation
|
||||
hide_table_of_contents: true
|
||||
---
|
||||
id: 'reference',
|
||||
title: 'Reference Documentation',
|
||||
sidebar_label: 'Reference Documentation',
|
||||
hide_table_of_contents: true,
|
||||
}
|
||||
|
||||
Reference documentation for the official Supabase client libraries, APIs, and tools.
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: support
|
||||
title: Support
|
||||
description: Supabase Support
|
||||
---
|
||||
id: 'support',
|
||||
title: 'Support',
|
||||
description: 'Supabase Support',
|
||||
}
|
||||
|
||||
How can we help?
|
||||
|
||||
|
||||
Reference in new issue
Block a user