diff --git a/.github/workflows/autofix_linters.yml b/.github/workflows/autofix_linters.yml
new file mode 100644
index 00000000000..ca8882d7e04
--- /dev/null
+++ b/.github/workflows/autofix_linters.yml
@@ -0,0 +1,58 @@
+name: Autofix Linting Checks
+
+on:
+ pull_request:
+ types:
+ - labeled
+
+# Cancel old builds on new commit for same workflow + branch/PR
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ autofix:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ if: ${{ github.event_name == 'pull_request' && (github.event.label.name == 'autofix') }}
+ steps:
+ - name: Calculate number of commits
+ run: echo "PR_FETCH_DEPTH=$(( ${{ github.event.pull_request.commits }} + 1 ))" >> "${GITHUB_ENV}"
+
+ - uses: actions/checkout@v4
+ with:
+ ref: ${{ github.head_ref }}
+ sparse-checkout: apps
+ fetch-depth: ${{ env.PR_FETCH_DEPTH }}
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version-file: '.nvmrc'
+
+ # Installing all dependencies takes up to three minutes, hacking around to only installing prettier+deps
+ - name: Install required dependencies
+ run: |
+ rm package.json
+ rm package-lock.json
+ npm i prettier@4.0.0-alpha.8 prettier-plugin-sql-cst
+
+ - name: Run Prettier in fix mode
+ run: |
+ npx prettier --write 'apps/**/*.{js,jsx,ts,tsx,css,md,mdx,json}'
+
+ - name: Commit changes and push to existing branch
+ run: |
+ git checkout -- package.json
+ git checkout -- package-lock.json
+ git config --global user.name 'github-tidy-bot'
+ git config --global user.email 'github-tidy-bot@supabase.com'
+ if [[ `git status --porcelain` ]]; then
+ echo "[bot] Changes detected, committing."
+
+ echo "[bot] Running in non-squash mode."
+ git commit -am "ci: Autofix updates from GitHub workflow"
+ git push
+ else
+ echo "[bot] No changes detected, nothing to commit."
+ fi
diff --git a/.github/workflows/prettier.yml b/.github/workflows/prettier.yml
index 379248ed601..886a2d41b40 100644
--- a/.github/workflows/prettier.yml
+++ b/.github/workflows/prettier.yml
@@ -27,7 +27,7 @@ jobs:
run: |
rm package.json
rm package-lock.json
- npm i prettier@2 prettier-plugin-sql-cst
+ npm i prettier@4.0.0-alpha.8 prettier-plugin-sql-cst
- name: Run prettier
run: |-
npx prettier -c 'apps/**/*.{js,jsx,ts,tsx,css,md,mdx,json}'
@@ -50,7 +50,7 @@ jobs:
run: |
rm package.json
rm package-lock.json
- npm i prettier@2 prettier-plugin-sql-cst
+ npm i prettier@4.0.0-alpha.8 prettier-plugin-sql-cst
- name: Run prettier
run: |-
npx prettier -c 'i18n/**/*.{js,jsx,ts,tsx,css,md,mdx,json}'
@@ -63,13 +63,14 @@ jobs:
with:
sparse-checkout: |
apps/docs/pages
+ apps/docs/content
# Installing all dependencies takes up to three minutes, hacking around to only installing prettier+deps
- name: Download dependencies
run: |
rm package.json
rm package-lock.json
- npm i prettier@2 prettier-plugin-sql-cst
+ npm i prettier@4.0.0-alpha.8 prettier-plugin-sql-cst
- name: Run prettier
run: |-
# Check mdx files which contain sql code blocks
- grep -lr '```sql' apps/docs/pages/**/*.mdx | xargs npx prettier -c
+ grep -lr '```sql' apps/docs/{pages,content}/**/*.mdx | xargs npx prettier -c
diff --git a/.github/workflows/search.yml b/.github/workflows/search.yml
index 2fc6b8cd510..b1dd9b1d57a 100644
--- a/.github/workflows/search.yml
+++ b/.github/workflows/search.yml
@@ -38,6 +38,7 @@ jobs:
with:
sparse-checkout: |
apps/docs
+ apps/www/.env.local.example
supabase
- name: Setup node
@@ -54,6 +55,10 @@ jobs:
- name: Run migrations
run: npx supabase db push
+ # Need the miscellaneous use API, which is available publicly (by design) in www
+ - name: Copy environment variables
+ run: cp apps/www/.env.local.example apps/docs/.env
+
- name: Update embeddings
working-directory: ./apps/docs
if: ${{ !inputs.refresh }}
diff --git a/.prettierrc b/.prettierrc
index c60d3ab91ef..5609026b6f4 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -7,5 +7,11 @@
"endOfLine": "lf",
"sqlKeywordCase": "lower",
"pluginSearchDirs": false,
- "plugins": ["prettier-plugin-sql-cst"]
+ "plugins": ["prettier-plugin-sql-cst"],
+ "overrides": [
+ {
+ "files": "**/*.json",
+ "options": { "parser": "json" }
+ }
+ ]
}
diff --git a/README.md b/README.md
index 069f098bdde..a3cd29f08a3 100644
--- a/README.md
+++ b/README.md
@@ -39,7 +39,6 @@ To see how to Contribute, visit [Getting Started](./DEVELOPERS.md)
- [Email Support](https://supabase.com/docs/support#business-support). Best for: problems with your database or infrastructure.
- [Discord](https://discord.supabase.com). Best for: sharing your applications and hanging out with the community.
-
## How it works
Supabase is a combination of open source tools. We’re building the features of Firebase using enterprise-grade, open source products. If the tools and communities exist, with an MIT, Apache 2, or equivalent open license, we will use and support that tool. If the tool doesn't exist, we build and open source it ourselves. Supabase is not a 1-to-1 mapping of Firebase. Our aim is to give developers a Firebase-like developer experience using open source tools.
@@ -49,7 +48,7 @@ Supabase is a combination of open source tools. We’re building the features of
Supabase is a [hosted platform](https://supabase.com/dashboard). You can sign up and start using Supabase without installing anything.
You can also [self-host](https://supabase.com/docs/guides/hosting/overview) and [develop locally](https://supabase.com/docs/guides/local-development).
-
+
- [Postgres](https://www.postgresql.org/) is an object-relational database system with over 30 years of active development that has earned it a strong reputation for reliability, feature robustness, and performance.
- [Realtime](https://github.com/supabase/realtime) is an Elixir server that allows you to listen to PostgreSQL inserts, updates, and deletes using websockets. Realtime polls Postgres' built-in replication functionality for database changes, converts changes to JSON, then broadcasts the JSON over websockets to authorized clients.
diff --git a/apps/database-new/app/[threadId]/[runId]/UserChat.tsx b/apps/database-new/app/[threadId]/[runId]/UserChat.tsx
index 8abc0683a6e..f1457b55ff6 100644
--- a/apps/database-new/app/[threadId]/[runId]/UserChat.tsx
+++ b/apps/database-new/app/[threadId]/[runId]/UserChat.tsx
@@ -138,8 +138,8 @@ const UserChat = ({ message, isLatest, times, run }: UserChatProps) => {
{replyDuration !== undefined
? ` with ${replyDuration}s response`
: isLoading
- ? ', generating response...'
- : ''}
+ ? ', generating response...'
+ : ''}
diff --git a/apps/docs/components/Mermaid/Mermaid.tsx b/apps/docs/components/Mermaid/Mermaid.tsx
new file mode 100644
index 00000000000..e2607613ccf
--- /dev/null
+++ b/apps/docs/components/Mermaid/Mermaid.tsx
@@ -0,0 +1,2 @@
+import { Mermaid } from 'mdx-mermaid/lib/Mermaid'
+export default Mermaid
diff --git a/apps/docs/components/Mermaid/index.tsx b/apps/docs/components/Mermaid/index.tsx
new file mode 100644
index 00000000000..b73a5d8033d
--- /dev/null
+++ b/apps/docs/components/Mermaid/index.tsx
@@ -0,0 +1,11 @@
+import { Suspense, lazy } from 'react'
+
+const MermaidHeavy = lazy(() => import('./Mermaid'))
+
+export function Mermaid(props) {
+ return (
+
+
+
+ )
+}
diff --git a/apps/docs/components/NavData.tsx b/apps/docs/components/NavData.tsx
new file mode 100644
index 00000000000..8fb29b5fa23
--- /dev/null
+++ b/apps/docs/components/NavData.tsx
@@ -0,0 +1,14 @@
+import { ReactNode } from 'react'
+
+import { navDataForMdx } from './Navigation/NavigationMenu/NavigationMenu.constants'
+
+export function NavData({
+ data,
+ children,
+}: {
+ data: keyof typeof navDataForMdx
+ children: (navItems: (typeof navDataForMdx)[keyof typeof navDataForMdx]) => ReactNode
+}) {
+ const navItems = navDataForMdx[data]
+ return children(navItems)
+}
diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts
index ec26db6379d..381cb046e77 100644
--- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts
+++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts
@@ -614,6 +614,10 @@ export const auth = {
url: undefined,
items: [
{ name: 'Overview', url: '/guides/auth/server-side/overview' },
+ {
+ name: 'Next.js guide',
+ url: '/guides/auth/server-side/nextjs',
+ },
{
name: 'Creating a client',
url: '/guides/auth/server-side/creating-a-client',
@@ -653,20 +657,20 @@ export const auth = {
items: [
{
name: 'Part One: JWTs',
- url: '/learn/auth-deep-dive/auth-deep-dive-jwts',
+ url: '/guides/auth/auth-deep-dive/auth-deep-dive-jwts',
},
{
name: 'Part Two: Row Level Security',
- url: '/learn/auth-deep-dive/auth-row-level-security',
+ url: '/guides/auth/auth-deep-dive/auth-row-level-security',
},
{
name: 'Part Three: Policies',
- url: '/learn/auth-deep-dive/auth-policies',
+ url: '/guides/auth/auth-deep-dive/auth-policies',
},
- { name: 'Part Four: GoTrue', url: '/learn/auth-deep-dive/auth-gotrue' },
+ { name: 'Part Four: GoTrue', url: '/guides/auth/auth-deep-dive/auth-gotrue' },
{
name: 'Part Five: Google OAuth',
- url: '/learn/auth-deep-dive/auth-google-oauth',
+ url: '/guides/auth/auth-deep-dive/auth-google-oauth',
},
],
},
@@ -751,6 +755,10 @@ export const database: NavMenuConstant = {
url: '/guides/database/postgres/roles',
},
{ name: 'Managing secrets with Vault', url: '/guides/database/vault' },
+ {
+ name: 'Superuser Access and Unsupported Operations',
+ url: '/guides/database/postgres/roles-superuser',
+ },
],
},
{
@@ -938,6 +946,10 @@ export const database: NavMenuConstant = {
name: 'Print PostgreSQL Version',
url: '/guides/database/postgres/which-version-of-postgres',
},
+ {
+ name: 'Replicating from Supabase to External Postgres',
+ url: '/guides/database/postgres/setup-replication-external',
+ },
],
},
],
@@ -1622,6 +1634,10 @@ export const platform: NavMenuConstant = {
name: 'Enterprise Billing',
url: '/guides/platform/enterprise-billing',
},
+ {
+ name: 'Billing FAQ',
+ url: '/guides/platform/billing-faq',
+ },
],
},
{
@@ -2110,3 +2126,9 @@ export const references = [
],
},
]
+
+export const navDataForMdx = {
+ nativeMobileLoginItems: NativeMobileLoginItems,
+ phoneLoginsItems: PhoneLoginsItems,
+ socialLoginItems: SocialLoginItems,
+}
diff --git a/apps/docs/components/Navigation/NavigationMenu/TopNavBar.tsx b/apps/docs/components/Navigation/NavigationMenu/TopNavBar.tsx
index c5727f3b2a6..5ac5557f0d9 100644
--- a/apps/docs/components/Navigation/NavigationMenu/TopNavBar.tsx
+++ b/apps/docs/components/Navigation/NavigationMenu/TopNavBar.tsx
@@ -4,8 +4,7 @@ import Link from 'next/link'
import { FC } from 'react'
import { Button, IconCommand, IconGitHub, IconSearch, SearchButton } from 'ui'
import { useIsLoggedIn, useIsUserLoading } from 'common'
-
-import ThemeToggle from '@ui/components/ThemeProvider/ThemeToggle'
+import { ThemeToggle } from 'ui-patterns/ThemeToggle'
const TopNavBar: FC = () => {
const isLoggedIn = useIsLoggedIn()
diff --git a/apps/docs/components/ProjectConfigVariables/ProjectConfigVariables.ComboBox.tsx b/apps/docs/components/ProjectConfigVariables/ProjectConfigVariables.ComboBox.tsx
index fa68260238a..5f2047470bd 100644
--- a/apps/docs/components/ProjectConfigVariables/ProjectConfigVariables.ComboBox.tsx
+++ b/apps/docs/components/ProjectConfigVariables/ProjectConfigVariables.ComboBox.tsx
@@ -64,8 +64,8 @@ export function ComboBox({
{isLoading
? 'Loading...'
: options.length === 0
- ? `No ${name} found`
- : selectedOptionDisplayName ?? `Select a ${name}...`}
+ ? `No ${name} found`
+ : selectedOptionDisplayName ?? `Select a ${name}...`}
diff --git a/apps/docs/components/ProjectConfigVariables/ProjectConfigVariables.tsx b/apps/docs/components/ProjectConfigVariables/ProjectConfigVariables.tsx
index dfe36c3b34d..b316a6cdbb8 100644
--- a/apps/docs/components/ProjectConfigVariables/ProjectConfigVariables.tsx
+++ b/apps/docs/components/ProjectConfigVariables/ProjectConfigVariables.tsx
@@ -98,14 +98,14 @@ function OrgProjectSelector() {
const stateSummary: ProjectOrgDataState = isUserLoading
? 'userLoading'
: !isLoggedIn
- ? 'loggedOut'
- : anyIsPending
- ? 'loggedIn.dataPending'
- : anyIsError
- ? 'loggedIn.dataError'
- : projects?.length === 0
- ? 'loggedIn.dataSuccess.hasNoData'
- : 'loggedIn.dataSuccess.hasData'
+ ? 'loggedOut'
+ : anyIsPending
+ ? 'loggedIn.dataPending'
+ : anyIsError
+ ? 'loggedIn.dataError'
+ : projects?.length === 0
+ ? 'loggedIn.dataSuccess.hasNoData'
+ : 'loggedIn.dataSuccess.hasData'
const formattedData: ComboBoxOption[] = useMemo(
() =>
@@ -194,16 +194,16 @@ function BranchSelector() {
const stateSummary: BranchesDataState = userLoading
? 'userLoading'
: !isLoggedIn
- ? 'loggedOut'
- : !hasBranches
- ? 'loggedIn.noBranches'
- : isPending
- ? 'loggedIn.branches.dataPending'
- : isError
- ? 'loggedIn.branches.dataError'
- : data.length === 0
- ? 'loggedIn.branches.dataSuccess.noData'
- : 'loggedIn.branches.dataSuccess.hasData'
+ ? 'loggedOut'
+ : !hasBranches
+ ? 'loggedIn.noBranches'
+ : isPending
+ ? 'loggedIn.branches.dataPending'
+ : isError
+ ? 'loggedIn.branches.dataError'
+ : data.length === 0
+ ? 'loggedIn.branches.dataSuccess.noData'
+ : 'loggedIn.branches.dataSuccess.hasData'
const formattedData: ComboBoxOption[] =
stateSummary !== 'loggedIn.branches.dataSuccess.hasData'
@@ -282,14 +282,14 @@ function VariableView({ variable, className }: { variable: Variable; className?:
const stateSummary: VariableDataState = isUserLoading
? 'userLoading'
: !isLoggedIn
- ? 'loggedOut'
- : !ref
- ? 'loggedIn.noSelectedProject'
- : isPending
- ? 'loggedIn.selectedProject.dataPending'
- : isError
- ? 'loggedIn.selectedProject.dataError'
- : 'loggedIn.selectedProject.dataSuccess'
+ ? 'loggedOut'
+ : !ref
+ ? 'loggedIn.noSelectedProject'
+ : isPending
+ ? 'loggedIn.selectedProject.dataPending'
+ : isError
+ ? 'loggedIn.selectedProject.dataError'
+ : 'loggedIn.selectedProject.dataSuccess'
let variableValue: string = null
if (stateSummary === 'loggedIn.selectedProject.dataSuccess') {
@@ -319,8 +319,8 @@ function VariableView({ variable, className }: { variable: Variable; className?:
stateSummary === 'loggedIn.selectedProject.dataPending'
? 'Loading...'
: stateSummary === 'loggedIn.selectedProject.dataSuccess'
- ? variableValue
- : `YOUR ${prettyFormatVariable[variable].toUpperCase()}`
+ ? variableValue
+ : `YOUR ${prettyFormatVariable[variable].toUpperCase()}`
}
/>
diff --git a/apps/docs/components/ProjectConfigVariables/ProjectConfigVariables.utils.ts b/apps/docs/components/ProjectConfigVariables/ProjectConfigVariables.utils.ts
index a0659cf8aca..519c40c25e0 100644
--- a/apps/docs/components/ProjectConfigVariables/ProjectConfigVariables.utils.ts
+++ b/apps/docs/components/ProjectConfigVariables/ProjectConfigVariables.utils.ts
@@ -8,6 +8,26 @@ export type Branch = BranchesData[number]
export type Variable = 'url' | 'anonKey'
+function removeDoubleQuotes(str: string) {
+ return str.replaceAll('"', '')
+}
+
+function escapeDoubleQuotes(str: string) {
+ return str.replaceAll('"', '\\"')
+}
+
+function unescapeDoubleQuotes(str: string) {
+ /**
+ * Regex matches a backslash followed by a double quote, except when the
+ * backslash is escaped.
+ *
+ * Negative lookbehind:
+ * \\(?:\\\\)* -> An odd number of backslashes (means the next backslash is escaped)
+ * (?:^|[^\\]) -> Backslash group is at start or follows non-backslash
+ */
+ return str.replace(/(? = {
url: 'Project URL',
anonKey: 'Anon key',
@@ -18,15 +38,19 @@ export function toDisplayNameOrgProject(org: Org, project: Project) {
}
export function toOrgProjectValue(org: Org, project: Project) {
- // @ts-ignore -- problem in OpenAPI spec -- project has ref property
- return JSON.stringify([org.id, project.ref, toDisplayNameOrgProject(org, project)])
+ return escapeDoubleQuotes(
+ // @ts-ignore -- problem in OpenAPI spec -- project has ref property
+ JSON.stringify([org.id, project.ref, removeDoubleQuotes(toDisplayNameOrgProject(org, project))])
+ )
}
export function fromOrgProjectValue(
maybeOrgProject: string
): [string, string, string] | [null, null, null] {
try {
- const data = JSON.parse(maybeOrgProject)
+ // not restoring the double quotes on the display name is fine because it's only used for
+ // command fuzzy search, not for exact/literal matching
+ const data = JSON.parse(unescapeDoubleQuotes(maybeOrgProject))
if (!Array.isArray(data) || data.length !== 3) {
throw Error("Shape of parsed JSON doesn't match form of org and project value")
}
@@ -37,12 +61,14 @@ export function fromOrgProjectValue(
}
export function toBranchValue(branch: Branch) {
- return JSON.stringify([branch.id, branch.name])
+ return escapeDoubleQuotes(JSON.stringify([branch.id, removeDoubleQuotes(branch.name)]))
}
export function fromBranchValue(maybeBranch: string): [string, string] | [null, null] {
try {
- const data = JSON.parse(maybeBranch)
+ // not restoring the double quotes on the branch name is fine because it's only used for
+ // command fuzzy search, not for exact/literal matching
+ const data = JSON.parse(unescapeDoubleQuotes(maybeBranch))
if (!Array.isArray(data) || data.length !== 2) {
throw Error("Shape of parsed JSON doesn't match form of branch value")
}
diff --git a/apps/docs/components/RealtimeLimitsEstimater.tsx b/apps/docs/components/RealtimeLimitsEstimator/RealtimeLimitsEstimator.tsx
similarity index 98%
rename from apps/docs/components/RealtimeLimitsEstimater.tsx
rename to apps/docs/components/RealtimeLimitsEstimator/RealtimeLimitsEstimator.tsx
index d8e153c2d3b..822c95f5a83 100644
--- a/apps/docs/components/RealtimeLimitsEstimater.tsx
+++ b/apps/docs/components/RealtimeLimitsEstimator/RealtimeLimitsEstimator.tsx
@@ -158,8 +158,8 @@ export default function RealtimeLimitsEstimater({}) {
{computeAddOn === 'micro'
? 'Micro'
: computeAddOn === 'small'
- ? 'Small to medium'
- : 'Large to 16XL'}
+ ? 'Small to medium'
+ : 'Large to 16XL'}
diff --git a/apps/docs/components/RealtimeLimitsEstimator/index.tsx b/apps/docs/components/RealtimeLimitsEstimator/index.tsx
new file mode 100644
index 00000000000..34fe3d20a42
--- /dev/null
+++ b/apps/docs/components/RealtimeLimitsEstimator/index.tsx
@@ -0,0 +1,11 @@
+import { lazy, Suspense } from 'react'
+
+const Estimator = lazy(() => import('./RealtimeLimitsEstimator'))
+
+export function RealtimeLimitsEstimator() {
+ return (
+
+
+
+ )
+}
diff --git a/apps/docs/components/index.tsx b/apps/docs/components/index.tsx
index bddb5268caf..a36aea45605 100644
--- a/apps/docs/components/index.tsx
+++ b/apps/docs/components/index.tsx
@@ -1,80 +1,94 @@
+/**
+ * This entire file could do with a cleanup and better code-splitting, but one thing at a time.
+ */
+
+// Basic UI things
import Link from 'next/link'
-import { Alert, Button, CodeBlock, GlassPanel, markdownComponents, Tabs } from 'ui'
-import StepHikeCompact from '~/components/StepHikeCompact'
+import { Accordion, Admonition, Alert, Button, CodeBlock, markdownComponents, Tabs } from 'ui'
+import { GlassPanel } from 'ui-patterns/GlassPanel'
+import { IconPanel } from 'ui-patterns/IconPanel'
+import { ThemeImage } from 'ui-patterns/ThemeImage'
+
// Common components
+import { CH } from '@code-hike/mdx/components'
+import StepHikeCompact from '~/components/StepHikeCompact'
import ButtonCard from './ButtonCard'
+import { Heading } from './CustomHTMLElements'
+
+// Reference guide specific
+// [Charis] I think we can factor these out so they aren't in the bundle for absolutely everything
+import CliGlobalFlagsHandler from '~/components/reference/enrichments/cli/CliGlobalFlagsHandler'
+import RefSubLayout from '~/layouts/ref/RefSubLayout'
+import RefHeaderSection from './reference/RefHeaderSection'
// Other components
-import RefSubLayout from '~/layouts/ref/RefSubLayout'
-import { Heading } from './CustomHTMLElements'
+import AuthProviders from '~/components/AuthProviders'
+import Options from '~/components/Options'
+import Param from '~/components/Params'
+import { ProjectConfigVariables } from './ProjectConfigVariables'
+
+// Data wrappers
+import { NavData } from './NavData'
+
+// Partials
import DatabaseSetup from './MDX/database_setup.mdx'
+import GetSessionWarning from './MDX/get_session_warning.mdx'
+import HuggingFaceDeployment from './MDX/ai/quickstart_hf_deployment.mdx'
+import MigrationWarnings from './MDX/migration_warnings.mdx'
import ProjectSetup from './MDX/project_setup.mdx'
import QuickstartIntro from './MDX/quickstart_intro.mdx'
import SocialProviderSettingsSupabase from './MDX/social_provider_settings_supabase.mdx'
import SocialProviderSetup from './MDX/social_provider_setup.mdx'
import StorageManagement from './MDX/storage_management.mdx'
-import MigrationWarnings from './MDX/migration_warnings.mdx'
-import GetSessionWarning from './MDX/get_session_warning.mdx'
-import { CH } from '@code-hike/mdx/components'
-import RefHeaderSection from './reference/RefHeaderSection'
-import { ProjectConfigVariables } from './ProjectConfigVariables'
-// Ref version specific
-import CliGlobalFlagsHandler from '~/components/reference/enrichments/cli/CliGlobalFlagsHandler'
-
-import Options from '~/components/Options'
-import Param from '~/components/Params'
-
-import { Admonition, ThemeImage } from 'ui'
+// Icons
import {
- IconMenuJavascript,
- IconMenuHome,
- IconMenuGettingStarted,
- IconMenuDatabase,
- IconMenuRestApis,
- IconMenuAuth,
- IconMenuEdgeFunctions,
- IconMenuRealtime,
- IconMenuStorage,
- IconMenuPlatform,
- IconMenuResources,
- IconMenuSelfHosting,
- IconMenuIntegrations,
- IconMenuFlutter,
- IconMenuPython,
- IconMenuCsharp,
- IconMenuSwift,
- IconMenuKotlin,
IconMenuApi,
+ IconMenuAuth,
IconMenuCli,
+ IconMenuCsharp,
+ IconMenuDatabase,
+ IconMenuEdgeFunctions,
+ IconMenuFlutter,
+ IconMenuGettingStarted,
+ IconMenuHome,
+ IconMenuIntegrations,
+ IconMenuJavascript,
+ IconMenuKotlin,
+ IconMenuPlatform,
+ IconMenuPython,
+ IconMenuRealtime,
+ IconMenuResources,
+ IconMenuRestApis,
+ IconMenuSelfHosting,
+ IconMenuStorage,
+ IconMenuSwift,
} from './Navigation/NavigationMenu/HomeMenuIcons'
+// Heavy/rare (lazy-loaded)
+import { AppleSecretGenerator } from './AppleSecretGenerator'
+import { Mermaid } from './Mermaid'
+import { RealtimeLimitsEstimator } from './RealtimeLimitsEstimator'
+
const components = {
...markdownComponents,
+ Accordion,
Admonition,
- Button,
- ButtonCard,
- CH,
- CodeBlock,
- GlassPanel,
- Link,
- QuickstartIntro,
- DatabaseSetup,
- ProjectSetup,
- MigrationWarnings,
- GetSessionWarning,
- SocialProviderSetup,
- SocialProviderSettingsSupabase,
- StepHikeCompact,
- ProjectConfigVariables,
- StorageManagement,
Alert: (props: any) => (
{props.children}
),
- Tabs: (props: any) => ,
- TabPanel: (props: any) => {props.children},
+ AppleSecretGenerator,
+ AuthProviders,
+ Button,
+ ButtonCard,
+ CH,
+ CliGlobalFlagsHandler: () => ,
+ CodeBlock,
+ DatabaseSetup,
+ GetSessionWarning,
+ GlassPanel,
h2: (props: any) => (
{props.children}
@@ -90,32 +104,47 @@ const components = {
{props.children}
),
+ HuggingFaceDeployment,
+ IconMenuApi,
+ IconMenuAuth,
+ IconMenuCli,
+ IconMenuCsharp,
+ IconMenuDatabase,
+ IconMenuEdgeFunctions,
+ IconMenuFlutter,
+ IconMenuGettingStarted,
+ IconMenuHome,
+ IconMenuIntegrations,
+ IconMenuJavascript,
+ IconMenuKotlin,
+ IconMenuPlatform,
+ IconMenuPython,
+ IconMenuRealtime,
+ IconMenuResources,
+ IconMenuRestApis,
+ IconMenuSelfHosting,
+ IconMenuStorage,
+ IconMenuSwift,
+ IconPanel,
Image: (props: any) => ,
- RefSubLayout,
- RefHeaderSection: (props: any) => ,
- CliGlobalFlagsHandler: () => ,
+ Link,
+ Mermaid,
+ MigrationWarnings,
+ NavData,
Options,
Param,
- IconMenuJavascript,
- IconMenuHome,
- IconMenuGettingStarted,
- IconMenuDatabase,
- IconMenuRestApis,
- IconMenuAuth,
- IconMenuEdgeFunctions,
- IconMenuRealtime,
- IconMenuStorage,
- IconMenuPlatform,
- IconMenuResources,
- IconMenuSelfHosting,
- IconMenuIntegrations,
- IconMenuFlutter,
- IconMenuPython,
- IconMenuCsharp,
- IconMenuKotlin,
- IconMenuSwift,
- IconMenuApi,
- IconMenuCli,
+ ProjectConfigVariables,
+ ProjectSetup,
+ QuickstartIntro,
+ RealtimeLimitsEstimator,
+ RefHeaderSection: (props: any) => ,
+ RefSubLayout,
+ SocialProviderSettingsSupabase,
+ SocialProviderSetup,
+ StepHikeCompact,
+ StorageManagement,
+ TabPanel: (props: any) => {props.children},
+ Tabs: (props: any) => ,
}
export default components
diff --git a/apps/docs/components/reference/RefFunctionSection.tsx b/apps/docs/components/reference/RefFunctionSection.tsx
index 733e07030f0..19d14023f54 100644
--- a/apps/docs/components/reference/RefFunctionSection.tsx
+++ b/apps/docs/components/reference/RefFunctionSection.tsx
@@ -126,14 +126,14 @@ const RefFunctionSection: React.FC = (props) => {
const codeBlockLang = example?.code?.startsWith('```js')
? 'js'
: example?.code?.startsWith('```ts')
- ? 'ts'
- : example?.code?.startsWith('```dart')
- ? 'dart'
- : example?.code?.startsWith('```c#')
- ? 'csharp'
- : example?.code?.startsWith('```kotlin')
- ? 'kotlin'
- : 'js'
+ ? 'ts'
+ : example?.code?.startsWith('```dart')
+ ? 'dart'
+ : example?.code?.startsWith('```c#')
+ ? 'csharp'
+ : example?.code?.startsWith('```kotlin')
+ ? 'kotlin'
+ : 'js'
// `
// import { createClient } from '@supabase/supabase-js'
diff --git a/apps/docs/pages/guides/ai.mdx b/apps/docs/content/guides/ai.mdx
similarity index 73%
rename from apps/docs/pages/guides/ai.mdx
rename to apps/docs/content/guides/ai.mdx
index a1abf0d2ba8..66c7ffbedae 100644
--- a/apps/docs/pages/guides/ai.mdx
+++ b/apps/docs/content/guides/ai.mdx
@@ -1,12 +1,10 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'ai',
- title: 'AI & Vectors',
- description: 'The best vector database is the database you already have.',
- subtitle: 'The best vector database is the database you already have.',
- sidebar_label: 'Overview',
-}
+---
+id: 'ai'
+title: 'AI & Vectors'
+description: 'The best vector database is the database you already have.'
+subtitle: 'The best vector database is the database you already have.'
+hideToc: true
+---
Supabase provides an open source toolkit for developing AI applications using Postgres and pgvector. Use the Supabase client libraries to store, index, and query your vector embeddings at scale.
@@ -109,7 +107,26 @@ export const integrations = [
## Case studies
- {customers.map((x) => (
+ {[
+ {
+ name: 'Berri AI Boosts Productivity by Migrating from AWS RDS to Supabase with pgvector',
+ description:
+ 'Learn how Berri AI overcame challenges with self-hosting their vector database on AWS RDS and successfully migrated to Supabase.',
+ href: 'https://supabase.com/customers/berriai',
+ },
+ {
+ name: 'Mendable switches from Pinecone to Supabase for PostgreSQL vector embeddings',
+ description:
+ 'How Mendable boosts efficiency and accuracy of chat powered search for documentation using Supabase with pgvector',
+ href: 'https://supabase.com/customers/mendableai',
+ },
+ {
+ name: 'Markprompt: GDPR-Compliant AI Chatbots for Docs and Websites',
+ description:
+ "AI-powered chatbot platform, Markprompt, empowers developers to deliver efficient and GDPR-compliant prompt experiences on top of their content, by leveraging Supabase's secure and privacy-focused database and authentication solutions",
+ href: 'https://supabase.com/customers/markprompt',
+ },
+ ].map((x) => (
+ ))}
- setFactorId(e.target.value.trim())}
- />
-
+ setFactorId(e.target.value.trim())} />
+
>
)
}
@@ -581,6 +570,10 @@ TOTP is not going to be the only MFA factor Supabase Auth is going to support in
The TOTP QR code encodes a URI with the `otpauth` scheme. It was [initially introduced by Google Authenticator](https://github.com/google/google-authenticator/wiki/Key-Uri-Format) but is now universally accepted by all authenticator apps.
+### How long is the TOTP code valid for?
+
+In our TOTP implementation, each generated code remains valid for one interval, which spans 30 seconds. To account for minor time discrepancies, we allow for a one-interval clock skew. This ensures that users can successfully authenticate within this timeframe, even if there are slight variations in system clocks.
+
### How do I check _when_ a user went through MFA?
Access tokens issued by Supabase Auth contain an `amr` (Authentication Methods Reference) claim. It is an array of objects that indicate what authentication methods the user has used so far.
@@ -629,13 +622,10 @@ Currently recognized authentication methods are:
- `sso/saml` - any Single Sign On (SAML) method.
The following additional claims are available when using PKCE flow:
+
- `invite` - any sign in via an invitation.
- `magiclink` - any sign in via magic link. Excludes logins resulting from invocation of `signUp`.
- `email/signup` - any login resulting from an email signup.
- `email_change` - any login resulting from a change in email.
More authentication methods will be added over time as we increase the number of authentication methods supported by Supabase.
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/auth-smtp.mdx b/apps/docs/content/guides/auth/auth-smtp.mdx
similarity index 84%
rename from apps/docs/pages/guides/auth/auth-smtp.mdx
rename to apps/docs/content/guides/auth/auth-smtp.mdx
index 918e20b144d..ed80f9780cd 100644
--- a/apps/docs/pages/guides/auth/auth-smtp.mdx
+++ b/apps/docs/content/guides/auth/auth-smtp.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-smtp',
- title: 'Configure a Custom SMTP',
- description: 'Moving towards production: Configuring a custom SMTP provider',
-}
+---
+id: 'auth-smtp'
+title: 'Configure a Custom SMTP'
+description: 'Moving towards production: Configuring a custom SMTP provider'
+---
## Auth SMTP
@@ -38,6 +36,3 @@ You can use Supabase Auth with any major SMTP provider of your choosing. Some SM
- [Twilio SendGrid](https://docs.sendgrid.com/for-developers/sending-email/integrating-with-the-smtp-api)
- [AWS SES](https://docs.aws.amazon.com/ses/latest/dg/send-email-smtp.html)
- [Resend](https://resend.com/docs/dashboard/emails/introduction)
-
-export const Page = ({ children }) =>
-export default Page
diff --git a/apps/docs/pages/guides/auth/auth-user-management.mdx b/apps/docs/content/guides/auth/auth-user-management.mdx
similarity index 95%
rename from apps/docs/pages/guides/auth/auth-user-management.mdx
rename to apps/docs/content/guides/auth/auth-user-management.mdx
index edc65197f44..1e24c2e142e 100644
--- a/apps/docs/pages/guides/auth/auth-user-management.mdx
+++ b/apps/docs/content/guides/auth/auth-user-management.mdx
@@ -1,11 +1,9 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-user-management',
- title: 'User Management',
- description: 'Manage your users with Supabase Auth',
- subtitle: 'Manage your users with Supabase Auth',
-}
+---
+id: 'auth-user-management'
+title: 'User Management'
+description: 'Manage your users with Supabase Auth'
+subtitle: 'Manage your users with Supabase Auth'
+---
## The user object
@@ -81,7 +79,3 @@ Supabase Auth provides these [configuration options](/dashboard/project/_/settin
- **Confirm Email (Deprecated)**: Users will need to confirm their email address before signing in for the first time.
- Having **Confirm Email** disabled assumes that the user's email does not need to be verified in order to login and implicitly confirms the user's email in the database.
- If you previously relied on this config to autoconfirm a user's email address, you can switch to use **Allow unverified email sign in** instead. This new option allows the user to sign in with an unverified email which you can keep track of through the user object. It provides more versatility if you require your users to verify their email address in the future since you can structure your RLS policies to check the user's `email_verified` field.
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/column-level-security.mdx b/apps/docs/content/guides/auth/column-level-security.mdx
similarity index 85%
rename from apps/docs/pages/guides/auth/column-level-security.mdx
rename to apps/docs/content/guides/auth/column-level-security.mdx
index 942c7ff8bcc..ac2155ca023 100644
--- a/apps/docs/pages/guides/auth/column-level-security.mdx
+++ b/apps/docs/content/guides/auth/column-level-security.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'column-level-security',
- title: 'Column Level Security',
- description: 'Secure your data using Postgres Column Level Security.',
-}
+---
+id: 'column-level-security'
+title: 'Column Level Security'
+description: 'Secure your data using Postgres Column Level Security.'
+---
PostgreSQL's [Row Level Security (RLS)](https://www.postgresql.org/docs/current/ddl-rowsecurity.html) gives you granular control over who can access rows of data. However, it doesn't give you control over which columns they can access within rows. Sometimes you want to restrict access to specific columns in your database. Column Level Privileges allows you to do just that.
@@ -118,30 +116,28 @@ supabase migration new create_posts_table
```sql
+ create table
+ posts (
+ id bigint primary key generated always as identity,
+ user_id text,
+ title text,
+ content text,
+ created_at timestamptz default now()
+ updated_at timestamptz default now()
+ );
-create table
-posts (
-id bigint primary key generated always as identity,
-user_id text,
-title text,
-content text,
-created_at timestamptz default now()
-updated_at timestamptz default now()
-);
+ -- Add row-level security
+ create a policy "Allow update for owners" on posts for
+ update
+ using (auth.uid () = user_id);
--- Add row-level security
-create a policy "Allow update for owners" on posts for
-update
-using (auth.uid () = user_id);
-
--- Add column-level security
-revoke
-update
-(title) on table public.posts
-from
-authenticated;
-
-```
+ -- Add column-level security
+ revoke
+ update
+ (title) on table public.posts
+ from
+ authenticated;
+ ```
@@ -149,10 +145,6 @@ authenticated;
## Considerations when using column-level privileges
+
- If you turn off a column privilege you won't be able to use that column at all.
- All operations (insert, update, delete) as well as using `select *` will fail.
-
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/concepts/redirect-urls.mdx b/apps/docs/content/guides/auth/concepts/redirect-urls.mdx
similarity index 94%
rename from apps/docs/pages/guides/auth/concepts/redirect-urls.mdx
rename to apps/docs/content/guides/auth/concepts/redirect-urls.mdx
index 2ffa7186bd8..2fcd240acd8 100644
--- a/apps/docs/pages/guides/auth/concepts/redirect-urls.mdx
+++ b/apps/docs/content/guides/auth/concepts/redirect-urls.mdx
@@ -1,11 +1,9 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'redirect-urls',
- title: 'Redirect URLs',
- description: 'Set up redirect urls with Supabase Auth.',
- subtitle: 'Set up redirect urls with Supabase Auth.',
-}
+---
+id: 'redirect-urls'
+title: 'Redirect URLs'
+description: 'Set up redirect urls with Supabase Auth.'
+subtitle: 'Set up redirect urls with Supabase Auth.'
+---
## Overview
@@ -83,7 +81,3 @@ const { data, error } = await supabase.auth.signInWithOAuth({
For mobile applications you can use deep linking URIs. For example, for your `SITE_URL` you can specify something like `com.supabase://login-callback/` and for additional redirect URLs something like `com.supabase.staging://login-callback/` if needed.
Read more about deep linking and find code examples for different frameworks [here](/docs/guides/auth/native-mobile-deep-linking).
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/content/guides/auth/enterprise-sso.mdx b/apps/docs/content/guides/auth/enterprise-sso.mdx
new file mode 100644
index 00000000000..16390c486f4
--- /dev/null
+++ b/apps/docs/content/guides/auth/enterprise-sso.mdx
@@ -0,0 +1,6 @@
+---
+title: 'Enterprise Single Sign-On'
+description: 'Learn about Single Sign-On support in Supabase Auth for enterprise applications'
+---
+
+Supabase Auth supports building enterprise applications that require Single Sign-On (SSO) authentication [with SAML 2.0](/docs/guides/auth/sso/auth-sso-saml).
diff --git a/apps/docs/pages/guides/auth/managing-user-data.mdx b/apps/docs/content/guides/auth/managing-user-data.mdx
similarity index 96%
rename from apps/docs/pages/guides/auth/managing-user-data.mdx
rename to apps/docs/content/guides/auth/managing-user-data.mdx
index 2735f05f837..dd73f0757ac 100644
--- a/apps/docs/pages/guides/auth/managing-user-data.mdx
+++ b/apps/docs/content/guides/auth/managing-user-data.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'managing-user-data',
- title: 'Managing User Data',
- description: 'Securing your user data with Row Level Security.',
-}
+---
+id: 'managing-user-data'
+title: 'Managing User Data'
+description: 'Securing your user data with Row Level Security.'
+---
For security purposes, the `auth` schema is not exposed on the auto-generated API.
@@ -241,7 +239,3 @@ create trigger on_auth_user_created
after insert on auth.users
for each row execute procedure public.handle_new_user();
```
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/native-mobile-deep-linking.mdx b/apps/docs/content/guides/auth/native-mobile-deep-linking.mdx
similarity index 95%
rename from apps/docs/pages/guides/auth/native-mobile-deep-linking.mdx
rename to apps/docs/content/guides/auth/native-mobile-deep-linking.mdx
index f1eb1425e3d..7017d7a779b 100644
--- a/apps/docs/pages/guides/auth/native-mobile-deep-linking.mdx
+++ b/apps/docs/content/guides/auth/native-mobile-deep-linking.mdx
@@ -1,13 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-import { IconPanel } from 'ui'
-import Link from 'next/link'
-import { NativeMobileLoginItems } from '~/components/Navigation/NavigationMenu/NavigationMenu.constants'
-
-export const meta = {
- title: 'Native Mobile Deep Linking',
- description: 'Learn how to handle deep linking for OAuth and email based login.',
- tocVideo: '8TZ6O1C8ujE',
-}
+---
+title: 'Native Mobile Deep Linking'
+description: 'Learn how to handle deep linking for OAuth and email based login.'
+tocVideo: '8TZ6O1C8ujE'
+---
In certain auth scenarios you will need to handle linking back into your application to finish the user's sign in.
@@ -115,6 +110,7 @@ In certain auth scenarios you will need to handle linking back into your applica
```
For the best user experience it is recommended to use universal links which require a more elaborate setup. You can find the detailed setup instructions in the [Expo docs](https://docs.expo.dev/guides/deep-linking/).
+
\*Currently supabase_flutter supports deep links on Android, iOS, Web, MacOS and Windows.
@@ -266,7 +262,7 @@ In certain auth scenarios you will need to handle linking back into your applica
...
```
- At this point, you can register your own scheme.
+ At this point, you can register your own scheme.
On Windows, URL protocols are setup in the Windows registry.
This package won't do it for you.
@@ -306,6 +302,7 @@ In certain auth scenarios you will need to handle linking back into your applica
+
@@ -344,10 +341,6 @@ In certain auth scenarios you will need to handle linking back into your applica
```
+
-
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/native-mobile-login.mdx b/apps/docs/content/guides/auth/native-mobile-login.mdx
similarity index 71%
rename from apps/docs/pages/guides/auth/native-mobile-login.mdx
rename to apps/docs/content/guides/auth/native-mobile-login.mdx
index c5883ab7bad..95acd9e583a 100644
--- a/apps/docs/pages/guides/auth/native-mobile-login.mdx
+++ b/apps/docs/content/guides/auth/native-mobile-login.mdx
@@ -1,12 +1,7 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-import { IconPanel } from 'ui'
-import Link from 'next/link'
-import { NativeMobileLoginItems } from '~/components/Navigation/NavigationMenu/NavigationMenu.constants'
-
-export const meta = {
- title: 'Native Mobile Login',
- description: 'Logging in with native mobile identity providers like Apple & Google.',
-}
+---
+title: 'Native Mobile Login'
+description: 'Logging in with native mobile identity providers like Apple & Google.'
+---
Some native mobile operating systems, like iOS and Android, offer a built-in identity provider for convenient user authentication.
@@ -25,21 +20,28 @@ There are several reasons why you might want to add social login to your applica
## Set up a native social login with Supabase Auth
## Provider tokens
@@ -47,7 +49,3 @@ There are several reasons why you might want to add social login to your applica
Just like with Oauth, you will receive a copy of the provider token in case you need to use it further. For example, you can use the Google provider token to access Google APIs on behalf of your user.
Provider tokens are intentionally not stored in your project's database, however. This is because provider tokens give access to potentially sensitive user data in third-party systems. Different applications have different needs, and one application's OAuth scopes may be significantly more permissive than another. If you do want to use the provider token outside of the browser that completed the OAuth flow, you will have to send it manually to a secure server under your control.
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/passwordless-login.mdx b/apps/docs/content/guides/auth/passwordless-login.mdx
similarity index 65%
rename from apps/docs/pages/guides/auth/passwordless-login.mdx
rename to apps/docs/content/guides/auth/passwordless-login.mdx
index cd8a76cd7f6..cb8d308ecb2 100644
--- a/apps/docs/pages/guides/auth/passwordless-login.mdx
+++ b/apps/docs/content/guides/auth/passwordless-login.mdx
@@ -1,12 +1,7 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-import { IconPanel, GlassPanel, IconMail } from 'ui'
-import Link from 'next/link'
-import { PhoneLoginsItems } from '~/components/Navigation/NavigationMenu/NavigationMenu.constants'
-
-export const meta = {
- title: 'Passwordless Login',
- description: 'Sign in your users without passwords via magic link email, or one-time passwords sent via email, SMS, or WhatsApp.',
-}
+---
+title: 'Passwordless Login'
+description: 'Sign in your users without passwords via magic link email, or one-time passwords sent via email, SMS, or WhatsApp.'
+---
Supabase supports various forms of passwordless authentication:
@@ -35,23 +30,22 @@ There are several reasons why you might want to add passwordless login to your a
Supabase supports [Phone Login](/docs/guides/auth/phone-login) (SMS & WhatsApp) with several communications platforms. Follow the guides below to set up a provider with Supabase Auth.
-
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/passwordless-login/auth-email-otp.mdx b/apps/docs/content/guides/auth/passwordless-login/auth-email-otp.mdx
similarity index 83%
rename from apps/docs/pages/guides/auth/passwordless-login/auth-email-otp.mdx
rename to apps/docs/content/guides/auth/passwordless-login/auth-email-otp.mdx
index 38857d78245..820f70e4b5c 100644
--- a/apps/docs/pages/guides/auth/passwordless-login/auth-email-otp.mdx
+++ b/apps/docs/content/guides/auth/passwordless-login/auth-email-otp.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-email-otp',
- title: 'Login With Email OTP',
- description: 'Use Supabase to authenticate your users using one-time password emails.',
-}
+---
+id: 'auth-email-otp'
+title: 'Login With Email OTP'
+description: 'Use Supabase to authenticate your users using one-time password emails.'
+---
Email one-time passwords (OTP) are a form of passwordless login where users key in a six digit code sent to their email address to log in to their accounts. By default, a user can only request an OTP once every 60 seconds and they expire after 24 hours.
@@ -86,6 +84,15 @@ If the request was successful, you receive a response with `error: null` and a `
## Verify OTP to create session
+
+
+
Provide an input field for the user to key in the one-time code. To verify the code and complete the user's sign in, call [verifyOtp()](/docs/reference/javascript/auth-verifyotp) with their email address, the code, and `type: "email"`:
```js
@@ -99,6 +106,18 @@ const {
})
```
+
+
+
+Provide an input field for the user to key in the one-time code. To verify the code and complete the user's sign in, call [verifyEmailOtp()](/docs/reference/kotlin/auth-verifyotp) with their email address, the code, and `OtpType.Email.EMAIL` as the type:
+
+```kotlin
+supabase.auth.verifyEmailOtp(type = OtpType.Email.EMAIL, email = "email", token = "151345")
+```
+
+
+
+
If successful the user will now be logged in and you should receive a valid session like:
```json
@@ -117,7 +136,3 @@ If successful the user will now be logged in and you should receive a valid sess
- [Phone SMS & WhatsApp OTP](/docs/guides/auth/phone-login)
- [Supabase JS Client](https://github.com/supabase/supabase-js)
- [Supabase Flutter Client](https://github.com/supabase/supabase-flutter)
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/passwordless-login/auth-magic-link.mdx b/apps/docs/content/guides/auth/passwordless-login/auth-magic-link.mdx
similarity index 93%
rename from apps/docs/pages/guides/auth/passwordless-login/auth-magic-link.mdx
rename to apps/docs/content/guides/auth/passwordless-login/auth-magic-link.mdx
index 9ca6be133c5..4b6ffdfdc87 100644
--- a/apps/docs/pages/guides/auth/passwordless-login/auth-magic-link.mdx
+++ b/apps/docs/content/guides/auth/passwordless-login/auth-magic-link.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-magic-link',
- title: 'Login With Magic Link',
- description: 'Use Supabase to authenticate your users using magic links.',
-}
+---
+id: 'auth-magic-link'
+title: 'Login With Magic Link'
+description: 'Use Supabase to authenticate your users using magic links.'
+---
Magic links are a form of passwordless logins where users click on a link sent to their email address to log in to their accounts. Magic links only work with email addresses and are one-time use only. By default, a user can only request a magic link once every 60 seconds and they expire after 24 hours.
@@ -140,7 +138,3 @@ suspend fun logout() {
- [Supabase Account - Free Plan OK](https://supabase.com)
- [Supabase JS Client](https://github.com/supabase/supabase-js)
- [Supabase Flutter Client](https://github.com/supabase/supabase-flutter)
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/passwords.mdx b/apps/docs/content/guides/auth/passwords.mdx
similarity index 76%
rename from apps/docs/pages/guides/auth/passwords.mdx
rename to apps/docs/content/guides/auth/passwords.mdx
index 41d85695f4b..25877dad288 100644
--- a/apps/docs/pages/guides/auth/passwords.mdx
+++ b/apps/docs/content/guides/auth/passwords.mdx
@@ -1,11 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-import { Accordion } from 'ui'
-
-export const meta = {
- id: 'auth-passwords',
- title: 'Passwords',
- description: 'How to work with passwords in Supabase Auth',
-}
+---
+id: 'auth-passwords'
+title: 'Passwords'
+description: 'How to work with passwords in Supabase Auth'
+---
Using passwords to authenticate users is a tried-and-tested method to give your users access to your application. Supabase Auth provides you with secure configuration options and uses best practices to store and verify your user's passwords.
@@ -52,28 +49,28 @@ Strong passwords are difficult to remember, so Supabase Auth provides you with A
To add a secure password reset flow to your application:
1. Build the **password reset page**:
- - Should be publicly accessible and contain a form asking for the user's email address.
- - Use the [`supabase.auth.resetPasswordForEmail`](/docs/reference/javascript/auth-resetpasswordforemail) API to request a password reset link for a user's email address.
- - Specify the `redirectTo` parameter when calling this API to point to the URL of the **change password page.**
+ - Should be publicly accessible and contain a form asking for the user's email address.
+ - Use the [`supabase.auth.resetPasswordForEmail`](/docs/reference/javascript/auth-resetpasswordforemail) API to request a password reset link for a user's email address.
+ - Specify the `redirectTo` parameter when calling this API to point to the URL of the **change password page.**
2. Build the **password change page**:
- - Should be accessible only to authenticated users.
- - Add its URL to the allowed [Redirect URLs](/dashboard/project/_/auth/url-configuration) settings.
- - Show a form or other prompt asking the user to choose a new password.
- - Call the [`supabase.auth.updateUser`](/docs/reference/javascript/auth-updateuser) API to set a new password for the user.
+ - Should be accessible only to authenticated users.
+ - Add its URL to the allowed [Redirect URLs](/dashboard/project/_/auth/url-configuration) settings.
+ - Show a form or other prompt asking the user to choose a new password.
+ - Call the [`supabase.auth.updateUser`](/docs/reference/javascript/auth-updateuser) API to set a new password for the user.
The email link sent to your users works in the same way as [passwordless authentication](/docs/guides/auth/passwordless-login):
1. After a user visits the **reset password page**, they are sent a reset password link.
- - If you use PKCE (default), this link only works on the device or browser where the original reset request was made. Display a message to the user to make sure they don't change devices or browsers.
- - If you use the implicit grant flow, the link can be opened on any device.
+ - If you use PKCE (default), this link only works on the device or browser where the original reset request was made. Display a message to the user to make sure they don't change devices or browsers.
+ - If you use the implicit grant flow, the link can be opened on any device.
2. A user clicks the link. They are taken to Supabase Auth, which validates the link.
- - If the link is valid, it redirects to the **change password page**, which you specified in the `redirectTo` parameter.
- - If the **change password page's** URL is not properly registered in the [Redirect URLs](/dashboard/project/_/auth/url-configuration) configuration, the user is taken to the default Site URL page.
+ - If the link is valid, it redirects to the **change password page**, which you specified in the `redirectTo` parameter.
+ - If the **change password page's** URL is not properly registered in the [Redirect URLs](/dashboard/project/_/auth/url-configuration) configuration, the user is taken to the default Site URL page.
3. Supabase Auth redirects to the **change password page** including [session](/docs/guides/auth/sessions) information in the URL.
- - If you used PKCE (default), the redirect contains the `code` query param.
- - If you are not using official Supabase libraries, or have a custom setup, extract the `code` from the URL and call the [`supabase.auth.exchangeCodeForSession`](/docs/reference/javascript/auth-exchangecodeforsession) API.
- - Official Supabase libraries handle code the code exchange for you.
- - If you used the implicit flow, the redirect contains a URL fragment encoding the user's [session](/docs/guides/auth/sessions).
+ - If you used PKCE (default), the redirect contains the `code` query param.
+ - If you are not using official Supabase libraries, or have a custom setup, extract the `code` from the URL and call the [`supabase.auth.exchangeCodeForSession`](/docs/reference/javascript/auth-exchangecodeforsession) API.
+ - Official Supabase libraries handle code the code exchange for you.
+ - If you used the implicit flow, the redirect contains a URL fragment encoding the user's [session](/docs/guides/auth/sessions).
### Example: Request a password reset email
@@ -153,7 +150,3 @@ The hash is stored in the `encrypted_password` column of the `auth.users` table.
### How will strengthened password requirements affect current users?
Existing users can still sign in with their current password even if it doesn't meet the new, strengthened password requirements. However, if their password falls short of these updated standards, they will encounter a `WeakPasswordError` during the `signInWithPassword` process, explaining why it's considered weak. This change is also applicable to new users and existing users changing their passwords, ensuring everyone adheres to the enhanced security standards.
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/content/guides/auth/phone-login.mdx b/apps/docs/content/guides/auth/phone-login.mdx
new file mode 100644
index 00000000000..a608bcb26eb
--- /dev/null
+++ b/apps/docs/content/guides/auth/phone-login.mdx
@@ -0,0 +1,291 @@
+---
+title: 'Phone Login'
+description: 'Learn about logging in to your platform using SMS one-time passwords.'
+---
+
+
+
+Authenticating users via SMS can become expensive. Adjust your project's rate limits and [configure CAPTCHA](/docs/guides/auth/auth-captcha) to control the bill. Read more about this in the [Production Checklist](/docs/guides/platform/going-into-prod).
+
+
+
+Phone Login is a method of authentication that allows users to log in to a website or application without using a password. Instead of entering a password, the user provides another form of authentication through a one-time code sent via SMS.
+
+## Benefits
+
+There are several reasons why you might want to add phone login to your applications:
+
+- **Improved user experience**: By eliminating the need for users to remember and enter complex passwords, phone login can make it easier and more convenient for users to log in to your application. This can improve the overall user experience and make it more enjoyable for users to interact with your application.
+
+- **Increased security**: Phone login can improve the security of your application by reducing the risk of password-related security breaches, such as password reuse and weak passwords. By using alternative forms of authentication, such as one-time codes or biometric factors, you can make it more difficult for unauthorized users to access your application.
+
+- **Reduced support burden**: Phone login can also help reduce the support burden for your team by eliminating the need to handle password recovery flows or deal with other password-related issues. This can free up your team to focus on other important tasks and improve the efficiency of your operation.
+
+## Set up a provider with Supabase Auth
+
+To use Phone Login, you first need to set up a Phone provider. Supabase supports Phone Login with several communications platforms. Follow the guides below to set up your provider.
+
+
+
+## Using Phone Login
+
+You can use Phone Login to:
+
+- [Sign up a user with phone number and password](/docs/guides/auth/phone-login#sign-up-a-user-with-phone-number-and-password)
+- [Sign in a user with a One Time Password (OTP)](/docs/guides/auth/phone-login#sign-in-a-user-with-otp)
+- [Update a user's phone number](/docs/guides/auth/phone-login#update-a-users-phone-number)
+
+Each of these flows sends the user an SMS containing a six-digit PIN, which you must [verify](/docs/guides/auth/phone-login#verify-a-user) to complete the flow.
+
+### Sign up a user with phone number and password
+
+You can use a user's mobile phone number, instead of an email address, when they sign up with a password.
+
+This practice is usually discouraged because phone networks often recycle mobile phone numbers. Anyone receiving a recycled phone number gets access to the original user's account. To mitigate this risk, [implement MFA](/docs/guides/auth/auth-mfa).
+
+To sign up the user, call [`signUp()`](/docs/reference/javascript/auth-signup) with their phone number and password:
+
+
+
+
+
+```js
+const { data, error } = await supabase.auth.signUp({
+ phone: '+13334445555',
+ password: 'some-password',
+})
+```
+
+
+
+
+```kotlin
+supabase.auth.signUpWith(Phone) {
+ phone = "+13334445555"
+ password = "some-password"
+}
+```
+
+
+
+
+```bash
+curl -X POST 'https://cvwawazfelidkloqmbma.supabase.co/auth/v1/signup' \
+-H "apikey: SUPABASE_KEY" \
+-H "Content-Type: application/json" \
+-d '{
+ "phone": "+13334445555",
+ "password": "some-password"
+}'
+```
+
+
+
+
+The user receives an SMS with a 6-digit pin that you must [verify](/docs/guides/auth/phone-login#verify-a-user) within 60 seconds.
+
+After their phone number is verified, the user can use their phone number and password to sign in with needing to reverify each time:
+
+
+
+
+```js
+const { user, error } = await supabase.auth.signInWithPassword({
+ phone: '+13334445555',
+ password: 'some-password',
+})
+```
+
+
+
+
+```kotlin
+supabase.auth.signInWith(Phone) {
+ phone = "+13334445555"
+ password = "some-password"
+}
+```
+
+
+
+
+```bash
+curl -X POST 'https://cvwawazfelidkloqmbma.supabase.co/auth/v1/token?grant_type=password' \
+-H "apikey: SUPABASE_KEY" \
+-H "Content-Type: application/json" \
+-d '{
+ "phone": "+13334445555",
+ "password": "some-password"
+}'
+```
+
+
+
+
+### Sign in a user with OTP
+
+With OTP, a user can sign in without setting a password on their account. They need to verify their phone number each time they sign in.
+
+
+
+
+```js
+const { data, error } = await supabase.auth.signInWithOtp({
+ phone: '+13334445555',
+})
+```
+
+
+
+
+```kotlin
+supabase.auth.signInWith(OTP) {
+ phone = "+13334445555"
+}
+```
+
+
+
+
+```bash
+curl -X POST 'https://cvwawazfelidkloqmbma.supabase.co/auth/v1/otp' \
+-H "apikey: SUPABASE_KEY" \
+-H "Content-Type: application/json" \
+-d '{
+ "phone": "+13334445555"
+}'
+```
+
+
+
+
+The user receives an SMS with a 6-digit pin that you must [verify](/docs/guides/auth/phone-login#verify-a-user) within 60 seconds.
+
+### Update a user's phone number
+
+To update a user's phone number, the user must be logged in. Call [`updateUser()`](/docs/reference/javascript/auth-updateuser) with their phone number:
+
+
+
+
+```js
+const { data, error } = await supabase.auth.updateUser({
+ phone: '123456789',
+})
+```
+
+
+
+
+The user receives an SMS with a 6-digit pin that you must [verify](/docs/guides/auth/phone-login#verify-a-user) within 60 seconds.
+
+### Verify a user
+
+To verify the one-time password (OTP) sent to the user's phone number, call [`verifyOtp()`](/docs/reference/javascript/auth-verifyotp) with the phone number and OTP:
+
+
+
+
+You should present a form to the user so they can input the 6 digit pin, then send it along with the phone number to `verifyOtp`:
+
+```js
+const {
+ data: { session },
+ error,
+} = await supabase.auth.verifyOtp({
+ phone: '+13334445555',
+ token: '123456',
+ type: 'sms',
+})
+```
+
+
+
+
+You should present a form to the user so they can input the 6 digit pin, then send it along with the phone number to `verifyPhoneOtp`:
+
+```kotlin
+supabase.auth.verifyPhoneOtp(
+ type = OtpType.Phone.SMS,
+ phone = "+13334445555",
+ token = "123456"
+)
+```
+
+
+
+
+```bash
+curl -X POST 'https://.supabase.co/auth/v1/verify' \
+-H "apikey: " \
+-H "Content-Type: application/json" \
+-d '{
+ "type": "sms",
+ "phone": "+13334445555",
+ "token": "123456"
+}'
+```
+
+
+
+
+If successful the user will now be logged in and you should receive a valid session like:
+
+```json
+{
+ "access_token": "",
+ "token_type": "bearer",
+ "expires_in": 3600,
+ "refresh_token": ""
+}
+```
+
+The access token can be sent in the Authorization header as a Bearer token for any CRUD operations on supabase-js. See our guide on [Row Level Security](/docs/guides/auth#row-level-security) for more info on restricting access on a user basis.
diff --git a/apps/docs/content/guides/auth/phone-login/messagebird.mdx b/apps/docs/content/guides/auth/phone-login/messagebird.mdx
new file mode 100644
index 00000000000..27d882780ef
--- /dev/null
+++ b/apps/docs/content/guides/auth/phone-login/messagebird.mdx
@@ -0,0 +1,69 @@
+---
+id: 'auth-messagebird'
+title: 'Phone Auth with MessageBird'
+description: 'How to set up and use Mobile OTP with MessageBird and Supabase.'
+---
+
+
+
+Authenticating users via SMS can become expensive. Adjust your project's rate limits and [configure CAPTCHA](/docs/guides/auth/auth-captcha) to control the bill. Read more about this in the [Production Checklist](/docs/guides/platform/going-into-prod).
+
+
+
+## Prerequisites
+
+You'll need:
+
+- A MessageBird account (sign up [here](https://dashboard.messagebird.com/en/sign-up))
+- A Supabase project (create one [here](https://supabase.com/dashboard))
+- A mobile phone capable of receiving SMS
+
+## Set up MessageBird as your SMS provider
+
+Start by logging into your MessageBird account and verify the mobile number you'll be using to test with [here](https://dashboard.messagebird.com/en/getting-started/sms). This is the number that will be receiving the SMS OTPs.
+
+
+
+
+
+Navigate to the [dashboard settings](https://dashboard.messagebird.com/en/settings/sms) to set the default originator. The messagebird originator is the name or number from which the message is sent. For more information, you can refer to the messagebird article on choosing an originator [here](https://support.messagebird.com/hc/en-us/articles/115002628665-Choosing-an-originator)
+
+
+
+You will need the following values to get started:
+
+- Live API Key / Test API Key
+- MessageBird originator
+
+Now go to the [Auth > Providers](https://supabase.com/dashboard/project/_/auth/providers) page in the Supabase dashboard and select "Phone" from the Auth Providers list.
+
+You should see an option to enable the Phone provider.
+
+Toggle it on, and copy the 2 values over from the Messagebird dashboard. Click save.
+
+
+
+If you use the Test API Key, the OTP will not be delivered to the mobile number specified but messagebird will log the response in the dashboard. If the Live API Key is used instead, the OTP will be delivered and there will be a deduction in your free credits.
+
+
+
+Plugin MessageBird credentials
+
+Now the backend should be setup, we can proceed to add our client-side code!
+
+#### SMS custom template
+
+The SMS message sent to a phone containing an OTP code can be customized. This is useful if you need to mention a brand name or display a website address.
+
+Go to [Auth > Templates](https://supabase.com/dashboard/project/_/auth/templates) page in the Supabase dashboard.
+
+Use the variable `.Code` in the template to display the code.
+
+## Next steps
+
+To implement Phone Login, see the docs on [using Phone Login](/docs/guides/auth/phone-login#using-phone-login).
+
+## Resources
+
+- [MessageBird Signup](https://dashboard.messagebird.com/en/sign-up)
+- [Supabase Dashboard](https://supabase.com/dashboard)
diff --git a/apps/docs/content/guides/auth/phone-login/twilio.mdx b/apps/docs/content/guides/auth/phone-login/twilio.mdx
new file mode 100644
index 00000000000..86bbd8bae8b
--- /dev/null
+++ b/apps/docs/content/guides/auth/phone-login/twilio.mdx
@@ -0,0 +1,151 @@
+---
+id: 'auth-twilio'
+title: 'Phone Auth with Twilio'
+description: 'How to set up and use Mobile OTP with Twilio and Supabase.'
+video: 'https://www.youtube.com/v/akScoPO01bc'
+---
+
+
+
+Authenticating users via SMS can become expensive. Adjust your project's rate limits and [configure CAPTCHA](/docs/guides/auth/auth-captcha) to control the bill. Read more about this in the [Production Checklist](/docs/guides/platform/going-into-prod).
+
+
+
+## Preqrequisites
+
+You'll need:
+
+- Twilio account ([sign up](https://www.twilio.com/try-twilio))
+- Supabase project (create one [here](https://supabase.com/dashboard))
+- Mobile phone capable of receiving SMS
+
+SMS Authentication can be done with either Twilio Verify or Twilio Programmable Messaging. [Twilio Verify](https://www.twilio.com/en-us/trusted-activation/verify) is a specialized OTP solution and is recommended for most developers that need over-the-phone authentication. Alternatively you can use [Twilio Programmable Messaging](https://www.twilio.com/docs/messaging) which offers generic SMS sending support.
+
+## Twilio Verify
+
+To set up Twilio Verify, you will need to:
+
+1. Create a new [verification service](https://support.twilio.com/hc/en-us/articles/360033309133-Getting-Started-with-Twilio-Verify-V2) in the Twilio dashboard.
+2. [Switch Phone Provider to Twilio Verify](https://supabase.com/dashboard/project/_/auth/providers)
+3. Configure the Twilio Verify Service ID field using the Verification Service ID obtained in 1.
+
+When using Twilio Verify, OTPs are generated by Twilio. This means that:
+
+- Unlike other providers, the OTP expiry duration and message content fields are not configurable via the Supabase dashboard. Please head to Twilio Verify to configure these settings.
+- The token remains the same during its validity period until the verification is successful. This means if your user make another request within that period, they will receive the same token.
+- Twilio Verify has a separate set of rate limits that apply. Visit Twilio's [Rate Limit and Timeouts page](https://www.twilio.com/docs/verify/api/rate-limits-and-timeouts) to find out more.
+
+
+
+At this time, Twilio Verify is only supported on the `whatsapp` and `sms` channels.
+
+
+
+## Twilio (Programmable Messaging)
+
+In this section, you'll set up Twilio as an SMS provider:
+
+What you'll need:
+
+- A Twilio account (sign up here: https://www.twilio.com/try-twilio)
+- A Supabase project (create one here: https://supabase.com/dashboard)
+- A mobile phone capable of receiving SMS
+
+
+
+
+
+### Setting up your Twilio credentials
+
+Start by logging into your Twilio account and starting a new project: https://www.twilio.com/console/projects/create
+
+Give your project a name and verify the mobile number you'll be using to test with. This is the number that will be receiving the SMS OTPs.
+
+
+
+
+Select 'SMS', 'Identity & Verification', and 'With code' as options on the welcome form.
+
+
+
+When you're back on the [Twilio console screen](https://www.twilio.com/console), you need to scroll down and click 'Get a trial phone number' - this is the number that you'll be sending SMSs from.
+
+
+
+
+
+You should now be able to see all three values you'll need to get started:
+
+- Account SID
+- Auth Token
+- Sender Phone Number
+
+
+
+Now go to the [Auth > Providers](https://supabase.com/dashboard/project/_/auth/providers) page in the Supabase dashboard and select "Phone" from the Auth Providers list.
+
+You should see an option to enable the Phone provider.
+
+Toggle it on, and copy the 3 values over from the Twilio dashboard. Click save.
+
+Note: for "Twilio Message Service SID" you can use the Sender Phone Number generated above.
+
+
+
+Now the backend should be setup, we can proceed to add our client-side code!
+
+
+ The `Twilio Content SID` field is specific to Twilio Programmable Messaging (WhatsApp) senders.
+ Disregard this field if you are only sending SMS messages. Refer to the section on WhatsApp OTP
+ Logins for further details.
+
+
+#### SMS custom template
+
+The SMS message sent to a phone containing an OTP code can be customized. This is useful if you need to mention a brand name or display a website address.
+
+Go to the [Auth > Providers](https://supabase.com/dashboard/project/_/auth/providers) page in the Supabase dashboard and select "Phone" from the Auth Providers list. Scroll to the very bottom of the "Phone" section to the "SMS Message" input - you can customize the SMS message here.
+
+Use the variable `.Code` in the template to display the OTP code. Here's an example in the SMS template.
+
+
+
+## WhatsApp OTP logins
+
+In some cases, you may wish to use WhatsApp as a delivery channel instead. Here are some examples our users have cited:
+
+- You want higher deliverability
+- You wish for a secure channel
+- Your users mostly use WhatsApp as a messaging platform
+
+Twilio Verify can be used with WhatsApp OTPs with no additional configuration.
+
+Complete the following steps to use WhatsApp OTP with Twilio Programmable Messaging:
+
+1. Go through the [Twilio self sign up guide for WhatsApp](https://www.twilio.com/docs/whatsapp/self-sign-up).
+2. Register a Twilio Content Template via the [API](https://www.twilio.com/docs/content/whatsappauthentication) and note the corresponding Twilio Content SID. You can also use the Template Builder on the Twilio dashboard to create a Content Template
+ 
+3. Register the Twilio Content SID on the Supabase dashboard under Authentication > Providers > Phone > Twilio Content SID. Ensure you have Twilio selected as your phone provider.
+
+
+
+You may only use one Twilio Content SID at a time. Supabase Auth will use the Content Template over the `SMS Message` field when sending WhatsApp messages. Use Twilio Verify if you need to use more than one message template.
+
+
+
+## Next steps
+
+To implement Phone Login, see the docs on [using Phone Login](/docs/guides/auth/phone-login#using-phone-login).
+
+## Resources
+
+- [Reasons to use Twilio Verify](https://www.twilio.com/blog/9-reasons-to-use-the-verify-api)
+- [Twilio Verify Documentation](https://www.twilio.com/docs/verify)
+- [Twilio Signup](https://www.twilio.com/try-twilio)
+- [Supabase Dashboard](https://supabase.com/dashboard)
+- [Supabase Row Level Security](/docs/guides/auth#row-level-security)
diff --git a/apps/docs/content/guides/auth/phone-login/vonage.mdx b/apps/docs/content/guides/auth/phone-login/vonage.mdx
new file mode 100644
index 00000000000..046f0b85d2a
--- /dev/null
+++ b/apps/docs/content/guides/auth/phone-login/vonage.mdx
@@ -0,0 +1,66 @@
+---
+id: 'auth-vonage'
+title: 'Phone Auth with Vonage'
+description: 'How to set up and use Mobile OTP with Vonage and Supabase.'
+---
+
+
+
+Authenticating users via SMS can become expensive. Adjust your project's rate limits and [configure CAPTCHA](/docs/guides/auth/auth-captcha) to control the bill. Read more about this in the [Production Checklist](/docs/guides/platform/going-into-prod).
+
+
+
+## Prerequisites
+
+You'll need:
+
+- A Vonage account (sign up here: https://dashboard.nexmo.com/sign-up)
+- A Supabase project (create one here: https://supabase.com/dashboard)
+- A mobile phone capable of receiving SMS
+
+## Set up Vonage as an SMS provider
+
+### Getting your Vonage credentials
+
+Start by logging into your Vonage Dashboard at https://dashboard.nexmo.com/
+
+You will see you API Key and API Secret here, which is actually all you need to get started.
+
+In most countries, a phone number is actually optional and you can also use any Alphanumeric Sender ID of up to 11 characters length (8 for India) as a Sender ID (from). This means you do not need a number to test with in most cases.
+
+To find out more about supported countries for Alphanumeric Sender ID, check this overview: https://help.nexmo.com/hc/en-us/articles/115011781468-SMS-Features-Overview-Outbound-only-
+
+Hint: Some countries might need a Sender ID Registration to allow sending with an Alphanumeric Sender ID. You can find this information in the help article as well. If Alpha Sender IDs are not supported, you will need to buy a phone number.
+
+### Getting a phone number (optional)
+
+If you want a phone number to send SMS from, you can buy one from the Vonage Dashboard under Numbers > Buy Numbers (https://dashboard.nexmo.com/buy-numbers).
+
+Select the country you want a number for. You will need a mobile phone number with SMS or SMS+Voice capability. After you have bought the number, you will be able to send SMS from it.
+
+### Configure Supabase
+
+Now go to the [Auth > Providers](https://supabase.com/dashboard/project/_/auth/providers) page in the Supabase dashboard and select "Phone" from the Auth Providers list.
+
+You should see an option to enable the Phone provider.
+
+Toggle it on, and copy the API key, API secret and phone number values over from the Vonage dashboard. Click save.
+
+Now the backend should be setup, we can proceed to add our client-side code!
+
+#### SMS custom template
+
+The SMS message sent to a phone containing an OTP code can be customized. This is useful if you need to mention a brand name or display a website address.
+
+Go to [Auth > Templates](https://supabase.com/dashboard/project/_/auth/templates) page in the Supabase dashboard.
+
+Use the variable `.Code` in the template to display the code.
+
+## Next steps
+
+To implement Phone Login, see the docs on [using Phone Login](/docs/guides/auth/phone-login#using-phone-login).
+
+## Resources
+
+- [Vonage Signup](https://dashboard.nexmo.com/sign-up)
+- [Supabase Dashboard](https://supabase.com/dashboard)
diff --git a/apps/docs/pages/guides/auth/quickstarts/nextjs.mdx b/apps/docs/content/guides/auth/quickstarts/nextjs.mdx
similarity index 85%
rename from apps/docs/pages/guides/auth/quickstarts/nextjs.mdx
rename to apps/docs/content/guides/auth/quickstarts/nextjs.mdx
index 05ff464107c..33bb93927d5 100644
--- a/apps/docs/pages/guides/auth/quickstarts/nextjs.mdx
+++ b/apps/docs/content/guides/auth/quickstarts/nextjs.mdx
@@ -1,11 +1,9 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-import StepHikeCompact from '~/components/StepHikeCompact'
-
-export const meta = {
- title: 'Use Supabase Auth with Next.js',
- subtitle: 'Learn how to configure Supabase Auth for the Next.js App Router.',
- breadcrumb: 'Auth Quickstarts',
-}
+---
+title: 'Use Supabase Auth with Next.js'
+subtitle: 'Learn how to configure Supabase Auth for the Next.js App Router.'
+breadcrumb: 'Auth Quickstarts'
+hideToc: true
+---
@@ -88,7 +86,3 @@ export const meta = {
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/quickstarts/react-native.mdx b/apps/docs/content/guides/auth/quickstarts/react-native.mdx
similarity index 95%
rename from apps/docs/pages/guides/auth/quickstarts/react-native.mdx
rename to apps/docs/content/guides/auth/quickstarts/react-native.mdx
index 87ab5ddbff2..ff35d7283e3 100644
--- a/apps/docs/pages/guides/auth/quickstarts/react-native.mdx
+++ b/apps/docs/content/guides/auth/quickstarts/react-native.mdx
@@ -1,11 +1,9 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-import StepHikeCompact from '~/components/StepHikeCompact'
-
-export const meta = {
- title: 'Use Supabase Auth with React Native',
- subtitle: 'Learn how to use Supabase Auth with React Native',
- breadcrumb: 'Auth Quickstarts',
-}
+---
+title: 'Use Supabase Auth with React Native'
+subtitle: 'Learn how to use Supabase Auth with React Native'
+breadcrumb: 'Auth Quickstarts'
+hideToc: true
+---
@@ -268,7 +266,3 @@ export const meta = {
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/quickstarts/react.mdx b/apps/docs/content/guides/auth/quickstarts/react.mdx
similarity index 90%
rename from apps/docs/pages/guides/auth/quickstarts/react.mdx
rename to apps/docs/content/guides/auth/quickstarts/react.mdx
index 8a852e454fd..ca3e45a75bd 100644
--- a/apps/docs/pages/guides/auth/quickstarts/react.mdx
+++ b/apps/docs/content/guides/auth/quickstarts/react.mdx
@@ -1,11 +1,9 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-import StepHikeCompact from '~/components/StepHikeCompact'
-
-export const meta = {
- title: 'Use Supabase Auth with React',
- subtitle: 'Learn how to use Supabase Auth with React.js.',
- breadcrumb: 'Auth Quickstarts',
-}
+---
+title: 'Use Supabase Auth with React'
+subtitle: 'Learn how to use Supabase Auth with React.js.'
+breadcrumb: 'Auth Quickstarts'
+hideToc: true
+---
@@ -132,7 +130,3 @@ export const meta = {
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/row-level-security.mdx b/apps/docs/content/guides/auth/row-level-security.mdx
similarity index 94%
rename from apps/docs/pages/guides/auth/row-level-security.mdx
rename to apps/docs/content/guides/auth/row-level-security.mdx
index d8c1b1b53ba..f7fb52a63df 100644
--- a/apps/docs/pages/guides/auth/row-level-security.mdx
+++ b/apps/docs/content/guides/auth/row-level-security.mdx
@@ -1,12 +1,10 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'row-level-security',
- title: 'Row Level Security',
- description: 'Using Row Level Security with Supabase Auth.',
- subtitle: 'Using Row Level Security with Supabase Auth.',
- tocVideo: 'Ow_Uzedfohk',
-}
+---
+id: 'row-level-security'
+title: 'Row Level Security'
+description: 'Using Row Level Security with Supabase Auth.'
+subtitle: 'Using Row Level Security with Supabase Auth.'
+tocVideo: 'Ow_Uzedfohk'
+---
[Postgres Row Level Security](/docs/guides/database/postgres/row-level-security) (RLS) is a feature of Postgres that allows you to control which users are permitted to perform SELECT/INSERT/UPDATE/DELETE statements on specific rows within tables and views. For example, you could restrict a `blog_post` table such that the current user is only allowed to UPDATE rows where their user id is set in the table's `author_id` column.
@@ -38,10 +36,11 @@ using ( auth.uid() = user_id );
```sql
select *
from todos
-where auth.uid() = todos.user_id; -- Policy is implicitly added.
+where auth.uid() = todos.user_id;
+-- Policy is implicitly added.
```
-## Authenticated and anonymous roles
+## Authenticated and anonymous roles
Supabase Auth maps every request to one of the roles:
@@ -56,7 +55,7 @@ on profiles for select
to authenticated, anon
using ( true );
--- OR
+-- OR
create policy "Public profiles are viewable only by authenticated users"
on profiles for select
@@ -64,7 +63,6 @@ to authenticated
using ( true );
```
-
## Helper functions
Supabase provides some helper functions that make it easier to write Policies.
@@ -82,8 +80,8 @@ Returns the JWT of the user making the request. Anything that you store in the u
The `auth.jwt()` function is extremely versatile. For example, if you store some team data inside `app_metadata`, you can use it to determine whether a particular user belongs to a team. For example, if this was an array of IDs:
-```sql
-create policy "User is in team"
+```sql
+create policy "User is in team"
on my_table
to authenticated
using ( team_id in (select auth.jwt() -> 'app_metadata' -> 'teams'));
@@ -91,7 +89,7 @@ using ( team_id in (select auth.jwt() -> 'app_metadata' -> 'teams'));
-Keep in mind that a JWT is not always "fresh". In the example above, even if you remove a user from a team and update the `app_metadata` field, that will not be reflected using `auth.jwt()` until the user's JWT is refreshed.
+Keep in mind that a JWT is not always "fresh". In the example above, even if you remove a user from a team and update the `app_metadata` field, that will not be reflected using `auth.jwt()` until the user's JWT is refreshed.
Also, if you are using Cookies for Auth, then you must be mindful of the JWT size. Some browsers are limited to 4096 bytes for each cookie, and so the total size of your JWT should be small enough to fit inside this limitation.
@@ -125,7 +123,7 @@ using ( true );
If you want to use another authorization method for your applications that's also fine. Supabase is "just Postgres", so if your application works with Postgres, then it also works with Supabase. If you take this path, don't put your tables in the `public` schema - instead create a new schema for your tables and functions:
-```sql
+```sql
create schema private;
create table private.employees (
@@ -147,10 +145,9 @@ alter table profiles enable row level security;
This makes the tables inaccessible via the [APIs](/docs/guides/api).
-
## Usage
-Row Level Security is extremely versatile, since it simply uses SQL to express access rules for your data.
+Row Level Security is extremely versatile, since it simply uses SQL to express access rules for your data.
### Using functions
@@ -291,7 +288,3 @@ to authenticated using (
- [Testing your database](/docs/guides/database/testing)
- Community repo on testing RLS using [pgTAP and dbdev](https://github.com/usebasejump/supabase-test-helpers/tree/main)
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/server-side-rendering.mdx b/apps/docs/content/guides/auth/server-side-rendering.mdx
similarity index 97%
rename from apps/docs/pages/guides/auth/server-side-rendering.mdx
rename to apps/docs/content/guides/auth/server-side-rendering.mdx
index 4d01f8e1605..78e0d7e31c4 100644
--- a/apps/docs/pages/guides/auth/server-side-rendering.mdx
+++ b/apps/docs/content/guides/auth/server-side-rendering.mdx
@@ -1,11 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-import { Accordion } from 'ui'
-
-export const meta = {
- id: 'server-side-rendering',
- title: 'Server-Side Rendering',
- description: 'Render pages with user information on the server.',
-}
+---
+id: 'server-side-rendering'
+title: 'Server-Side Rendering'
+description: 'Render pages with user information on the server.'
+---
Single-page apps with server-side rendering (SSR) is a popular way to optimize rendering performance and leverage advanced caching strategies.
@@ -68,7 +65,7 @@ Supabase Auth supports two authentication flows: **Implicit** and **PKCE**. The
Web browsers do not send the URL fragment to the server they're making the request to. Since you may not be hosting the single-page app on a server under your direct control (such as on GitHub Pages or other freemium hosting providers), we want to prevent hosting services from getting access to your user's authorization credentials by default.
-
+
Even if the server is under your direct control, `GET` requests and their full URLs are often logged. This approach also avoids leaking credentials in request or access logs. If you wish to obtain the `access_token` and `refresh_token` on a server, please consider using the PKCE flow.
@@ -80,7 +77,7 @@ Supabase Auth supports two authentication flows: **Implicit** and **PKCE**. The
header={PKCE}
id={`ssr-pkce-flow`}
>
-
+
When using the PKCE flow, a redirect URL will be returned with the following structure:
```
https://yourapp.com/...?code=<...>
@@ -90,7 +87,7 @@ Supabase Auth supports two authentication flows: **Implicit** and **PKCE**. The
For security purposes, the code has a validity of 5 minutes and can only be exchanged for an access token once. You will need to restart the authentication flow from scratch if you wish to obtain a new access token.
-
+
As the flow is run server side, `localStorage` may not be available. You may configure the client library to use a custom storage adapter an alternate backing storage such as cookies by setting the `storage` option to an object with the following methods:
@@ -143,6 +140,7 @@ Supabase Auth supports two authentication flows: **Implicit** and **PKCE**. The
+
## Bringing it together
@@ -240,7 +238,3 @@ Also be sure you set proper cache control headers. We recommend invalidating cac
### Which authentication flows have PKCE support?
At present, PKCE is supported on the Magic Link, OAuth, Sign Up, and Password Recovery routes. These correspond to the `signInWithOtp`, `signInWithOAuth`, `signUp`, and `resetPasswordForEmail` methods on the Supabase client library. When using PKCE with Phone and Email OTPs, there is no behavior change with respect to the implicit flow - an access token will be returned in the body when a request is successful.
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/server-side/creating-a-client.mdx b/apps/docs/content/guides/auth/server-side/creating-a-client.mdx
similarity index 96%
rename from apps/docs/pages/guides/auth/server-side/creating-a-client.mdx
rename to apps/docs/content/guides/auth/server-side/creating-a-client.mdx
index f0e4ef72106..b8917844105 100644
--- a/apps/docs/pages/guides/auth/server-side/creating-a-client.mdx
+++ b/apps/docs/content/guides/auth/server-side/creating-a-client.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- title: 'Creating a Supabase client for SSR',
- description: 'Configure Supabase client to use Cookies',
- sidebar_label: 'Creating a client',
-}
+---
+title: 'Creating a Supabase client for SSR'
+description: 'Configure Supabase client to use Cookies'
+sidebar_label: 'Creating a client'
+---
### Install Supabase packages
@@ -98,6 +96,12 @@ dotenv.config()
Creating a Supabase client with the `ssr` package automatically configures it to use cookies. This means your user's session is available throughout the entire Next.js stack - client, server, App Router, Pages Router. It just works!
+
+
+For the client utility functions, it is recommended to create them in a separate `/utils/supabase` folder. That way, you can import them as `client` into any component or page that needs access to Supabase. For further information, you can look at the [Next.js Auth Guide](/docs/guides/auth/server-side/nextjs).
+
+
+
{
* will replicate previous/standard behaviour (https://kit.svelte.dev/docs/types#public-types-cookies)
*/
set: (key, value, options) => {
- event.cookies.set(key, value, { ...options, path: '' })
+ event.cookies.set(key, value, { ...options, path: '/' })
},
remove: (key, options) => {
- event.cookies.delete(key, { ...options, path: '' })
+ event.cookies.delete(key, { ...options, path: '/' })
},
},
})
@@ -862,7 +866,3 @@ app.post("/hello-world", async function (req, res, next) {
- Implement [Authentication using Email and Password](/docs/guides/auth/server-side/email-based-auth-with-pkce-flow-for-ssr)
- Implement [Authentication using OAuth](/docs/guides/auth/server-side/oauth-with-pkce-flow-for-ssr)
- [Learn more about SSR](/docs/guides/auth/server-side-rendering)
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/server-side/email-based-auth-with-pkce-flow-for-ssr.mdx b/apps/docs/content/guides/auth/server-side/email-based-auth-with-pkce-flow-for-ssr.mdx
similarity index 93%
rename from apps/docs/pages/guides/auth/server-side/email-based-auth-with-pkce-flow-for-ssr.mdx
rename to apps/docs/content/guides/auth/server-side/email-based-auth-with-pkce-flow-for-ssr.mdx
index 0eea3cf2723..02fe242a0a0 100644
--- a/apps/docs/pages/guides/auth/server-side/email-based-auth-with-pkce-flow-for-ssr.mdx
+++ b/apps/docs/content/guides/auth/server-side/email-based-auth-with-pkce-flow-for-ssr.mdx
@@ -1,12 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- title: 'Email Auth with PKCE flow for SSR',
- description:
- 'Learn how to configure email authentication in your server-side rendering (SSR) application to work with the PKCE flow.',
- subtitle:
- 'Learn how to configure email authentication in your server-side rendering (SSR) application to work with the PKCE flow.',
-}
+---
+title: 'Email Auth with PKCE flow for SSR'
+description: 'Learn how to configure email authentication in your server-side rendering (SSR) application to work with the PKCE flow.'
+subtitle: 'Learn how to configure email authentication in your server-side rendering (SSR) application to work with the PKCE flow.'
+---
### Setting up SSR client
@@ -277,7 +273,7 @@ Let's update the URL in our email templates to point to our new confirmation end
```
**Change Email Address template**
@@ -306,7 +302,3 @@ Let's update the URL in our email templates to point to our new confirmation end
>
```
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/server-side/migrating-to-ssr-from-auth-helpers.mdx b/apps/docs/content/guides/auth/server-side/migrating-to-ssr-from-auth-helpers.mdx
similarity index 78%
rename from apps/docs/pages/guides/auth/server-side/migrating-to-ssr-from-auth-helpers.mdx
rename to apps/docs/content/guides/auth/server-side/migrating-to-ssr-from-auth-helpers.mdx
index 4ff96642f8b..63de85f80bb 100644
--- a/apps/docs/pages/guides/auth/server-side/migrating-to-ssr-from-auth-helpers.mdx
+++ b/apps/docs/content/guides/auth/server-side/migrating-to-ssr-from-auth-helpers.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- title: 'Migrating to the SSR package from Auth Helpers',
- description: 'Step-by-step guide to migrating your app to the new SSR package',
- sidebar_label: 'Migrating to SSR from Auth Helpers',
-}
+---
+title: 'Migrating to the SSR package from Auth Helpers'
+description: 'Step-by-step guide to migrating your app to the new SSR package'
+sidebar_label: 'Migrating to SSR from Auth Helpers'
+---
The new `ssr` package takes the core concepts of the Auth Helpers and makes them available to any server language or framework. This page will guide you through migrating from the Auth Helpers package to `ssr`.
@@ -50,7 +48,3 @@ Check out the [Creating a client](/docs/guides/auth/server-side/creating-a-clien
- Implement [Authentication using Email and Password](/docs/guides/auth/server-side/email-based-auth-with-pkce-flow-for-ssr)
- Implement [Authentication using OAuth](/docs/guides/auth/server-side/oauth-with-pkce-flow-for-ssr)
- [Learn more about SSR](/docs/guides/auth/server-side-rendering)
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/content/guides/auth/server-side/nextjs.mdx b/apps/docs/content/guides/auth/server-side/nextjs.mdx
new file mode 100644
index 00000000000..99b0cd126e0
--- /dev/null
+++ b/apps/docs/content/guides/auth/server-side/nextjs.mdx
@@ -0,0 +1,1010 @@
+---
+title: 'Setting up Server-Side Auth for Next.js'
+sidebar_label: 'Next.js guide'
+hideToc: true
+---
+
+Next.js comes in two flavors: the [App Router](https://nextjs.org/docs/app) and the [Pages Router](https://nextjs.org/docs/pages). You can set up Server-Side Auth with either strategy. You can even use both in the same application.
+
+
+
+
+
+
+
+
+
+
+
+Install the `@supabase/supabase-js` package and the helper `@supabase/ssr` package.
+
+
+
+
+
+```sh
+npm install @supabase/supabase-js @supabase/ssr
+```
+
+
+
+
+
+
+
+
+
+Create a `.env.local` file in your project root directory.
+
+Fill in your `NEXT_PUBLIC_SUPABASE_URL` and `NEXT_PUBLIC_SUPABASE_ANON_KEY`:
+
+
+
+
+
+
+
+
+```txt .env.local
+NEXT_PUBLIC_SUPABASE_URL=
+NEXT_PUBLIC_SUPABASE_ANON_KEY=
+```
+
+
+
+
+
+
+
+
+
+To access Supabase from your Next.js app, you need 2 types of Supabase clients:
+
+1. **Client Component client** - To access Supabase from Client Components, which run in the browser.
+1. **Server Component client** - To access Supabase from Server Components, Server Actions, and Route Handlers, which run only on the server.
+
+Create a `utils/supabase` folder with a file for each type of client. Then copy the utility functions for each client type.
+
+
+
+ What does the `cookies` object do?}
+ id="utility-cookies"
+ >
+
+ The cookies object lets the Supabase client know how to access the cookies, so it can read and write the user session data. To make `@supabase/ssr` framework-agnostic, the cookies methods aren't hard-coded. These utility functions adapt `@supabase/ssr`'s cookie handling for Next.js.
+
+ The `set` and `remove` methods for the server client need error handlers, because Next.js throws an error if cookies are set from Server Components. You can safely ignore this error because you'll set up middleware in the next step to write refreshed cookies to storage.
+
+
+
+
+
+ Do I need to create a new client for every route?}
+ id="client-deduplication"
+ >
+
+ Yes! Creating a Supabase client is lightweight.
+
+ - On the server, it basically configures a `fetch` call. You need to reconfigure the fetch call anew for every request to your server, because you need the cookies from the request.
+ - On the client, `createBrowserClient` already uses a singleton pattern, so you only ever create one instance, no matter how many times you call your `createClient` function.
+
+
+
+
+
+
+
+
+
+
+
+
+```ts utils/supabase/client.ts
+import { createBrowserClient } from '@supabase/ssr'
+
+export function createClient() {
+ return createBrowserClient(
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
+ process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
+ )
+}
+```
+
+```ts utils/supabase/server.ts
+import { createServerClient, type CookieOptions } from '@supabase/ssr'
+import { type cookies } from 'next/headers'
+
+export function createClient(cookieStore: ReturnType) {
+ return createServerClient(
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
+ process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
+ {
+ cookies: {
+ get(name: string) {
+ return cookieStore.get(name)?.value
+ },
+ set(name: string, value: string, options: CookieOptions) {
+ try {
+ cookieStore.set({ name, value, ...options })
+ } catch (error) {
+ // The `set` method was called from a Server Component.
+ // This can be ignored if you have middleware 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.
+ // This can be ignored if you have middleware refreshing
+ // user sessions.
+ }
+ },
+ },
+ }
+ )
+}
+```
+
+
+
+
+
+
+
+
+
+
+
+Create a `middleware.ts` file at the root of your project.
+
+Since Server Components can't write cookies, you need middleware to refresh expired Auth tokens and store them.
+
+The middleware is responsible for:
+
+1. Refreshing the Auth token (by calling `supabase.auth.getUser`).
+1. Passing the refreshed Auth token to Server Components, so they don't attempt to refresh the same token themselves. This is accomplished with `request.cookies.set`.
+1. Passing the refreshed Auth token to the browser, so it replaces the old token. This is accomplished with `response.cookies.set`.
+
+Copy the middleware code for your app.
+
+Add a [matcher](https://nextjs.org/docs/app/building-your-application/routing/middleware#matching-paths) so the middleware doesn't run on routes that don't access Supabase.
+
+
+
+Be careful when protecting pages. The server gets the user session from the cookies, which can be spoofed by anyone.
+
+Always use `supabase.auth.getUser()` to protect pages and user data.
+
+_Never_ trust `supabase.auth.getSession()` inside server code such as middleware. It isn't guaranteed to revalidate the Auth token.
+
+It's safe to trust `getUser()` because it sends a request to the Supabase Auth server every time to revalidate the Auth token.
+
+
+
+
+
+
+
+```ts middleware.ts
+import { createServerClient, type CookieOptions } from '@supabase/ssr'
+import { NextResponse, type NextRequest } from 'next/server'
+
+export async function middleware(request: NextRequest) {
+ let response = NextResponse.next({
+ request: {
+ headers: request.headers,
+ },
+ })
+
+ const supabase = createServerClient(
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
+ process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
+ {
+ cookies: {
+ get(name: string) {
+ return request.cookies.get(name)?.value
+ },
+ set(name: string, value: string, options: CookieOptions) {
+ request.cookies.set({
+ name,
+ value,
+ ...options,
+ })
+ response = NextResponse.next({
+ request: {
+ headers: request.headers,
+ },
+ })
+ response.cookies.set({
+ name,
+ value,
+ ...options,
+ })
+ },
+ remove(name: string, options: CookieOptions) {
+ request.cookies.set({
+ name,
+ value: '',
+ ...options,
+ })
+ response = NextResponse.next({
+ request: {
+ headers: request.headers,
+ },
+ })
+ response.cookies.set({
+ name,
+ value: '',
+ ...options,
+ })
+ },
+ },
+ }
+ )
+
+ await supabase.auth.getUser()
+
+ return response
+}
+
+export const config = {
+ matcher: [
+ /*
+ * Match all request paths except for the ones starting with:
+ * - _next/static (static files)
+ * - _next/image (image optimization files)
+ * - favicon.ico (favicon file)
+ * Feel free to modify this pattern to include more paths.
+ */
+ '/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
+ ],
+}
+```
+
+
+
+
+
+
+
+
+
+Create a login page for your app. Use a Server Action to call the Supabase signup function.
+
+Since Supabase is being called from an Action, use the client defined in `@/utils/supabase/server.ts`.
+
+
+
+Note that `cookies` is called before any calls to Supabase, which opts fetch calls out of Next.js's caching. This is important for authenticated data fetches, to ensure that users get access only to their own data.
+
+See the Next.js docs to learn more about [opting out of data caching](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#opting-out-of-data-caching).
+
+
+
+
+
+
+
+
+
+```ts app/login/page.tsx
+import { login, signup } from './actions'
+
+export default function LoginPage() {
+ return (
+
+ )
+}
+```
+
+```ts app/login/actions.ts
+'use server'
+
+import { revalidatePath } from 'next/cache'
+import { cookies } from 'next/headers'
+import { redirect } from 'next/navigation'
+
+import { createClient } from '@/utils/supabase/server'
+
+export async function login(formData: FormData) {
+ const cookieStore = cookies()
+ const supabase = createClient(cookieStore)
+
+ // type-casting here for convenience
+ // in practice, you should validate your inputs
+ const data = {
+ email: formData.get('email') as string,
+ password: formData.get('password') as string,
+ }
+
+ const { error } = await supabase.auth.signInWithPassword(data)
+
+ if (error) {
+ redirect('/error')
+ }
+
+ revalidatePath('/', 'layout')
+ redirect('/')
+}
+
+export async function signup(formData: FormData) {
+ const cookieStore = cookies()
+ const supabase = createClient(cookieStore)
+
+ // type-casting here for convenience
+ // in practice, you should validate your inputs
+ const data = {
+ email: formData.get('email') as string,
+ password: formData.get('password') as string,
+ }
+
+ const { error } = await supabase.auth.signUp(data)
+
+ if (error) {
+ redirect('/error')
+ }
+
+ revalidatePath('/', 'layout')
+ redirect('/')
+}
+```
+
+```ts app/error/page.tsx
+export default function ErrorPage() {
+ return
Sorry, something went wrong
+}
+```
+
+
+
+
+
+
+
+
+
+
+
+If you have email confirmation turned on (the default), a new user will receive an email confirmation after signing up.
+
+Change the email template to support a server-side authentication flow.
+
+Go to the [Auth templates](https://supabase.com/dashboard/project/_/auth/templates) page in your dashboard. In each email template, change `{{ .ConfirmationURL }}` to `{{ .SiteURL }}/auth/confirm?token_hash={{ .TokenHash }}&type=signup`.
+
+
+
+
+
+
+
+
+
+Create a Route Handler for `auth/confirm`. When a user clicks their confirmation email link, exchange their secure code for an Auth token.
+
+Since this is a Router Handler, use the Supabase client from `@/utils/supabase/server.ts`.
+
+
+
+
+
+```ts app/auth/confirm/route.ts
+import { type EmailOtpType } from '@supabase/supabase-js'
+import { cookies } from 'next/headers'
+import { type NextRequest, NextResponse } from 'next/server'
+
+import { createClient } from '@/utils/supabase/server'
+
+export async function GET(request: NextRequest) {
+ const cookieStore = cookies()
+
+ const { searchParams } = new URL(request.url)
+ const token_hash = searchParams.get('token_hash')
+ const type = searchParams.get('type') as EmailOtpType | null
+ const next = searchParams.get('next') ?? '/'
+
+ const redirectTo = request.nextUrl.clone()
+ redirectTo.pathname = next
+ redirectTo.searchParams.delete('token_hash')
+ redirectTo.searchParams.delete('type')
+
+ if (token_hash && type) {
+ const supabase = createClient(cookieStore)
+
+ const { error } = await supabase.auth.verifyOtp({
+ type,
+ token_hash,
+ })
+ if (!error) {
+ redirectTo.searchParams.delete('next')
+ return NextResponse.redirect(redirectTo)
+ }
+ }
+
+ // return the user to an error page with some instructions
+ redirectTo.pathname = '/error'
+ return NextResponse.redirect(redirectTo)
+}
+```
+
+
+
+
+
+
+
+
+
+Server Components can read cookies, so you can get the Auth status and user info.
+
+Since you're calling Supabase from a Server Component, use the client created in `@/utils/supabase/server.ts`.
+
+Create a `private` page that users can only access if they're logged in. The page displays their email.
+
+
+
+Be careful when protecting pages. The server gets the user session from the cookies, which can be spoofed by anyone.
+
+Always use `supabase.auth.getUser()` to protect pages and user data.
+
+_Never_ trust `supabase.auth.getSession()` inside Server Components. It isn't guaranteed to revalidate the Auth token.
+
+It's safe to trust `getUser()` because it sends a request to the Supabase Auth server every time to revalidate the Auth token.
+
+
+
+
+
+
+
+```ts app/private/page.tsx
+import { cookies } from 'next/headers'
+import { redirect } from 'next/navigation'
+
+import { createClient } from '@/utils/supabase/server'
+
+export default async function PrivatePage() {
+ const cookieStore = cookies()
+ const supabase = createClient(cookieStore)
+
+ const { data, error } = await supabase.auth.getUser()
+ if (error || !data?.user) {
+ redirect('/')
+ }
+
+ return
Hello {data.user.email}
+}
+```
+
+
+
+
+
+
+
+## Congratulations
+
+You're done! To recap, you've successfully:
+
+- Called Supabase from a Server Action.
+- Called Supabase from a Server Component.
+- Set up a Supabase client utility to call Supabase from a Client Component. You can use this if you need to call Supabase from a Client Component, for example to set up a realtime subscription.
+- Set up middleware to automatically refresh the Supabase Auth session.
+
+You can now use any Supabase features from your client or server code!
+
+## Troubleshooting
+
+
+
+ Getting the error DynamicServerError: Dynamic server usage: cookies}
+ id="troubleshooting-error-dynamic-cookies"
+ >
+ This means Next.js has failed to detect that the route is dynamic until the `cookies` function is called. To fix this, make sure you call the `cookies` function directly in your Server Component, instead of abstracting it out.
+
+ Alternatively, you can mark the route as dynamic using `export const dynamic = 'force-dynamic'`.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Install the `@supabase/supabase-js` package and the helper `@supabase/ssr` package.
+
+
+
+
+
+```sh
+npm install @supabase/supabase-js @supabase/ssr
+```
+
+
+
+
+
+
+
+
+
+Create a `.env.local` file in your project root directory.
+
+Fill in your `NEXT_PUBLIC_SUPABASE_URL` and `NEXT_PUBLIC_SUPABASE_ANON_KEY`:
+
+
+
+
+
+
+
+
+```txt .env.local
+NEXT_PUBLIC_SUPABASE_URL=
+NEXT_PUBLIC_SUPABASE_ANON_KEY=
+```
+
+
+
+
+
+
+
+
+
+To access Supabase from your Next.js app, you need 4 types of Supabase clients:
+
+1. **`getServerSideProps` client** - To access Supabase from `getServerSideProps`.
+1. **`getStaticProps` client** - To access Supabase from `getStaticProps`.
+1. **Component client** - To access Supabase from within components.
+1. **API route client** - To access Supabase from API route handlers.
+
+Create a `utils/supabase` folder with a file for each type of client. Then copy the utility functions for each client type.
+
+
+
+ Why do I need so many types of clients?}
+ id="nextjs-clients"
+ >
+
+ A Supabase client reads and sets cookies in order to access and update the user session. Depending on where the client is used, it needs to interact with cookies in a different way:
+
+ - **`getServerSideProps`** - Runs on the server. Reads cookies from the request, which is passed through from `GetServerSidePropsContext`.
+ - **`getStaticProps`** - Runs at build time, where there is no user, session, or cookies.
+ - **Component** - Runs on the client. Reads cookies from browser storage. Behind the scenes, `createBrowserClient` reuses the same client instance if called multiple times, so don't worry about deduplicating the client yourself.
+ - **API route** - Runs on the server. Reads cookies from the request, which is passed through from `NextApiRequest`.
+
+
+
+
+
+ What does the `cookies` object do?}
+ id="client-storage-cookies"
+ >
+
+ The cookies object lets the Supabase client know how to access the cookies, so it can read and write the user session. To make `@supabase/ssr` framework-agnostic, the cookies methods aren't hard-coded. But you only need to set them up once. You can then reuse your utility functions whenever you need a Supabase client.
+
+
+
+
+
+
+
+
+
+
+
+
+```ts utils/supabase/server-props.ts
+import { createServerClient, type CookieOptions, serialize } from '@supabase/ssr'
+import { type GetServerSidePropsContext } from 'next'
+
+export function createClient(context: GetServerSidePropsContext) {
+ const supabase = createServerClient(
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
+ process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
+ {
+ cookies: {
+ get(name: string) {
+ return context.req.cookies[name]
+ },
+ set(name: string, value: string, options: CookieOptions) {
+ context.res.appendHeader('Set-Cookie', serialize(name, value, options))
+ },
+ remove(name: string, options: CookieOptions) {
+ context.res.appendHeader('Set-Cookie', serialize(name, '', options))
+ },
+ },
+ }
+ )
+
+ return supabase
+}
+```
+
+```ts utils/supabase/static-props.ts
+import { createClient as createClientPrimitive } from '@supabase/supabase-js'
+
+export function createClient() {
+ const supabase = createClientPrimitive(
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
+ process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
+ )
+
+ return supabase
+}
+```
+
+```ts utils/supabase/component.ts
+import { createBrowserClient } from '@supabase/ssr'
+
+export function createClient() {
+ const supabase = createBrowserClient(
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
+ process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
+ )
+
+ return supabase
+}
+```
+
+```ts utils/supabase/api.ts
+import { createServerClient, type CookieOptions, serialize } from '@supabase/ssr'
+import { type NextApiRequest, type NextApiResponse } from 'next'
+
+export default function createClient(req: NextApiRequest, res: NextApiResponse) {
+ const supabase = createServerClient(
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
+ process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
+ {
+ cookies: {
+ get(name: string) {
+ return req.cookies[name]
+ },
+ set(name: string, value: string, options: CookieOptions) {
+ res.appendHeader('Set-Cookie', serialize(name, value, options))
+ },
+ remove(name: string, options: CookieOptions) {
+ res.appendHeader('Set-Cookie', serialize(name, '', options))
+ },
+ },
+ }
+ )
+
+ return supabase
+}
+```
+
+
+
+
+
+
+
+
+
+
+
+Create a login page for your app.
+
+Since Supabase is being called from a component, use the client defined in `@/utils/supabase/component.ts`.
+
+
+
+
+
+
+
+```ts pages/login.tsx
+import { useRouter } from 'next/router'
+import { useState } from 'react'
+
+import { createClient } from '@/utils/supabase/component'
+
+export default function LoginPage() {
+ const router = useRouter()
+ const supabase = createClient()
+
+ const [email, setEmail] = useState('')
+ const [password, setPassword] = useState('')
+
+ async function logIn() {
+ const { error } = await supabase.auth.signInWithPassword({ email, password })
+ if (error) {
+ console.error(error)
+ }
+ router.push('/')
+ }
+
+ async function signUp() {
+ const { error } = await supabase.auth.signUp({ email, password })
+ if (error) {
+ console.error(error)
+ }
+ router.push('/')
+ }
+
+ return (
+
+
+
+ )
+}
+```
+
+
+
+
+
+
+
+
+
+
+
+If you have email confirmation turned on (the default), a new user will receive an email confirmation after signing up.
+
+Change the email template to support a server-side authentication flow.
+
+Go to the [Auth templates](https://supabase.com/dashboard/project/_/auth/templates) page in your dashboard. In each email template, change `{{ .ConfirmationURL }}` to `{{ .SiteURL }}/api/auth/confirm?token_hash={{ .TokenHash }}&type=signup`.
+
+
+
+
+
+
+
+
+
+Create an API route for `api/auth/confirm`. When a user clicks their confirmation email link, exchange their secure code for an Auth token.
+
+Since this is an API route, use the Supabase client from `@/utils/supabase/api.ts`.
+
+
+
+
+
+
+
+```ts pages/api/auth/confirm.tsx
+import { type EmailOtpType } from '@supabase/supabase-js'
+import type { NextApiRequest, NextApiResponse } from 'next'
+
+import { createClient } from '@/utils/supabase/api'
+
+function stringOrFirstString(item: string | string[] | undefined) {
+ return Array.isArray(item) ? item[0] : item
+}
+
+export default async function handler(req: NextApiRequest, res: NextApiResponse) {
+ if (req.method !== 'GET') {
+ res.status(405).appendHeader('Allow', 'GET').end()
+ return
+ }
+
+ const queryParams = req.query
+ const token_hash = stringOrFirstString(queryParams.token_hash)
+ const type = stringOrFirstString(queryParams.type)
+
+ let next = '/error'
+
+ if (token_hash && type) {
+ const supabase = createClient(req, res)
+ const { error } = await supabase.auth.verifyOtp({
+ type: type as EmailOtpType,
+ token_hash,
+ })
+ if (error) {
+ console.error(error)
+ } else {
+ next = stringOrFirstString(queryParams.next) || '/'
+ }
+ }
+
+ res.redirect(next)
+}
+```
+
+```tsx pages/error.tsx
+export default function ErrorPage() {
+ return
Sorry, something went wrong
+}
+```
+
+
+
+
+
+
+
+
+
+
+
+If you use dynamic server-side rendering, you can serve a page to authenticated users only by checking for the user data in `getServerSideProps`. Unauthenticated users will be redirected to the home page.
+
+Since you're calling Supabse from `getServerSideProps`, use the client from `@/utils/supabase/server-props.ts`.
+
+
+
+Be careful when protecting pages. The server gets the user session from the cookies, which can be spoofed by anyone.
+
+Always use `supabase.auth.getUser()` to protect pages and user data.
+
+_Never_ trust `supabase.auth.getSession()` inside server code. It isn't guaranteed to revalidate the Auth token.
+
+It's safe to trust `getUser()` because it sends a request to the Supabase Auth server every time to revalidate the Auth token.
+
+
+
+
+
+
+
+```ts pages/private.tsx
+import type { User } from '@supabase/supabase-js'
+import type { GetServerSidePropsContext } from 'next'
+
+import { createClient } from '@/utils/supabase/server-props'
+
+export default function PrivatePage({ user }: { user: User }) {
+ return
Hello, {user.email || 'user'}!
+}
+
+export async function getServerSideProps(context: GetServerSidePropsContext) {
+ const supabase = createClient(context)
+
+ const { data, error } = await supabase.auth.getUser()
+
+ if (error || !data) {
+ return {
+ redirect: {
+ destination: '/',
+ permanent: false,
+ },
+ }
+ }
+
+ return {
+ props: {
+ user: data.user,
+ },
+ }
+}
+```
+
+
+
+
+
+
+
+
+
+You can also fetch static data at build time using Supabase. Note that there's no session or user at build time, so the data will be the same for everyone who sees the page.
+
+Add some countries data to your database by running the [Countries Quickstart](https://supabase.com/dashboard/project/_/sql/quickstarts) in the dashboard.
+
+Then fetch the countries data using `getStaticProps` with the client from `@/utils/supabase/static-props.ts`.
+
+
+
+
+
+```ts pages/public.tsx
+import { createClient } from '@/utils/supabase/static-props'
+
+export default function PublicPage({ data }: { data?: any[] }) {
+ return
{data && JSON.stringify(data, null, 2)}
+}
+
+export async function getStaticProps() {
+ const supabase = createClient()
+
+ const { data, error } = await supabase.from('countries').select()
+
+ if (error || !data) {
+ return { props: {} }
+ }
+
+ return { props: { data } }
+}
+```
+
+
+
+
+
+
+
+## Congratulations
+
+You're done! To recap, you've successfully:
+
+- Called Supabase from a component
+- Called Supabase from an API route
+- Called Supabase from `getServerSideProps`
+- Called Supabase from `getStaticProps`
+
+You can now use any Supabase features from your client or server code!
+
+
+
+
+
+You can use both the App and Pages Routers together.
+
+Follow the instructions for both the App and Pages Routers. Whenever you need to connect to Supabase, import the `createClient` utility that you need:
+
+| Router | Code location | Which `createClient` to use |
+| ------------ | ------------------------------------------------- | --------------------------- |
+| App Router | Server Component, Server Action, or Route Handler | `server.ts` |
+| | Client Component | `client.ts` |
+| Pages Router | `getServerSideProps` | `server-props.ts` |
+| | `getStaticProps` | `static-props.ts` |
+| | Component | `component.ts` |
+| | API route | `api.ts` |
+
+Remember to create the `middleware.ts` file for the App Router so the session refreshes for App Router pages.
+
+
+
+
diff --git a/apps/docs/pages/guides/auth/server-side/oauth-with-pkce-flow-for-ssr.mdx b/apps/docs/content/guides/auth/server-side/oauth-with-pkce-flow-for-ssr.mdx
similarity index 92%
rename from apps/docs/pages/guides/auth/server-side/oauth-with-pkce-flow-for-ssr.mdx
rename to apps/docs/content/guides/auth/server-side/oauth-with-pkce-flow-for-ssr.mdx
index 884460b3c92..9ff80b227e0 100644
--- a/apps/docs/pages/guides/auth/server-side/oauth-with-pkce-flow-for-ssr.mdx
+++ b/apps/docs/content/guides/auth/server-side/oauth-with-pkce-flow-for-ssr.mdx
@@ -1,12 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- title: 'OAuth with PKCE flow for SSR',
- description:
- 'Learn how to configure OAuth authentication in your server-side rendering (SSR) application to work with the PKCE flow.',
- subtitle:
- 'Learn how to configure OAuth authentication in your server-side rendering (SSR) application to work with the PKCE flow.',
-}
+---
+title: 'OAuth with PKCE flow for SSR'
+description: 'Learn how to configure OAuth authentication in your server-side rendering (SSR) application to work with the PKCE flow.'
+subtitle: 'Learn how to configure OAuth authentication in your server-side rendering (SSR) application to work with the PKCE flow.'
+---
### Setting up SSR client
@@ -219,7 +215,3 @@ await supabase.auth.signInWithOAuth({
},
})
```
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/server-side/overview.mdx b/apps/docs/content/guides/auth/server-side/overview.mdx
similarity index 58%
rename from apps/docs/pages/guides/auth/server-side/overview.mdx
rename to apps/docs/content/guides/auth/server-side/overview.mdx
index 18e4c186f9a..eb2d1c1c9d8 100644
--- a/apps/docs/pages/guides/auth/server-side/overview.mdx
+++ b/apps/docs/content/guides/auth/server-side/overview.mdx
@@ -1,21 +1,27 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'index',
- title: 'Server-Side Auth Overview',
- description: 'Configure Supabase Auth to use Cookies',
- sidebar_label: 'Overview',
-}
+---
+id: 'index'
+title: 'Server-Side Auth Overview'
+description: 'Configure Supabase Auth to use Cookies'
+sidebar_label: 'Overview'
+---
When using Supabase with server-side languages and frameworks - such as Next.js, SvelteKit and Remix - it is important to configure your Supabase client to use cookies for storing user sessions. We have developed an `@supabase/ssr` package to make this process as simple as possible. This package is currently in `beta`. Adoption is recommended but be aware that the API is still unstable and may have breaking changes in the future.
## Framework quickstarts
-
- {quickstarts.map((item) => {
+
+ {[
+ {
+ title: 'Next.js',
+ href: '/guides/auth/server-side/nextjs',
+ description:
+ 'Automatically configure Supabase to use cookies, making your user and their session available on the client and server.',
+ icon: '/docs/img/icons/nextjs-icon',
+ },
+ ].map((item) => {
return (
-
-
+
+
{item.description}
@@ -35,17 +41,3 @@ If you're currently using the [Auth Helpers package](https://github.com/supabase
- [Email Auth with PKCE flow for SSR](/docs/guides/auth/server-side/email-based-auth-with-pkce-flow-for-ssr)
- [OAuth with PKCE flow for SSR](/docs/guides/auth/server-side/oauth-with-pkce-flow-for-ssr)
- [Learn more about SSR](/docs/guides/auth/server-side-rendering)
-
-export const quickstarts = [
- {
- title: 'Next.js',
- href: '/guides/auth/quickstarts/nextjs',
- description:
- 'Automatically configure Supabase to use cookies, making your user and their session available on the client and server.',
- icon: '/docs/img/icons/nextjs-icon',
- },
-]
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/sessions.mdx b/apps/docs/content/guides/auth/sessions.mdx
similarity index 90%
rename from apps/docs/pages/guides/auth/sessions.mdx
rename to apps/docs/content/guides/auth/sessions.mdx
index 5e8f5fe32d0..15484293d0d 100644
--- a/apps/docs/pages/guides/auth/sessions.mdx
+++ b/apps/docs/content/guides/auth/sessions.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'sessions',
- title: 'User Sessions',
- description: 'Control and manage user sessions.',
-}
+---
+id: 'sessions'
+title: 'User Sessions'
+description: 'Control and manage user sessions.'
+---
Supabase Auth provides fine-grained control over your user's sessions.
@@ -16,9 +14,9 @@ A session is created when a user signs in. By default, it lasts indefinitely and
A session is represented by the Supabase Auth access token in the form of a JWT, and a refresh token which is a unique string.
-Access tokens are designed to be short lived, usually between 5 minutes and 1 hour while refresh tokens never expire but can only be used once. You can exchange a refresh token only once to get a new access and refresh token pair.
+Access tokens are designed to be short lived, usually between 5 minutes and 1 hour while refresh tokens never expire but can only be used once. You can exchange a refresh token only once to get a new access and refresh token pair.
-This process is called **refreshing the session.**
+This process is called **refreshing the session.**
A session terminates, depending on configuration, when:
@@ -54,7 +52,7 @@ Upon sign out, all refresh tokens and potentially other database objects related
-Access tokens of revoked sessions remain valid until their expiry time, encoded in the `exp` claim. The user won't be immediately logged out and will only be logged out when the access token expires.
+Access tokens of revoked sessions remain valid until their expiry time, encoded in the `exp` claim. The user won't be immediately logged out and will only be logged out when the access token expires.
@@ -74,7 +72,7 @@ There are three ways to limit the lifetime of a session:
- Time-boxed sessions, which terminate after a fixed amount of time.
- Set an inactivity timeout, which terminates sessions that haven't been refreshed within the timeout duration.
-- Enforce a single-session per user, which only keeps the most recently active session.
+- Enforce a single-session per user, which only keeps the most recently active session.
To make sure that users are required to re-authenticate periodically, you can set a positive value for the **Time-box user sessions** option in the [Auth settings](/dashboard/project/_/settings/auth) for your project.
@@ -82,7 +80,7 @@ To make sure that sessions expire after a period of inactivity, you can set a po
You can also enforce only one active session per user per device or browser. When this is enabled, the session from the most recent sign in will remain active, while the rest are terminated. Enable this via the _Single session per user_ option in the [Auth settings](/dashboard/project/_/settings/auth).
-Sessions are not proactively destroyed when you change these settings, but rather the check is enforced whenever a session is refreshed next. This can confuse developers because the actual druation of a session is the configured timeout plus the JWT expiration time. For single session per user, the effect will only be noticed at intervals of the JWT expiration time. Please make sure you adjust this setting depending on your needs. We do not recommend going below 5 minutes for the JWT expiration time.
+Sessions are not proactively destroyed when you change these settings, but rather the check is enforced whenever a session is refreshed next. This can confuse developers because the actual duration of a session is the configured timeout plus the JWT expiration time. For single session per user, the effect will only be noticed at intervals of the JWT expiration time. Please make sure you adjust this setting depending on your needs. We do not recommend going below 5 minutes for the JWT expiration time.
Otherwise sessions are progressively deleted from the database 24 hours after they expire, which prevents you from causing a high load on your project by accident and allows you some freedom to undo changes without adversely affecting all users.
@@ -108,11 +106,11 @@ As your users continue using your app, refresh tokens are being constantly excha
The general rule is that a refresh token can only be used once. However, strictly enforcing this can cause certain issues to arise. There are two exceptions to this design to prevent the early and unexpected termination of user's sessions:
- A refresh token can be used more than once within a defined reuse interval. By default this is 10 seconds and we do not recommend changing this value. This exception is granted for legitimate situations such as:
- - Using server-side rendering where the same refresh token needs to be reused on the server and soon after on the client
- - To allow some leeway for bugs or issues with serializing access to the refresh token request
+ - Using server-side rendering where the same refresh token needs to be reused on the server and soon after on the client
+ - To allow some leeway for bugs or issues with serializing access to the refresh token request
- If the parent of the currently active refresh token for the user's session is being used, the active token will be returned. This exception solves an important and often common situation:
- - All clients such as browsers, mobile or desktop apps, and even some servers are inherently unreliable due to network issues. A request does not indicate that they received a response or even processed the response they received.
- - If a refresh token is revoked after being used only once, and the response wasn't received and processed by the client, when the client comes back online, it will attempt to use the refresh token that was already used. Since this might happen outside of the reuse interval, it can cause sudden and unexpected session termination.
+ - All clients such as browsers, mobile or desktop apps, and even some servers are inherently unreliable due to network issues. A request does not indicate that they received a response or even processed the response they received.
+ - If a refresh token is revoked after being used only once, and the response wasn't received and processed by the client, when the client comes back online, it will attempt to use the refresh token that was already used. Since this might happen outside of the reuse interval, it can cause sudden and unexpected session termination.
Should the reuse attempt not fall under these two exceptions, the whole session is regarded as terminated and all refresh tokens belonging to it are marked as revoked. You can disable this behavior in the Advanced Settings of the [Auth settings](/dashboard/project/_/settings/auth) page, though it is generally not recommended.
@@ -161,7 +159,3 @@ const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {
The `customStorageObject` should implement the `getItem`, `setItem`, and `removeItem` methods from the [`Storage` interface](https://developer.mozilla.org/en-US/docs/Web/API/Storage). Async versions of these methods are also supported.
When using cookies to store access and refresh tokens, make sure that the [`Expires` or `Max-Age` attributes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#attributes) of the cookies is set to a timestamp very far into the future. Browsers will clear the cookies, but the session will remain active in Supabase Auth. Therefore it's best to let Supabase Auth control the validity of these tokens and instruct the browser to always store the cookies indefinitely.
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/social-login.mdx b/apps/docs/content/guides/auth/social-login.mdx
similarity index 77%
rename from apps/docs/pages/guides/auth/social-login.mdx
rename to apps/docs/content/guides/auth/social-login.mdx
index f5e9b16a66c..73b1f211573 100644
--- a/apps/docs/pages/guides/auth/social-login.mdx
+++ b/apps/docs/content/guides/auth/social-login.mdx
@@ -1,12 +1,7 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-import { IconPanel } from 'ui'
-import Link from 'next/link'
-import { SocialLoginItems } from '~/components/Navigation/NavigationMenu/NavigationMenu.constants'
-
-export const meta = {
- title: 'Social Login',
- description: 'Logging in with social accounts',
-}
+---
+title: 'Social Login'
+description: 'Logging in with social accounts'
+---
Social Login (OAuth) is an open standard for authentication that allows users to log in to one website or application using their credentials from another website or application. OAuth allows users to grant third-party applications access to their online accounts without sharing their passwords.
OAuth is commonly used for things like logging in to a social media account from a third-party app. It is a secure and convenient way to authenticate users and share information between applications.
@@ -26,32 +21,37 @@ There are several reasons why you might want to add social login to your applica
Supabase supports a suite of social providers. Follow these guides to configure a social provider for your platform.
## Provider tokens
-
-You can use the provider token and provider refresh token returned to make API calls to the OAuth provider. For example, you can use the Google provider token to access Google APIs on behalf of your user.
+
+You can use the provider token and provider refresh token returned to make API calls to the OAuth provider. For example, you can use the Google provider token to access Google APIs on behalf of your user.
Supabase Auth does not manage refreshing the provider token for the user. Your application will need to use the provider refresh token to obtain a new provider token. If no provider refresh token is returned, then it could mean one of the following:
+
- The OAuth provider does not return a refresh token
- Additional scopes need to be specified in order for the OAuth provider to return a refresh token.
-
+
Provider tokens are intentionally not stored in your project's database. This is because provider tokens give access to potentially sensitive user data in third-party systems. Different applications have different needs, and one application's OAuth scopes may be significantly more permissive than another. If you want to use the provider token outside of the browser that completed the OAuth flow, it is recommended to send it to a trusted and secure server you control.
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/social-login/auth-apple.mdx b/apps/docs/content/guides/auth/social-login/auth-apple.mdx
similarity index 83%
rename from apps/docs/pages/guides/auth/social-login/auth-apple.mdx
rename to apps/docs/content/guides/auth/social-login/auth-apple.mdx
index d121be46da3..ade47b772e3 100644
--- a/apps/docs/pages/guides/auth/social-login/auth-apple.mdx
+++ b/apps/docs/content/guides/auth/social-login/auth-apple.mdx
@@ -1,12 +1,9 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-import AppleSecretGenerator from '~/components/AppleSecretGenerator'
-
-export const meta = {
- id: 'auth-apple',
- title: 'Login with Apple',
- description: 'Use Sign in with Apple with Supabase',
- tocVideo: '-tpcZzTdvN0',
-}
+---
+id: 'auth-apple'
+title: 'Login with Apple'
+description: 'Use Sign in with Apple with Supabase'
+tocVideo: '-tpcZzTdvN0'
+---
Supabase Auth supports using [Sign in with Apple](https://developer.apple.com/sign-in-with-apple/) on the web and in native apps for iOS, macOS, watchOS or tvOS.
@@ -200,9 +197,9 @@ When developing with Expo, you can test Sign in with Apple via the Expo Go app,
- ## Using native sign in with Apple in Flutter
+ ## Apple sign in on iOS and macOS
- You can perform Apple sign in using the [sign_in_with_apple](https://pub.dev/packages/sign_in_with_apple) package on Flutter.
+ You can perform Apple sign in using the [sign_in_with_apple](https://pub.dev/packages/sign_in_with_apple) package on Flutter apps running on iOS or macOS.
Follow the instructions in the package README to set up native Apple sign in on iOS and macOS.
Once the setup is complete on the Flutter app, add the bundle ID of your app to your Supabase dashboard in `Authentication -> Providers -> Apple` in order to register your app with Supabase.
@@ -249,6 +246,32 @@ When developing with Expo, you can test Sign in with Apple via the Expo Go app,
+ ## Apple sign in on Android, Web, Windows and Linux
+
+ For platforms that doesn't support native Apple sign in, you can use the `signInWithOAuth()` method to perform the Apple sign in.
+ This method of signing in is web based, and will open a browser window to perform the sign in. For non-web platforms, the user is brought back to the app via [deep linking](/docs/guides/auth/native-mobile-deep-linking?platform=flutter).
+
+ ```dart
+ supabase.auth.signInWithOAuth(
+ OAuthProvider.apple,
+ redirectTo: 'my-scheme://login-callback',
+ );
+ ```
+
+ This call takes the user to Apple's consent screen. Once the flow ends, the user's profile information is exchanged and validated with Supabase Auth before it redirects back to your Flutter application with an access and refresh token representing the user's session.
+
+ ### Configuration [#flutter-configuration-web]
+
+ You will require the following information:
+
+ 1. Your Apple Developer account's **Team ID**, which is an alphanumeric string of 10 characters that uniquely identifies the developer of the app. It's often easily accessible in the upper right-side menu on the Apple Developer Console.
+ 2. Register email sources for _Sign in with Apple for Email Communication_ which can be found in the [Services](https://developer.apple.com/account/resources/services/list) section of the Apple Developer Console.
+ 3. An **App ID** which uniquely identifies the app you are building. You can create a new App ID from the [Identifiers](https://developer.apple.com/account/resources/identifiers/list/bundleId) section in the Apple Developer Console (use the filter menu in the upper right side to see all App IDs). These usually are a reverse domain name string, for example `com.example.app`. Make sure you configure Sign in with Apple once you create an App ID in the Capabilities list. At this time Supabase Auth does not support Server-to-Server notification endpoints, so you should leave that setting blank. (In the past App IDs were referred to as _bundle IDs._)
+ 4. A **Services ID** which uniquely identifies the web services provided by the app you registered in the previous step. You can create a new Services ID from the [Identifiers](https://developer.apple.com/account/resources/identifiers/list/serviceId) section in the Apple Developer Console (use the filter menu in the upper right side to see all Services IDs). These usually are a reverse domain name string, for example `com.example.app.web`.
+ 5. Configure Website URLs for the newly created **Services ID**. The web domain you should use is the domain your Supabase project is hosted on. This is usually `.supabase.co` while the redirect URL is `https://.supabase.co/auth/v1/callback`.
+ 6. Create a signing **Key** in the [Keys](https://developer.apple.com/account/resources/authkeys/list) section of the Apple Developer Console. You can use this key to generate a secret key using the tool below, which is added to your Supabase project's Auth configuration. Make sure you safely store the `AuthKey_XXXXXXXXXX.p8` file. If you ever lose access to it, or make it public accidentally please revoke it from the Apple Developer Console and create a new one immediately. You will have to generate a new secret key using this file every 6 months, so make sure you schedule a recurring reminder in your calendar!
+ 7. Finally, add the information you configured above to the [Apple provider configuration in the Supabase dashboard](https://supabase.com/dashboard/project/_/auth/providers).
+
@@ -352,7 +375,3 @@ When developing with Expo, you can test Sign in with Apple via the Expo Go app,
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/social-login/auth-azure.mdx b/apps/docs/content/guides/auth/social-login/auth-azure.mdx
similarity index 96%
rename from apps/docs/pages/guides/auth/social-login/auth-azure.mdx
rename to apps/docs/content/guides/auth/social-login/auth-azure.mdx
index 1fde454fc36..df8831ccc13 100644
--- a/apps/docs/pages/guides/auth/social-login/auth-azure.mdx
+++ b/apps/docs/content/guides/auth/social-login/auth-azure.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-azure',
- title: 'Login with Azure (Microsoft)',
- description: 'Add Azure (Microsoft) OAuth to your Supabase project',
-}
+---
+id: 'auth-azure'
+title: 'Login with Azure (Microsoft)'
+description: 'Add Azure (Microsoft) OAuth to your Supabase project'
+---
To enable Azure (Microsoft) Auth for your project, you need to set up an Azure OAuth application and add the application credentials to your Supabase Dashboard.
@@ -103,6 +101,8 @@ A Microsoft Entra tenant is the directory of users who are allowed to access you
By default, Supabase Auth uses the _common_ Microsoft tenant (`https://login.microsoftonline.com/common`) which generally allows any Microsoft account to sign in to your project. Microsoft Entra further limits what accounts can access your project depending on the type of OAuth application you registered.
+If your app is registered as _Personal Microsoft accounts only_ for the _Supported account types_ set Microsoft tenant to _consumers_ (`https://login.microsoftonline.com/consumers`).
+
If your app is registered as _My organization only_ for the _Supported account types_ you may want to configure Supabase Auth with the organization's tenant URL. This will use the tenant's authorization flows instead, and will limit access at the Supabase Auth level to Microsoft accounts arising from only the specified tenant.
Configure this by storing a value under _Azure Tenant URL_ in the Supabase Auth provider configuration page for Azure that has the following format `https://login.microsoftonline.com/`.
@@ -227,7 +227,3 @@ suspend fun signInWithAzure() {
- [Azure Developer Account](https://portal.azure.com)
- [GitHub Discussion](https://github.com/supabase/gotrue/pull/54#issuecomment-757043573)
- [Potential Risk of Privilege Escalation in Azure AD Applications](https://msrc.microsoft.com/blog/2023/06/potential-risk-of-privilege-escalation-in-azure-ad-applications/)
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/social-login/auth-bitbucket.mdx b/apps/docs/content/guides/auth/social-login/auth-bitbucket.mdx
similarity index 91%
rename from apps/docs/pages/guides/auth/social-login/auth-bitbucket.mdx
rename to apps/docs/content/guides/auth/social-login/auth-bitbucket.mdx
index a0284543d47..1cdde00d182 100644
--- a/apps/docs/pages/guides/auth/social-login/auth-bitbucket.mdx
+++ b/apps/docs/content/guides/auth/social-login/auth-bitbucket.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-bitbucket',
- title: 'Login with Bitbucket',
- description: 'Add Bitbucket OAuth to your Supabase project',
-}
+---
+id: 'auth-bitbucket'
+title: 'Login with Bitbucket'
+description: 'Add Bitbucket OAuth to your Supabase project'
+---
To enable Bitbucket Auth for your project, you need to set up a BitBucket OAuth application and add the application credentials to your Supabase Dashboard.
@@ -117,7 +115,3 @@ suspend fun signOut() {
- [Supabase Account - Free Plan OK](https://supabase.com)
- [Supabase JS Client](https://github.com/supabase/supabase-js)
- [Bitbucket Account](https://bitbucket.org)
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/social-login/auth-discord.mdx b/apps/docs/content/guides/auth/social-login/auth-discord.mdx
similarity index 91%
rename from apps/docs/pages/guides/auth/social-login/auth-discord.mdx
rename to apps/docs/content/guides/auth/social-login/auth-discord.mdx
index 043234a76e5..1c15e17249e 100644
--- a/apps/docs/pages/guides/auth/social-login/auth-discord.mdx
+++ b/apps/docs/content/guides/auth/social-login/auth-discord.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-discord',
- title: 'Login with Discord',
- description: 'Add Discord OAuth to your Supabase project',
-}
+---
+id: 'auth-discord'
+title: 'Login with Discord'
+description: 'Add Discord OAuth to your Supabase project'
+---
To enable Discord Auth for your project, you need to set up a Discord Application and add the Application OAuth credentials to your Supabase Dashboard.
@@ -119,7 +117,3 @@ suspend fun signOut() {
- [Supabase JS Client](https://github.com/supabase/supabase-js)
- [Discord Account](https://discord.com)
- [Discord Developer Portal](https://discord.com/developers)
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/social-login/auth-facebook.mdx b/apps/docs/content/guides/auth/social-login/auth-facebook.mdx
similarity index 93%
rename from apps/docs/pages/guides/auth/social-login/auth-facebook.mdx
rename to apps/docs/content/guides/auth/social-login/auth-facebook.mdx
index 46e9d05ccb7..b195edf22d2 100644
--- a/apps/docs/pages/guides/auth/social-login/auth-facebook.mdx
+++ b/apps/docs/content/guides/auth/social-login/auth-facebook.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-facebook',
- title: 'Login with Facebook',
- description: 'Add Facebook OAuth to your Supabase project',
-}
+---
+id: 'auth-facebook'
+title: 'Login with Facebook'
+description: 'Add Facebook OAuth to your Supabase project'
+---
To enable Facebook Auth for your project, you need to set up a Facebook OAuth application and add the application credentials to your Supabase Dashboard.
@@ -136,7 +134,3 @@ You can read more about App Review [here](https://developers.facebook.com/docs/a
- [Supabase Account - Free Plan OK](https://supabase.com)
- [Supabase JS Client](https://github.com/supabase/supabase-js)
- [Facebook Developers Dashboard](https://developers.facebook.com/)
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/social-login/auth-figma.mdx b/apps/docs/content/guides/auth/social-login/auth-figma.mdx
similarity index 91%
rename from apps/docs/pages/guides/auth/social-login/auth-figma.mdx
rename to apps/docs/content/guides/auth/social-login/auth-figma.mdx
index 6e9633a8313..0db6671df23 100644
--- a/apps/docs/pages/guides/auth/social-login/auth-figma.mdx
+++ b/apps/docs/content/guides/auth/social-login/auth-figma.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-figma',
- title: 'Login with Figma',
- description: 'Add Figma OAuth to your Supabase project',
-}
+---
+id: 'auth-figma'
+title: 'Login with Figma'
+description: 'Add Figma OAuth to your Supabase project'
+---
To enable Figma Auth for your project, you need to set up a Figma OAuth application and add the application credentials to your Supabase Dashboard.
@@ -117,7 +115,3 @@ suspend fun signOut() {
- [Supabase Account - Free Plan OK](https://supabase.com)
- [Supabase JS Client](https://github.com/supabase/supabase-js)
- [Figma Developers page](https://www.figma.com/developers)
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/social-login/auth-github.mdx b/apps/docs/content/guides/auth/social-login/auth-github.mdx
similarity index 92%
rename from apps/docs/pages/guides/auth/social-login/auth-github.mdx
rename to apps/docs/content/guides/auth/social-login/auth-github.mdx
index aba15f2401d..c0ffc5e8f04 100644
--- a/apps/docs/pages/guides/auth/social-login/auth-github.mdx
+++ b/apps/docs/content/guides/auth/social-login/auth-github.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-github',
- title: 'Login with GitHub',
- description: 'Add GitHub OAuth to your Supabase project',
-}
+---
+id: 'auth-github'
+title: 'Login with GitHub'
+description: 'Add GitHub OAuth to your Supabase project'
+---
To enable GitHub Auth for your project, you need to set up a GitHub OAuth application and add the application credentials to your Supabase Dashboard.
@@ -128,7 +126,3 @@ suspend fun signOut() {
- [Supabase Account - Free Plan OK](https://supabase.com)
- [Supabase JS Client](https://github.com/supabase/supabase-js)
- [GitHub Developer Settings](https://github.com/settings/developers)
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/social-login/auth-gitlab.mdx b/apps/docs/content/guides/auth/social-login/auth-gitlab.mdx
similarity index 91%
rename from apps/docs/pages/guides/auth/social-login/auth-gitlab.mdx
rename to apps/docs/content/guides/auth/social-login/auth-gitlab.mdx
index c08e3c33ab7..6dd71afa9be 100644
--- a/apps/docs/pages/guides/auth/social-login/auth-gitlab.mdx
+++ b/apps/docs/content/guides/auth/social-login/auth-gitlab.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-gitlab',
- title: 'Login with GitLab',
- description: 'Add GitLab OAuth to your Supabase project',
-}
+---
+id: 'auth-gitlab'
+title: 'Login with GitLab'
+description: 'Add GitLab OAuth to your Supabase project'
+---
To enable GitLab Auth for your project, you need to set up a GitLab OAuth application and add the application credentials to your Supabase Dashboard.
@@ -114,7 +112,3 @@ suspend fun signOut() {
- [Supabase Account - Free Plan OK](https://supabase.com)
- [Supabase JS Client](https://github.com/supabase/supabase-js)
- [GitLab Account](https://gitlab.com)
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/social-login/auth-google.mdx b/apps/docs/content/guides/auth/social-login/auth-google.mdx
similarity index 98%
rename from apps/docs/pages/guides/auth/social-login/auth-google.mdx
rename to apps/docs/content/guides/auth/social-login/auth-google.mdx
index 09556ea8ba4..38f6936b717 100644
--- a/apps/docs/pages/guides/auth/social-login/auth-google.mdx
+++ b/apps/docs/content/guides/auth/social-login/auth-google.mdx
@@ -1,11 +1,9 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-google',
- title: 'Login with Google',
- description: 'Use Sign in with Google on the web, in native apps or with Chrome extensions',
- tocVideo: 'vojHmGUGUGc',
-}
+---
+id: 'auth-google'
+title: 'Login with Google'
+description: 'Use Sign in with Google on the web, in native apps or with Chrome extensions'
+tocVideo: 'vojHmGUGUGc'
+---
Supabase Auth supports Sign in with Google on the web, native Android applications and Chrome extensions.
@@ -424,7 +422,3 @@ Before you can use Sign in with Google, you need to obtain a [Google Cloud Platf
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/social-login/auth-kakao.mdx b/apps/docs/content/guides/auth/social-login/auth-kakao.mdx
similarity index 93%
rename from apps/docs/pages/guides/auth/social-login/auth-kakao.mdx
rename to apps/docs/content/guides/auth/social-login/auth-kakao.mdx
index c80537d176b..f838a83641e 100644
--- a/apps/docs/pages/guides/auth/social-login/auth-kakao.mdx
+++ b/apps/docs/content/guides/auth/social-login/auth-kakao.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-kakao',
- title: 'Login with Kakao',
- description: 'Add Kakao OAuth to your Supabase project',
-}
+---
+id: 'auth-kakao'
+title: 'Login with Kakao'
+description: 'Add Kakao OAuth to your Supabase project'
+---
To enable Kakao Auth for your project, you need to set up an Kakao OAuth application and add the application credentials to your Supabase Dashboard.
@@ -137,7 +135,3 @@ suspend fun signOut() {
## Resources
- [Kakao Developers Portal](https://developers.kakao.com).
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/social-login/auth-keycloak.mdx b/apps/docs/content/guides/auth/social-login/auth-keycloak.mdx
similarity index 94%
rename from apps/docs/pages/guides/auth/social-login/auth-keycloak.mdx
rename to apps/docs/content/guides/auth/social-login/auth-keycloak.mdx
index 7826c312ad5..96cde43b5a3 100644
--- a/apps/docs/pages/guides/auth/social-login/auth-keycloak.mdx
+++ b/apps/docs/content/guides/auth/social-login/auth-keycloak.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-keycloak',
- title: 'Login with Keycloak',
- description: 'Add Keycloak OAuth to your Supabase project',
-}
+---
+id: 'auth-keycloak'
+title: 'Login with Keycloak'
+description: 'Add Keycloak OAuth to your Supabase project'
+---
To enable Keycloak Auth for your project, you need to set up an Keycloak OAuth application and add the application credentials to your Supabase Dashboard.
@@ -136,7 +134,3 @@ suspend fun signOut() {
- You can find the keycloak openid endpoint configuration under the realm settings.

-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/social-login/auth-linkedin.mdx b/apps/docs/content/guides/auth/social-login/auth-linkedin.mdx
similarity index 94%
rename from apps/docs/pages/guides/auth/social-login/auth-linkedin.mdx
rename to apps/docs/content/guides/auth/social-login/auth-linkedin.mdx
index 1383fccdb1e..f6ed6125535 100644
--- a/apps/docs/pages/guides/auth/social-login/auth-linkedin.mdx
+++ b/apps/docs/content/guides/auth/social-login/auth-linkedin.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-linkedin',
- title: 'Login with LinkedIn',
- description: 'Add LinkedIn OAuth to your Supabase project',
-}
+---
+id: 'auth-linkedin'
+title: 'Login with LinkedIn'
+description: 'Add LinkedIn OAuth to your Supabase project'
+---
To enable LinkedIn Auth for your project, you need to set up a LinkedIn OAuth application and add the application credentials to your Supabase Dashboard.
@@ -140,7 +138,3 @@ Do reach out to support if you have any concerns around this change.
- [Supabase Account - Free Plan OK](https://supabase.com)
- [Supabase JS Client](https://github.com/supabase/supabase-js)
- [LinkedIn Developer Dashboard](https://api.LinkedIn.com/apps)
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/social-login/auth-notion.mdx b/apps/docs/content/guides/auth/social-login/auth-notion.mdx
similarity index 92%
rename from apps/docs/pages/guides/auth/social-login/auth-notion.mdx
rename to apps/docs/content/guides/auth/social-login/auth-notion.mdx
index 800e5682792..0c414ab4fdb 100644
--- a/apps/docs/pages/guides/auth/social-login/auth-notion.mdx
+++ b/apps/docs/content/guides/auth/social-login/auth-notion.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-notion',
- title: 'Login with Notion',
- description: 'Add Notion OAuth to your Supabase project',
-}
+---
+id: 'auth-notion'
+title: 'Login with Notion'
+description: 'Add Notion OAuth to your Supabase project'
+---
To enable Notion Auth for your project, you need to set up a Notion Application and add the Application OAuth credentials to your Supabase Dashboard.
@@ -118,7 +116,3 @@ suspend fun signOut() {
- [Supabase JS Client](https://github.com/supabase/supabase-js)
- [Notion Account](https://notion.so)
- [Notion Developer Portal](https://www.notion.so/my-integrations)
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/social-login/auth-slack.mdx b/apps/docs/content/guides/auth/social-login/auth-slack.mdx
similarity index 93%
rename from apps/docs/pages/guides/auth/social-login/auth-slack.mdx
rename to apps/docs/content/guides/auth/social-login/auth-slack.mdx
index 2b9e34f2da7..238b394b9d3 100644
--- a/apps/docs/pages/guides/auth/social-login/auth-slack.mdx
+++ b/apps/docs/content/guides/auth/social-login/auth-slack.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-slack',
- title: 'Login with Slack',
- description: 'Add Slack OAuth to your Supabase project',
-}
+---
+id: 'auth-slack'
+title: 'Login with Slack'
+description: 'Add Slack OAuth to your Supabase project'
+---
To enable Slack Auth for your project, you need to set up a Slack OAuth application and add the application credentials to your Supabase Dashboard.
@@ -135,7 +133,3 @@ suspend fun signOut() {
- [Supabase Account - Free Plan OK](https://supabase.com)
- [Supabase JS Client](https://github.com/supabase/supabase-js)
- [Slack Developer Dashboard](https://api.slack.com/apps)
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/social-login/auth-spotify.mdx b/apps/docs/content/guides/auth/social-login/auth-spotify.mdx
similarity index 83%
rename from apps/docs/pages/guides/auth/social-login/auth-spotify.mdx
rename to apps/docs/content/guides/auth/social-login/auth-spotify.mdx
index a4647b8c554..c74d07bb473 100644
--- a/apps/docs/pages/guides/auth/social-login/auth-spotify.mdx
+++ b/apps/docs/content/guides/auth/social-login/auth-spotify.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-spotify',
- title: 'Login with Spotify',
- description: 'Add Spotify OAuth to your Supabase project',
-}
+---
+id: 'auth-spotify'
+title: 'Login with Spotify'
+description: 'Add Spotify OAuth to your Supabase project'
+---
To enable Spotify Auth for your project, you need to set up a Spotify OAuth application and add the application credentials to your Supabase Dashboard.
@@ -52,6 +50,14 @@ Under `Redirect URIs`:
## Add login code to your client app
+The following outlines the steps to sign in using Spotify with Supabase Auth.
+
+1. Call the signin method from the client library.
+1. The user is redirected to the Spotify login page.
+1. After completing the sign-in process, the user will be redirected to your app with an error that says the email address needs to be confirmed. Simultaneously the user receives a confirmation email from Supabase Auth.
+1. The user clicks the confirmation link in the email.
+1. The user is brought back to the app and is now signed in.
+
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/social-login/auth-twitch.mdx b/apps/docs/content/guides/auth/social-login/auth-twitch.mdx
similarity index 92%
rename from apps/docs/pages/guides/auth/social-login/auth-twitch.mdx
rename to apps/docs/content/guides/auth/social-login/auth-twitch.mdx
index 0db9cf7070c..405477b5da4 100644
--- a/apps/docs/pages/guides/auth/social-login/auth-twitch.mdx
+++ b/apps/docs/content/guides/auth/social-login/auth-twitch.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-twitch',
- title: 'Login with Twitch',
- description: 'Add Twitch OAuth to your Supabase project',
-}
+---
+id: 'auth-twitch'
+title: 'Login with Twitch'
+description: 'Add Twitch OAuth to your Supabase project'
+---
To enable Twitch Auth for your project, you need to set up a Twitch Application and add the Application OAuth credentials to your Supabase Dashboard.
@@ -133,7 +131,3 @@ suspend fun signOut() {
- [Supabase JS Client](https://github.com/supabase/supabase-js)
- [Twitch Account](https://twitch.tv)
- [Twitch Developer Console](https://dev.twitch.tv/console)
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/social-login/auth-twitter.mdx b/apps/docs/content/guides/auth/social-login/auth-twitter.mdx
similarity index 88%
rename from apps/docs/pages/guides/auth/social-login/auth-twitter.mdx
rename to apps/docs/content/guides/auth/social-login/auth-twitter.mdx
index f23283d9417..749029d3c9f 100644
--- a/apps/docs/pages/guides/auth/social-login/auth-twitter.mdx
+++ b/apps/docs/content/guides/auth/social-login/auth-twitter.mdx
@@ -1,12 +1,10 @@
-import Layout from '~/layouts/DefaultGuideLayout'
+---
+id: 'auth-twitter'
+title: 'Login with Twitter'
+description: 'Add Twitter OAuth to your Supabase project'
+---
-export const meta = {
- id: 'auth-twitter',
- title: 'Login with Twitter',
- description: 'Add Twitter OAuth to your Supabase project',
-}
-
-To enable Twitter Auth for your project, you need to set up a Twitter OAuth application with [elevated access](https://developer.twitter.com/en/portal/products/elevated) and add the application credentials in the Supabase Dashboard.
+To enable Twitter Auth for your project, you need to set up a Twitter OAuth application and add the application credentials in the Supabase Dashboard.
## Overview
@@ -123,7 +121,3 @@ suspend fun signOut() {
- [Supabase Account - Free Plan OK](https://supabase.com)
- [Supabase JS Client](https://github.com/supabase/supabase-js)
- [Twitter Developer Dashboard](https://developer.twitter.com/en/portal/dashboard)
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/social-login/auth-workos.mdx b/apps/docs/content/guides/auth/social-login/auth-workos.mdx
similarity index 93%
rename from apps/docs/pages/guides/auth/social-login/auth-workos.mdx
rename to apps/docs/content/guides/auth/social-login/auth-workos.mdx
index 95ff6c4617e..77ed925c241 100644
--- a/apps/docs/pages/guides/auth/social-login/auth-workos.mdx
+++ b/apps/docs/content/guides/auth/social-login/auth-workos.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-workos',
- title: 'Login with WorkOS',
- description: 'Add WorkOS OAuth to your Supabase project',
-}
+---
+id: 'auth-workos'
+title: 'Login with WorkOS'
+description: 'Add WorkOS OAuth to your Supabase project'
+---
To enable WorkOS Auth for your project, you need to set up WorkOS OAuth application and add the application credentials to your Supabase Dashboard.
@@ -134,7 +132,3 @@ suspend fun signOut() {
## Resources
- [WorkOS Documentation](https://workos.com/docs/sso/guide)
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/social-login/auth-zoom.mdx b/apps/docs/content/guides/auth/social-login/auth-zoom.mdx
similarity index 91%
rename from apps/docs/pages/guides/auth/social-login/auth-zoom.mdx
rename to apps/docs/content/guides/auth/social-login/auth-zoom.mdx
index 9fd1ae7cdd4..37d6d07a8e8 100644
--- a/apps/docs/pages/guides/auth/social-login/auth-zoom.mdx
+++ b/apps/docs/content/guides/auth/social-login/auth-zoom.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-zoom',
- title: 'Login with Zoom',
- description: 'Add Zoom OAuth to your Supabase project',
-}
+---
+id: 'auth-zoom'
+title: 'Login with Zoom'
+description: 'Add Zoom OAuth to your Supabase project'
+---
To enable Zoom Auth for your project, you need to set up a Zoom OAuth application and add the application credentials to your Supabase Dashboard.
@@ -130,7 +128,3 @@ suspend fun signOut() {
- [Supabase Account - Free Plan OK](https://supabase.com)
- [Supabase JS Client](https://github.com/supabase/supabase-js)
- [Zoom App Marketplace](https://marketplace.zoom.us/)
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/auth/sso/auth-sso-saml.mdx b/apps/docs/content/guides/auth/sso/auth-sso-saml.mdx
similarity index 98%
rename from apps/docs/pages/guides/auth/sso/auth-sso-saml.mdx
rename to apps/docs/content/guides/auth/sso/auth-sso-saml.mdx
index c4b36288765..48a16a52779 100644
--- a/apps/docs/pages/guides/auth/sso/auth-sso-saml.mdx
+++ b/apps/docs/content/guides/auth/sso/auth-sso-saml.mdx
@@ -1,11 +1,9 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth-sso-saml',
- title: 'Single Sign-On with SAML 2.0 for Projects',
- description: 'Use Single Sign-On (SSO) authentication on your project with SAML 2.0',
- video: 'https://www.youtube.com/v/em1cpOAXknM',
-}
+---
+id: 'auth-sso-saml'
+title: 'Single Sign-On with SAML 2.0 for Projects'
+description: 'Use Single Sign-On (SSO) authentication on your project with SAML 2.0'
+video: 'https://www.youtube.com/v/em1cpOAXknM'
+---
@@ -406,7 +404,3 @@ Should you run into this problem, it is most likely a misconfiguration issue **o
At this time it is not possible to extract the RSA private key used by your project's Supabase Auth server. This is done to keep the private key as secure as possible, given that SAML does not offer an easy way to rotate keys without disrupting service. (Please use a SAML 2.0 Metadata URL whenever possible for this reason!)
If you really need access to the key, please [open a support ticket](https://supabase.com/dashboard/support/new) and we'll try to support you as best as possible.
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/content/guides/functions.mdx b/apps/docs/content/guides/functions.mdx
new file mode 100644
index 00000000000..4889ef00ef0
--- /dev/null
+++ b/apps/docs/content/guides/functions.mdx
@@ -0,0 +1,170 @@
+---
+id: 'functions'
+title: 'Edge Functions'
+description: 'Globally distributed TypeScript functions.'
+subtitle: 'Globally distributed TypeScript functions.'
+sidebar_label: 'Overview'
+hideToc: true
+---
+
+Edge Functions are server-side TypeScript functions, distributed globally at the edge—close to your users. They can be used for listening to webhooks or integrating your Supabase project with third-parties [like Stripe](https://github.com/supabase/supabase/tree/master/examples/edge-functions/supabase/functions/stripe-webhooks). Edge Functions are developed using [Deno](https://deno.com), which offers a few benefits to you as a developer:
+
+- It is open source.
+- It is portable. Supabase Edge Functions run locally, and on any other Deno-compatible platform (including self-hosted infrastructure).
+- It is TypeScript first and supports WASM.
+- Edge Functions are globally distributed for low-latency.
+
+
+
+
+
+## Examples
+
+Check out the [Edge Function Examples](https://github.com/supabase/supabase/tree/master/examples/edge-functions) in our GitHub repository.
+
+
+ {[
+ {
+ name: 'With supabase-js',
+ description: 'Use the Supabase client inside your Edge Function.',
+ href: '/guides/functions/auth',
+ },
+ {
+ name: 'Type-Safe SQL with Kysely',
+ description:
+ 'Combining Kysely with Deno Postgres gives you a convenient developer experience for interacting directly with your Postgres database.',
+ href: '/guides/functions/kysely-postgres',
+ },
+ {
+ name: 'With CORS headers',
+ description: 'Send CORS headers for invoking from the browser.',
+ href: '/guides/functions/cors',
+ },
+ {
+ name: 'React Native with Stripe',
+ description: 'Full example for using Supabase and Stripe, with Expo.',
+ href: 'https://github.com/supabase-community/expo-stripe-payments-with-supabase-functions',
+ },
+ {
+ name: 'Flutter with Stripe',
+ description: 'Full example for using Supabase and Stripe, with Flutter.',
+ href: 'https://github.com/supabase-community/flutter-stripe-payments-with-supabase-functions',
+ },
+ {
+ name: 'Building a RESTful Service API',
+ description:
+ 'Learn how to use HTTP methods and paths to build a RESTful service for managing tasks.',
+ href: 'https://github.com/supabase/supabase/blob/master/examples/edge-functions/supabase/functions/restful-tasks/index.ts',
+ },
+ {
+ name: 'Working with Supabase Storage',
+ description: 'An example on reading a file from Supabase Storage.',
+ href: 'https://github.com/supabase/supabase/blob/master/examples/edge-functions/supabase/functions/read-storage/index.ts',
+ },
+ {
+ name: 'Open Graph Image Generation',
+ description: 'Generate Open Graph images with Deno and Supabase Edge Functions.',
+ href: '/guides/functions/examples/og-image',
+ },
+ {
+ name: 'OG Image Generation & Storage CDN Caching',
+ description: 'Cache generated images with Supabase Storage CDN.',
+ href: 'https://github.com/supabase/supabase/tree/master/examples/edge-functions/supabase/functions/og-image-with-storage-cdn',
+ },
+ {
+ name: 'Get User Location',
+ description: `Get user location data from user's IP address.`,
+ href: 'https://github.com/supabase/supabase/tree/master/examples/edge-functions/supabase/functions/location',
+ },
+ {
+ name: 'Cloudflare Turnstile',
+ description: `Protecting Forms with Cloudflare Turnstile.`,
+ href: '/guides/functions/examples/cloudflare-turnstile',
+ },
+ {
+ name: 'Connect to Postgres',
+ description: `Connecting to Postgres from Edge Functions.`,
+ href: '/guides/functions/connect-to-postgres',
+ },
+ {
+ name: 'Github Actions',
+ description: `Deploying Edge Functions with GitHub Actions.`,
+ href: '/guides/functions/examples/github-actions',
+ },
+ {
+ name: 'Oak Server Middleware',
+ description: `Request Routing with Oak server middleware.`,
+ href: 'https://github.com/supabase/supabase/tree/master/examples/edge-functions/supabase/functions/oak-server',
+ },
+ {
+ name: 'Hugging Face',
+ description: `Access 100,000+ Machine Learning models.`,
+ href: '/guides/ai/examples/huggingface-image-captioning',
+ },
+ {
+ name: 'OpenAI',
+ description: `Using OpenAI in Edge Functions.`,
+ href: '/guides/ai/examples/openai',
+ },
+ {
+ name: 'Stripe Webhooks',
+ description: `Handling signed Stripe Webhooks with Edge Functions.`,
+ href: '/guides/functions/examples/stripe-webhooks',
+ },
+ {
+ name: 'Send emails',
+ description: `Send emails in Edge Functions with Resend.`,
+ href: '/guides/functions/examples/send-emails',
+ },
+ {
+ name: 'Web Stream',
+ description: `Server-Sent Events in Edge Functions.`,
+ href: 'https://github.com/supabase/supabase/tree/master/examples/edge-functions/supabase/functions/streams',
+ },
+ {
+ name: 'Puppeteer',
+ description: `Generate screenshots with Puppeteer.`,
+ href: '/guides/functions/examples/screenshots',
+ },
+ {
+ name: 'Discord Bot',
+ description: `Building a Slash Command Discord Bot with Edge Functions.`,
+ href: '/guides/functions/examples/discord-bot',
+ },
+ {
+ name: 'Telegram Bot',
+ description: `Building a Telegram Bot with Edge Functions.`,
+ href: '/guides/functions/examples/telegram-bot',
+ },
+ {
+ name: 'Upload File',
+ description: `Process multipart/form-data.`,
+ href: 'https://github.com/supabase/supabase/tree/master/examples/edge-functions/supabase/functions/file-upload-storage',
+ },
+ {
+ name: 'Upstash Redis',
+ description: `Build an Edge Functions Counter with Upstash Redis.`,
+ href: '/guides/functions/examples/upstash-redis',
+ },
+ {
+ name: 'Rate Limiting',
+ description: `Rate Limiting Edge Functions with Upstash Redis.`,
+ href: '/guides/functions/examples/rate-limiting',
+ },
+ {
+ name: 'Slack Bot Mention Edge Function',
+ description: `Slack Bot handling Slack mentions in Edge Function`,
+ href: '/guides/functions/examples/slack-bot-mention',
+ },
+ ].map((x) => (
+
+
+
+ {x.description}
+
+
+
+ ))}
+
diff --git a/apps/docs/pages/guides/functions/auth.mdx b/apps/docs/content/guides/functions/auth.mdx
similarity index 88%
rename from apps/docs/pages/guides/functions/auth.mdx
rename to apps/docs/content/guides/functions/auth.mdx
index 963c7af0be7..609f18a46de 100644
--- a/apps/docs/pages/guides/functions/auth.mdx
+++ b/apps/docs/content/guides/functions/auth.mdx
@@ -1,11 +1,9 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'auth',
- title: 'Integrating With Supabase Auth',
- description: 'Supabase Edge Functions and Auth.',
- subtitle: 'Supabase Edge Functions and Auth.',
-}
+---
+id: 'auth'
+title: 'Integrating With Supabase Auth'
+description: 'Supabase Edge Functions and Auth.'
+subtitle: 'Supabase Edge Functions and Auth.'
+---
Edge Functions work seamlessly with [Supabase Auth](/docs/guides/auth).
@@ -86,7 +84,3 @@ Deno.serve(async (req: Request) => {
## Example code
See a full [example on GitHub](https://github.com/supabase/supabase/blob/master/examples/edge-functions/supabase/functions/select-from-table-with-auth-rls/index.ts).
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/functions/cicd-workflow.mdx b/apps/docs/content/guides/functions/cicd-workflow.mdx
similarity index 84%
rename from apps/docs/pages/guides/functions/cicd-workflow.mdx
rename to apps/docs/content/guides/functions/cicd-workflow.mdx
index 05347734533..76cc5d3cafb 100644
--- a/apps/docs/pages/guides/functions/cicd-workflow.mdx
+++ b/apps/docs/content/guides/functions/cicd-workflow.mdx
@@ -1,12 +1,10 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'cicd-workflow',
- title: 'Deploying with CI / CD pipelines',
- description: 'Use GitHub Actions, Bitbucket, and GitLab CI to deploy your Edge Functions.',
- subtitle: 'Use GitHub Actions, Bitbucket, and GitLab CI to deploy your Edge Functions.',
- tocVideo: '6OMVWiiycLs',
-}
+---
+id: 'cicd-workflow'
+title: 'Deploying with CI / CD pipelines'
+description: 'Use GitHub Actions, Bitbucket, and GitLab CI to deploy your Edge Functions.'
+subtitle: 'Use GitHub Actions, Bitbucket, and GitLab CI to deploy your Edge Functions.'
+tocVideo: '6OMVWiiycLs'
+---
You can use popular CI / CD tools like GitHub Actions, Bitbucket, and GitLab CI to automate Edge Function deployments.
@@ -116,7 +114,3 @@ verify_jwt = false
## Resources
- See the [example on GitHub](https://github.com/supabase/supabase/blob/master/examples/edge-functions/.github/workflows/deploy.yaml).
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/functions/connect-to-postgres.mdx b/apps/docs/content/guides/functions/connect-to-postgres.mdx
similarity index 89%
rename from apps/docs/pages/guides/functions/connect-to-postgres.mdx
rename to apps/docs/content/guides/functions/connect-to-postgres.mdx
index b10c1f7c3ee..ac1da710b40 100644
--- a/apps/docs/pages/guides/functions/connect-to-postgres.mdx
+++ b/apps/docs/content/guides/functions/connect-to-postgres.mdx
@@ -1,12 +1,10 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'examples-postgres-on-the-edge',
- title: 'Connecting directly to Postgres',
- description: 'Connecting to Postgres from Edge Functions.',
- subtitle: 'Connecting to Postgres from Edge Functions.',
- tocVideo: 'cl7EuF1-RsY',
-}
+---
+id: 'examples-postgres-on-the-edge'
+title: 'Connecting directly to Postgres'
+description: 'Connecting to Postgres from Edge Functions.'
+subtitle: 'Connecting to Postgres from Edge Functions.'
+tocVideo: 'cl7EuF1-RsY'
+---
Connect to your Postgres database from an Edge Function by using the `supabase-js` client.
You can also use other Postgres clients like [Deno Postgres](https://deno.land/x/postgres)
@@ -115,7 +113,3 @@ DENO_TLS_CA_STORE=mozilla,system
allowFullScreen
>
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/functions/cors.mdx b/apps/docs/content/guides/functions/cors.mdx
similarity index 80%
rename from apps/docs/pages/guides/functions/cors.mdx
rename to apps/docs/content/guides/functions/cors.mdx
index 758b90cce3d..dc357aae63d 100644
--- a/apps/docs/pages/guides/functions/cors.mdx
+++ b/apps/docs/content/guides/functions/cors.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'functions-cors',
- title: 'CORS (Cross-Origin Resource Sharing) support for Invoking from the browser',
- description: 'Add CORS headers to invoke Edge Functions from the browser.',
-}
+---
+id: 'functions-cors'
+title: 'CORS (Cross-Origin Resource Sharing) support for Invoking from the browser'
+description: 'Add CORS headers to invoke Edge Functions from the browser.'
+---
To invoke edge functions from the browser, you need to handle [CORS Preflight](https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request) requests.
@@ -52,7 +50,3 @@ Deno.serve(async (req) => {
}
})
```
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/functions/dart-edge.mdx b/apps/docs/content/guides/functions/dart-edge.mdx
similarity index 94%
rename from apps/docs/pages/guides/functions/dart-edge.mdx
rename to apps/docs/content/guides/functions/dart-edge.mdx
index 66b8c7513a8..32f89e469a4 100644
--- a/apps/docs/pages/guides/functions/dart-edge.mdx
+++ b/apps/docs/content/guides/functions/dart-edge.mdx
@@ -1,10 +1,8 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'functions-dart-edge',
- title: 'Dart Edge',
- description: 'Write your functions using Dart.',
-}
+---
+id: 'functions-dart-edge'
+title: 'Dart Edge'
+description: 'Write your functions using Dart.'
+---
[Dart Edge](https://docs.dartedge.dev/), a project built and maintained by [Invertase](https://invertase.io/), enables Dart code to be run on different edge environments. This guide will walk you through how you can start using Dart Edge to write your backend code using Dart and run it on Supabase.
@@ -156,7 +154,3 @@ supabase functions deploy dart_edge
```
You will be asked to provide the project reference of your Supabase instance to which you want to deploy the function. You can [link your local project to your Supabase instance](https://supabase.com/docs/guides/getting-started/local-development#link-your-project) to avoid having to provide the Supabase reference every time you deploy.
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/functions/debugging.mdx b/apps/docs/content/guides/functions/debugging.mdx
similarity index 96%
rename from apps/docs/pages/guides/functions/debugging.mdx
rename to apps/docs/content/guides/functions/debugging.mdx
index afcd52d6e3a..c9bccc5c505 100644
--- a/apps/docs/pages/guides/functions/debugging.mdx
+++ b/apps/docs/content/guides/functions/debugging.mdx
@@ -1,11 +1,9 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'functions-debugging',
- title: 'Debugging Edge Functions',
- description: 'Debugging tips and Edge Function limitations.',
- subtitle: 'Debugging tips and Edge Function limitations.',
-}
+---
+id: 'functions-debugging'
+title: 'Debugging Edge Functions'
+description: 'Debugging tips and Edge Function limitations.'
+subtitle: 'Debugging tips and Edge Function limitations.'
+---
## Logs & debugging
@@ -166,7 +164,3 @@ deno info --import-map=/path/to/import_map.json /path/to/function/index.ts
- Memory limit for the function: 150 MB (heap) + 150 MB (external - array buffers/ WASM)
- Wall clock limit: 400 s
- CPU Time: 2 s
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/functions/deploy.mdx b/apps/docs/content/guides/functions/deploy.mdx
similarity index 86%
rename from apps/docs/pages/guides/functions/deploy.mdx
rename to apps/docs/content/guides/functions/deploy.mdx
index e285c74f8e9..9e4c6eebef1 100644
--- a/apps/docs/pages/guides/functions/deploy.mdx
+++ b/apps/docs/content/guides/functions/deploy.mdx
@@ -1,12 +1,10 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'functions-deploy',
- title: 'Deploy to Production',
- description: 'Deploy your Edge Functions to your remote Supabase Project.',
- subtitle: 'Deploy your Edge Functions to your remote Supabase Project.',
- tocVideo: 'rzglqRdZUQE',
-}
+---
+id: 'functions-deploy'
+title: 'Deploy to Production'
+description: 'Deploy your Edge Functions to your remote Supabase Project.'
+subtitle: 'Deploy your Edge Functions to your remote Supabase Project.'
+tocVideo: '5OWH9c4u68M'
+---
Once you have developed your Edge Functions locally, you can deploy them to your Supabase project.
@@ -101,7 +99,3 @@ const { data, error } = await supabase.functions.invoke('hello-world', {
You should receive the response `{ "message":"Hello Functions!" }`.
-
-export const Page = ({ children }) =>
-
-export default Page
diff --git a/apps/docs/pages/guides/functions/examples/cloudflare-turnstile.mdx b/apps/docs/content/guides/functions/examples/cloudflare-turnstile.mdx
similarity index 86%
rename from apps/docs/pages/guides/functions/examples/cloudflare-turnstile.mdx
rename to apps/docs/content/guides/functions/examples/cloudflare-turnstile.mdx
index c1c0b694e14..2e6b1bd1355 100644
--- a/apps/docs/pages/guides/functions/examples/cloudflare-turnstile.mdx
+++ b/apps/docs/content/guides/functions/examples/cloudflare-turnstile.mdx
@@ -1,11 +1,9 @@
-import Layout from '~/layouts/DefaultGuideLayout'
-
-export const meta = {
- id: 'examples-cloudflare-turnstile',
- title: 'CAPTCHA support with Cloudflare Turnstile',
- description: 'Protecting Forms with Cloudflare Turnstile.',
- video: 'https://www.youtube.com/v/OwW0znboh60',
-}
+---
+id: 'examples-cloudflare-turnstile'
+title: 'CAPTCHA support with Cloudflare Turnstile'
+description: 'Protecting Forms with Cloudflare Turnstile.'
+video: 'https://www.youtube.com/v/OwW0znboh60'
+---