Merge branch 'master' into feat/docs2.0
This commit is contained in:
3
.github/workflows/publish_image.yml
vendored
3
.github/workflows/publish_image.yml
vendored
@@ -52,7 +52,8 @@ jobs:
|
||||
- uses: docker/build-push-action@v3
|
||||
with:
|
||||
push: true
|
||||
context: '{{defaultContext}}:studio'
|
||||
context: '{{defaultContext}}'
|
||||
file: studio/Dockerfile
|
||||
target: production
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
|
||||
@@ -79,7 +79,7 @@ Then visit, and edit, any of the following sites:
|
||||
|
||||
#### Running sites individually
|
||||
|
||||
You can run any of the sites indiviudally by using the scope name. For example:
|
||||
You can run any of the sites individually by using the scope name. For example:
|
||||
|
||||
```sh
|
||||
npm run dev:www
|
||||
|
||||
@@ -6,8 +6,8 @@ interface Props {
|
||||
title: string
|
||||
description?: string
|
||||
to: string
|
||||
icon?: string | ReactNode
|
||||
children?: ReactNode
|
||||
icon?: string | any
|
||||
children?: any
|
||||
layout?: 'vertical' | 'horizontal'
|
||||
}
|
||||
|
||||
|
||||
35
apps/docs/components/Extensions.js
Normal file
35
apps/docs/components/Extensions.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import React, { useState } from 'react'
|
||||
import extensions from '../data/extensions.json'
|
||||
|
||||
export default function Extensions() {
|
||||
const [filter, setFilter] = useState('')
|
||||
return (
|
||||
<>
|
||||
<div className="mb-8 grid">
|
||||
<label className="text-xs mb-2">Filter extensions</label>
|
||||
<input
|
||||
type="text"
|
||||
className="border text-gray-200"
|
||||
placeholder="Extension name"
|
||||
onChange={(e) => setFilter(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid sm:grid-cols-2 gap-4">
|
||||
{extensions
|
||||
.filter((x) => x.name.indexOf(filter) >= 0)
|
||||
.map((extension) => (
|
||||
<div className={' my-2 px-2'} key={extension.name}>
|
||||
<div className="border rounded-sm p-4">
|
||||
<h3 className="m-0">
|
||||
<code className="text-sm">{extension.name}</code>
|
||||
</h3>
|
||||
<p className=" mt-4">
|
||||
{extension.comment.charAt(0).toUpperCase() + extension.comment.slice(1)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
74
apps/docs/components/GuidesTableOfContents.tsx
Normal file
74
apps/docs/components/GuidesTableOfContents.tsx
Normal file
@@ -0,0 +1,74 @@
|
||||
import { FC } from 'react'
|
||||
import { removeAnchor } from './CustomHTMLElements/CustomHTMLElements.utils'
|
||||
|
||||
const formatSlug = (slug: string) => {
|
||||
// [Joshen] We will still provide support for headers declared like this:
|
||||
// ## REST API {#rest-api-overview}
|
||||
// At least for now, this was a docusaurus thing.
|
||||
if (slug.includes('#')) return slug.split('#')[1]
|
||||
return slug
|
||||
}
|
||||
|
||||
const formatTOCHeader = (content: string) => {
|
||||
let begin = false
|
||||
const res = []
|
||||
for (const x of content) {
|
||||
if (x === '`') {
|
||||
if (!begin) {
|
||||
begin = true
|
||||
res.push(`<code class="text-xs border rounded bg-scale-400 border-scale-500">`)
|
||||
} else {
|
||||
begin = false
|
||||
res.push(`</code>`)
|
||||
}
|
||||
} else {
|
||||
res.push(x)
|
||||
}
|
||||
}
|
||||
return res.join('')
|
||||
}
|
||||
|
||||
interface TOCHeader {
|
||||
id: number
|
||||
level: number
|
||||
text: string
|
||||
link: string
|
||||
}
|
||||
|
||||
interface Props {
|
||||
list: TOCHeader[]
|
||||
}
|
||||
|
||||
const GuidesTableOfContents: FC<Props> = ({ list }) => {
|
||||
return (
|
||||
<ul className="toc-menu list-none pl-4 text-[0.8rem] grid gap-2 mt-12">
|
||||
{list.map((item, i) => (
|
||||
<li key={`${item.level}-${i}`} className={item.level === 3 ? 'ml-4' : ''}>
|
||||
<a
|
||||
href={`#${formatSlug(item.link)}`}
|
||||
className="text-scale-1000 hover:text-brand-900 transition-colors"
|
||||
dangerouslySetInnerHTML={{ __html: formatTOCHeader(removeAnchor(item.text)) }}
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
// <ul className="toc-menu list-none pl-4 text-[0.8rem] grid gap-2 mt-12">
|
||||
// {(toc.json as TOCHeader[])
|
||||
// .filter((item) => item.lvl !== 1 && item.lvl <= 3)
|
||||
// .map((item: any, i: number) => {
|
||||
// return (
|
||||
// <li key={i} id={item.lvl} style={{ marginLeft: `${(item.lvl - 2) * 1}rem` }}>
|
||||
// <a
|
||||
// href={`#${formatSlug(item.slug)}`}
|
||||
// className="text-scale-1000 hover:text-brand-900 transition-colors"
|
||||
// dangerouslySetInnerHTML={{ __html: formatTOCHeader(removeAnchor(item.content)) }}
|
||||
// />
|
||||
// </li>
|
||||
// )
|
||||
// })}
|
||||
// </ul>
|
||||
)
|
||||
}
|
||||
|
||||
export default GuidesTableOfContents
|
||||
@@ -9,7 +9,7 @@ export default function LinkCard({
|
||||
}: {
|
||||
title: string
|
||||
description: string
|
||||
icon: ReactElement
|
||||
icon: any
|
||||
link: string
|
||||
}) {
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ReactElement } from 'react'
|
||||
|
||||
export default function LinkCardsWrapper({ children }: { children: ReactElement }) {
|
||||
export default function LinkCardsWrapper({ children }: { children: any }) {
|
||||
return <div className="flex w-full flex-col lg:flex-row lg:flex-wrap">{children}</div>
|
||||
}
|
||||
|
||||
@@ -110,15 +110,17 @@ const AlgoliaSearch: FC<Props> = ({}) => {
|
||||
: 'capitalize'
|
||||
}`}
|
||||
>
|
||||
{item.category}
|
||||
{item.version ? ` (${item.version})` : ''}:
|
||||
<>
|
||||
{item.category}
|
||||
{item.version ? ` (${item.version})` : ''}:
|
||||
</>
|
||||
</p>
|
||||
)}
|
||||
<p>
|
||||
<components.Highlight hit={item} attribute="title" />
|
||||
</p>
|
||||
</div>
|
||||
<p className="aa-ItemContentSubtitle">{item.description}</p>
|
||||
<p className="aa-ItemContentSubtitle">{item.description as string}</p>
|
||||
</div>
|
||||
</a>
|
||||
)
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
// [Terry]
|
||||
// Delete this after we've implemented GuidesTableofContents and moved all guides
|
||||
// and rename GuidesTableofContents to TableOfContents
|
||||
|
||||
import { FC } from 'react'
|
||||
import { getAnchor, removeAnchor } from './CustomHTMLElements/CustomHTMLElements.utils'
|
||||
|
||||
|
||||
@@ -11,11 +11,13 @@ import JwtGenerator from './JwtGenerator'
|
||||
import Frameworks from './Frameworks'
|
||||
import AuthProviders from './AuthProviders'
|
||||
import FunctionsExamples from './FunctionsExamples'
|
||||
import Extensions from './Extensions'
|
||||
|
||||
// Other components
|
||||
import { Heading } from './CustomHTMLElements'
|
||||
import QuickstartIntro from './MDX/quickstart_intro.mdx'
|
||||
import ProjectSetup from './MDX/project_setup.mdx'
|
||||
import { Mermaid } from 'mdx-mermaid/lib/Mermaid'
|
||||
|
||||
const components = {
|
||||
Admonition,
|
||||
@@ -28,6 +30,8 @@ const components = {
|
||||
JwtGenerator,
|
||||
QuickstartIntro,
|
||||
ProjectSetup,
|
||||
Mermaid,
|
||||
Extensions,
|
||||
Alert: (props: any) => (
|
||||
<Alert {...props} className="not-prose">
|
||||
{props.children}
|
||||
|
||||
0
apps/docs/docs/.gitkeep
Normal file
0
apps/docs/docs/.gitkeep
Normal file
@@ -1,6 +0,0 @@
|
||||
---
|
||||
title: '404'
|
||||
description: 'Page not found'
|
||||
---
|
||||
|
||||
# Page not found
|
||||
@@ -1,172 +0,0 @@
|
||||
---
|
||||
id: features
|
||||
title: Features
|
||||
description: 'Supabase features'
|
||||
---
|
||||
|
||||
This is a non-exhaustive list of features that Supabase provides for every project.
|
||||
|
||||
## Database
|
||||
|
||||
### Postgres Database
|
||||
|
||||
Every project is a full Postgres database. [Docs](/docs/guides/database).
|
||||
|
||||
### Database Extensions
|
||||
|
||||
Every database comes with a full set of Postgres extensions. [Docs](/docs/guides/database/extensions).
|
||||
|
||||
### Database Functions
|
||||
|
||||
Create custom database functions which you can call from the browser. [Docs](/docs/guides/database/functions).
|
||||
|
||||
### Database Triggers
|
||||
|
||||
Attach triggers to your tables to handle database changes. [Docs](/docs/guides/auth/managing-user-data#using-triggers).
|
||||
|
||||
### Database Webhooks
|
||||
|
||||
Send database changes to any external service using Webhooks. [Link](https://supabase.com/blog/supabase-functions-updates#database-webhooks-alpha).
|
||||
|
||||
### Database Backups
|
||||
|
||||
Projects are backed up daily with the option to upgrade to Point in Time recovery.
|
||||
|
||||
### Search
|
||||
|
||||
Build search functionality using Postgres Full Text Search. [Docs](/docs/guides/database/full-text-search).
|
||||
|
||||
### Secrets and encryption
|
||||
|
||||
Encrypt sensitive data and store secrets using our Postgres extension, Supabase Vault. [Link](https://supabase.com/blog/supabase-vault).
|
||||
|
||||
### Database migrations
|
||||
|
||||
Develop locally and push your changes to your production database using migrations. [Docs](/docs/guides/cli/local-development#database-migrations)
|
||||
|
||||
<br />
|
||||
|
||||
## Auth
|
||||
|
||||
### Email & Password Logins
|
||||
|
||||
Build email logins for your application or website. [Docs](/docs/guides/auth/auth-email).
|
||||
|
||||
### Magic Links
|
||||
|
||||
Build passwordless logins for your application or website.[Docs](/docs/guides/auth/auth-magic-link).
|
||||
|
||||
### Social Logins
|
||||
|
||||
Provide social logins - everything from Apple, to GitHub, to Slack. [Docs](/docs/guides/auth/auth-apple).
|
||||
|
||||
### Phone Logins
|
||||
|
||||
Provide phone logins using a 3rd-party SMS provider. [Docs](/docs/guides/auth/auth-twilio).
|
||||
|
||||
### Row Level Security
|
||||
|
||||
Control the data each user can access with Postgres Policies. [Docs](/docs/guides/auth/row-level-security).
|
||||
|
||||
### Serverside Auth Helpers
|
||||
|
||||
Helpers for implementing user authentication in popular frameworks like [Next.js](/docs/guides/auth/auth-helpers/nextjs) and [SvelteKit](/docs/guides/auth/auth-helpers/sveltekit)
|
||||
|
||||
### Auth UI Kit
|
||||
|
||||
Build login and registration pages with custom themes. [Docs](/docs/guides/auth/auth-helpers/auth-ui).
|
||||
|
||||
<br />
|
||||
|
||||
## APIs & Client libraries
|
||||
|
||||
### Auto-generated REST API
|
||||
|
||||
RESTful APIs are autogenerated from your database, without a single line of code. [Docs](/docs/guides/api#rest-api-overview).
|
||||
|
||||
### Auto-generated GraphQL API
|
||||
|
||||
Fast GraphQL APIs using our custom Postgres GraphQL extension. [Docs](/docs/guides/api#graphql-api-overview).
|
||||
|
||||
### Realtime Database changes
|
||||
|
||||
Receive your database changes through websockets. [Docs](/docs/guides/realtime/postgres-cdc).
|
||||
|
||||
### User Broadcasting
|
||||
|
||||
Send messages between connected users through websockets. [Docs](/docs/guides/realtime#broadcast).
|
||||
|
||||
### User Presence
|
||||
|
||||
Synchronize shared state across your users, including online status and typing indicators. [Docs](/docs/guides/realtime#presence).
|
||||
|
||||
### Client libraries
|
||||
|
||||
Official client libraries for [JavaScript](/docs/reference/javascript/) and [Dart](/docs/reference/dart).
|
||||
Unofficial libraries [supported by the community](https://github.com/supabase-community#client-libraries).
|
||||
|
||||
<br />
|
||||
|
||||
## File Storage
|
||||
|
||||
### Large File storage
|
||||
|
||||
Supabase Storage makes it simple to store and serve large files. [Docs](/docs/guides/storage).
|
||||
|
||||
### Storage CDN
|
||||
|
||||
Cache large files using the Supabase CDN. [Docs](/docs/guides/storage-cdn).
|
||||
|
||||
<br />
|
||||
|
||||
## Edge Functions
|
||||
|
||||
### Deno Edge Functions
|
||||
|
||||
Globally distributed TypeScript functions to execute custom business logic. [Docs](/docs/guides/functions).
|
||||
|
||||
<br />
|
||||
|
||||
## Project Managment
|
||||
|
||||
### CLI
|
||||
|
||||
Use our CLI to develop your project locally and deploy to the Supabase Platform. [Docs](/docs/reference/cli).
|
||||
|
||||
### Management API
|
||||
|
||||
Manage your projects programmatically. [Docs](/docs/reference/api).
|
||||
|
||||
<br />
|
||||
|
||||
## Feature Status
|
||||
|
||||
Both Postgres and the Supabase Platform are production-ready. Some tools we offer on top of Postgres are still under development.
|
||||
|
||||
| Product | Feature | Stage |
|
||||
| -------------------------- | ---------------------- | ------- |
|
||||
| Database | Postgres | `GA` |
|
||||
| Database | Triggers | `GA` |
|
||||
| Database | Functions | `GA` |
|
||||
| Database | Extensions | `GA` |
|
||||
| Database | Full Text Search | `GA` |
|
||||
| Database | Webhooks | `alpha` |
|
||||
| Database | Point-in-Time Recovery | `alpha` |
|
||||
| Database | Vault | `alpha` |
|
||||
| Studio | | `GA` |
|
||||
| Realtime | Postgres CDC | `beta` |
|
||||
| Realtime | Broadcast | `alpha` |
|
||||
| Realtime | Presence | `alpha` |
|
||||
| Storage | Backend (S3) | `GA` |
|
||||
| Storage | API | `beta` |
|
||||
| Storage | CDN | `beta` |
|
||||
| Edge Functions | | `beta` |
|
||||
| Auth | OAuth Providers | `beta` |
|
||||
| Auth | Passwordless | `beta` |
|
||||
| Auth | Next.js Auth Helpers | `alpha` |
|
||||
| Auth | SvelteKit Auth Helpers | `alpha` |
|
||||
| Auth | Remix Auth Helpers | `alpha` |
|
||||
| Management API | | `beta` |
|
||||
| CLI | | `beta` |
|
||||
| Client Library: JavaScript | | `GA` |
|
||||
| Client Library: Dart | | `beta` |
|
||||
@@ -1,11 +0,0 @@
|
||||
---
|
||||
id: examples
|
||||
title: Examples
|
||||
description: Useful Supabase Edge Functions Examples
|
||||
---
|
||||
|
||||
You can find a list of useful [Edge Function Examples](https://github.com/supabase/supabase/tree/master/examples/edge-functions) in our GitHub repository.
|
||||
|
||||
<div className="container" style={{ padding: 0 }}>
|
||||
<FunctionsExamples />
|
||||
</div>
|
||||
@@ -1,12 +0,0 @@
|
||||
---
|
||||
id: storage-sample
|
||||
title: 'Storage Sample Doc'
|
||||
description: Storage Sample Doc
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
|
||||
## Description
|
||||
|
||||
Sample...
|
||||
@@ -24,5 +24,5 @@ Read [this post](https://supabase.com/blog/supabase-storage) on why we decided t
|
||||
|
||||
- [Source Code](https://github.com/supabase/storage-api)
|
||||
- [Known bugs and issues](https://github.com/supabase/storage-js/issues)
|
||||
- [Storage Guides](/guides/storage)
|
||||
- [Storage Guides](/docs/guides/storage)
|
||||
- [OpenAPI Docs](https://supabase.github.io/storage-api/)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, FC } from 'react'
|
||||
import Head from 'next/head'
|
||||
import { NextSeo } from 'next-seo'
|
||||
import NavBar from '../components/Navigation/NavBar'
|
||||
import SideBar from '../components/Navigation/SideBar'
|
||||
import Footer from '../components/Footer'
|
||||
@@ -36,16 +36,20 @@ const Layout: FC<Props> = ({ meta, children, toc }) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{meta?.title} | Supabase</title>
|
||||
<meta name="description" content={meta?.description} />
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport" />
|
||||
<link rel="icon" href="/docs/favicon.ico" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:site_name" content={meta?.title} />
|
||||
<meta property="og:description" content={meta?.description} />
|
||||
<meta property="og:title" content={meta?.title} />
|
||||
</Head>
|
||||
<NextSeo
|
||||
title={`${meta?.title} | Supabase`}
|
||||
description={meta?.description ? meta?.description : meta?.title}
|
||||
openGraph={{
|
||||
title: meta?.title,
|
||||
description: meta?.description,
|
||||
url: `https://supabase.com/docs/${currentPage}`,
|
||||
images: [
|
||||
{
|
||||
url: `https://supabase.com/docs/img/supabase-og-image.png`,
|
||||
},
|
||||
],
|
||||
}}
|
||||
/>
|
||||
|
||||
<main>
|
||||
<NavBar />
|
||||
|
||||
112
apps/docs/layouts/DefaultGuideLayout.tsx
Normal file
112
apps/docs/layouts/DefaultGuideLayout.tsx
Normal file
@@ -0,0 +1,112 @@
|
||||
import { MDXProvider } from '@mdx-js/react'
|
||||
import { useEffect, FC, useRef, useState } from 'react'
|
||||
import { NextSeo } from 'next-seo'
|
||||
import NavBar from '../components/Navigation/NavBar'
|
||||
import SideBar from '../components/Navigation/SideBar'
|
||||
import Footer from '../components/Footer'
|
||||
import GuidesTableOfContents from '~/components/GuidesTableOfContents'
|
||||
import { useRouter } from 'next/router'
|
||||
import { getPageType } from '../lib/helpers'
|
||||
import components from '~/components'
|
||||
import { menuItems } from '../components/Navigation/Navigation.constants'
|
||||
|
||||
interface Props {
|
||||
meta: { title: string; description?: string; hide_table_of_contents?: boolean }
|
||||
children: any
|
||||
toc?: any
|
||||
currentPage: string
|
||||
}
|
||||
|
||||
const Layout: FC<Props> = ({ meta, children }) => {
|
||||
const { asPath } = useRouter()
|
||||
const page = getPageType(asPath)
|
||||
|
||||
useEffect(() => {
|
||||
const key = localStorage.getItem('supabaseDarkMode')
|
||||
if (!key) {
|
||||
// Default to dark mode if no preference config
|
||||
document.documentElement.className = 'dark'
|
||||
} else {
|
||||
document.documentElement.className = key === 'true' ? 'dark' : ''
|
||||
}
|
||||
}, [])
|
||||
|
||||
const articleRef = useRef()
|
||||
const [tocList, setTocList] = useState([])
|
||||
|
||||
useEffect(() => {
|
||||
const articleEl = articleRef.current as HTMLElement
|
||||
|
||||
if (!articleRef.current) return
|
||||
const headings = Array.from(articleEl.querySelectorAll('h2, h3'))
|
||||
const newHeadings = headings
|
||||
.filter((heading) => heading.id)
|
||||
.map((heading) => {
|
||||
const text = heading.textContent.replace('#', '')
|
||||
const link = heading.querySelector('a').getAttribute('href')
|
||||
const level = heading.tagName === 'H2' ? 2 : 3
|
||||
return { text, link, level }
|
||||
})
|
||||
setTocList(newHeadings)
|
||||
}, [])
|
||||
|
||||
const hasTableOfContents = tocList.length > 0
|
||||
|
||||
return (
|
||||
<>
|
||||
<NextSeo
|
||||
title={`${meta?.title} | Supabase`}
|
||||
description={meta?.description ? meta?.description : meta?.title}
|
||||
openGraph={{
|
||||
title: meta?.title,
|
||||
description: meta?.description,
|
||||
url: `https://supabase.com/docs${asPath}`,
|
||||
images: [
|
||||
{
|
||||
url: `https://supabase.com/docs/img/supabase-og-image.png`,
|
||||
},
|
||||
],
|
||||
}}
|
||||
/>
|
||||
|
||||
<main>
|
||||
<NavBar currentPage={page} />
|
||||
<div className="flex w-full flex-row">
|
||||
<SideBar menuItems={menuItems[page]} />
|
||||
<div className="main-content-pane docs-width grid md:grid-cols-12 gap-4 justify-between p-4 pb-8 w-full">
|
||||
<div
|
||||
className={`${
|
||||
meta?.hide_table_of_contents || !hasTableOfContents
|
||||
? 'col-span-12 xl:col-start-2 xl:col-span-10 2xl:col-start-3 2xl:col-span-8'
|
||||
: 'col-span-12 lg:col-span-9'
|
||||
} py-2 lg:py-4 px-2 lg:px-8 mx-auto`}
|
||||
>
|
||||
<article
|
||||
ref={articleRef}
|
||||
className={`${
|
||||
meta?.hide_table_of_contents || !hasTableOfContents ? 'xl:min-w-[880px]' : ''
|
||||
} doc-content-container prose dark:prose-dark dark:bg-scale-200 width-full mt-8 2xl:max-w-[880px]`}
|
||||
>
|
||||
{meta?.title && <h1>{meta.title}</h1>}
|
||||
<MDXProvider components={components}>{children}</MDXProvider>
|
||||
</article>
|
||||
</div>
|
||||
{hasTableOfContents && !meta?.hide_table_of_contents && (
|
||||
<div
|
||||
className={[
|
||||
'border-scale-400 dark:bg-scale-200 table-of-contents-height border-l',
|
||||
'thin-scrollbar overflow-y-auto sticky hidden xl:block md:col-span-3 px-2',
|
||||
].join(' ')}
|
||||
>
|
||||
<GuidesTableOfContents list={tocList} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<Footer />
|
||||
</main>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Layout
|
||||
@@ -45,7 +45,7 @@ export function getDocsBySlug(slug: string) {
|
||||
// if no match, 404
|
||||
if (!fs.existsSync(fullPath)) {
|
||||
console.log(`\nfile ${fullPath} not found, redirect to 404\n`)
|
||||
fullPath = join(docsDirectory, 'docs/404.mdx')
|
||||
fullPath = join(docsDirectory, 'pages/404.mdx')
|
||||
}
|
||||
|
||||
const fileContents = fs.readFileSync(fullPath, 'utf8')
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import nextMdx from '@next/mdx'
|
||||
import bundleAnalyzer from '@next/bundle-analyzer'
|
||||
|
||||
import remarkGfm from 'remark-gfm'
|
||||
import rehypeSlug from 'rehype-slug'
|
||||
|
||||
import theme from 'shiki/themes/nord.json' assert { type: 'json' }
|
||||
//import theme from 'shiki/themes/nord.json' assert { type: 'json' }
|
||||
import { remarkCodeHike } from '@code-hike/mdx'
|
||||
|
||||
import withTM from 'next-transpile-modules'
|
||||
@@ -35,14 +33,10 @@ const withMDX = nextMdx({
|
||||
],
|
||||
rehypePlugins: [rehypeSlug],
|
||||
// This is required for `MDXProvider` component
|
||||
providerImportSource: '@mdx-js/react',
|
||||
// providerImportSource: '@mdx-js/react',
|
||||
},
|
||||
})
|
||||
|
||||
// const withBundleAnalyzer = bundleAnalyzer({
|
||||
// enabled: process.env.ANALYZE === 'true',
|
||||
// })
|
||||
|
||||
// /** @type {NextConfig} */
|
||||
const nextConfig = {
|
||||
// Append the default value with md extensions
|
||||
@@ -54,6 +48,27 @@ const nextConfig = {
|
||||
dangerouslyAllowSVG: true,
|
||||
domains: ['avatars.githubusercontent.com', 'github.com', 'user-images.githubusercontent.com'],
|
||||
},
|
||||
async headers() {
|
||||
return [
|
||||
{
|
||||
source: '/(.*)',
|
||||
headers: [
|
||||
{
|
||||
key: 'Strict-Transport-Security',
|
||||
value: '',
|
||||
},
|
||||
{
|
||||
key: 'X-Robots-Tag',
|
||||
value: 'all',
|
||||
},
|
||||
{
|
||||
key: 'X-Frame-Options',
|
||||
value: 'DENY',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
},
|
||||
}
|
||||
|
||||
// next.config.js
|
||||
|
||||
@@ -51,11 +51,13 @@
|
||||
"jsrsasign": "^10.5.26",
|
||||
"lodash": "^4.17.21",
|
||||
"markdown-toc": "^1.2.0",
|
||||
"mdx-mermaid": "2.0.0-rc3",
|
||||
"next": "12.1.0",
|
||||
"next-compose-plugins": "^2.2.1",
|
||||
"next-mdx-remote": "^4.1.0",
|
||||
"next-mdx-toc": "^0.1.3",
|
||||
"next-plugin-yaml": "^1.0.1",
|
||||
"next-seo": "^5.14.1",
|
||||
"next-themes": "0.0.15",
|
||||
"next-transpile-modules": "^9.0.0",
|
||||
"octokit": "^2.0.10",
|
||||
|
||||
6
apps/docs/pages/404.mdx
Normal file
6
apps/docs/pages/404.mdx
Normal file
@@ -0,0 +1,6 @@
|
||||
export const meta = {
|
||||
title: '404',
|
||||
description: 'Page not found',
|
||||
}
|
||||
|
||||
# Page not found
|
||||
@@ -30,7 +30,6 @@ export default function Doc({ meta, content, toc }: Props) {
|
||||
|
||||
export async function getStaticProps({ params }: { params: { slug: string[] } }) {
|
||||
let slug
|
||||
|
||||
if (params.slug.length > 1) {
|
||||
slug = `docs/${params.slug.join('/')}`
|
||||
} else {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
---
|
||||
id: architecture
|
||||
title: Architecture
|
||||
description: 'Supabase design and architecture'
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'architecture',
|
||||
title: 'Architecture',
|
||||
description: 'Supabase design and architecture',
|
||||
}
|
||||
|
||||
Supabase is open source. We choose open source tools which are scalable and make them simple to use.
|
||||
|
||||
@@ -154,3 +156,7 @@ As the profile of a developer changes over time, Supabase will continue to evolv
|
||||
Supabase supports existing tools and communities wherever possible. Supabase is more like a "community of communities" - each tool typically has its own community
|
||||
which we work with.
|
||||
Open source is something we approach [collaboratively](https://supabase.com/blog/supabase-series-b#giving-back): we employ maintainers, sponsor projects, invest in businesses, and develop our own open source tools.
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,8 +1,10 @@
|
||||
---
|
||||
id: faq
|
||||
title: FAQs
|
||||
description: 'Most frequently asked questions regarding Supabase'
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'faq',
|
||||
title: 'FAQs',
|
||||
description: 'Most frequently asked questions regarding Supabase',
|
||||
}
|
||||
|
||||
### Where do I find support?
|
||||
|
||||
@@ -36,3 +38,7 @@ We only support PostgreSQL. It's unlikely we'll ever move away from Postgres; ho
|
||||
We officially support [JavaScript](/docs/reference/javascript/installing) and [Flutter](/docs/reference/dart/installing).
|
||||
|
||||
You can find community-supported libraries in our [GitHub Community](https://github.com/supabase-community), and you can also help us to identify the most popular languages by [voting for a new client library](https://github.com/supabase/supabase/discussions/5).
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,8 +1,10 @@
|
||||
---
|
||||
id: features
|
||||
title: Features
|
||||
description: 'Supabase features'
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'features',
|
||||
title: 'Features',
|
||||
description: 'Supabase features',
|
||||
}
|
||||
|
||||
This is a non-exhaustive list of features that Supabase provides for every project.
|
||||
|
||||
@@ -170,3 +172,7 @@ Both Postgres and the Supabase Platform are production-ready. Some tools we offe
|
||||
| CLI | | `beta` |
|
||||
| Client Library: JavaScript | | `GA` |
|
||||
| Client Library: Dart | | `beta` |
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,9 +1,11 @@
|
||||
---
|
||||
id: api
|
||||
title: Serverless APIs
|
||||
description: Auto-generating and Realtime APIs.
|
||||
sidebar_label: Overview
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'api',
|
||||
title: 'Serverless APIs',
|
||||
description: 'Auto-generating and Realtime APIs.',
|
||||
sidebar_label: 'Overview',
|
||||
}
|
||||
|
||||
Supabase auto-generates three types of API directly from your database schema.
|
||||
|
||||
@@ -319,8 +321,8 @@ called `supabase_realtime`, and by managing this publication you can control whi
|
||||
|
||||
### Securing your Routes
|
||||
|
||||
Your API is designed to work with Postgres Row Level Security (RLS). If you use Supabase [Auth](/guides/auth), you can restrict data based on the logged-in user.
|
||||
To control access to your data, you can use [Policies](/guides/auth#policies).
|
||||
Your API is designed to work with Postgres Row Level Security (RLS). If you use Supabase [Auth](/docs/guides/auth), you can restrict data based on the logged-in user.
|
||||
To control access to your data, you can use [Policies](/docs/guides/auth#policies).
|
||||
When you create a table in Postgres, Row Level Security is disabled by default. To enable RLS:
|
||||
|
||||
<Tabs
|
||||
@@ -373,3 +375,7 @@ The expected value for `useconfig` should be:
|
||||
```sql
|
||||
['session_preload_libraries=supautils, safeupdate']
|
||||
```
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,8 +1,10 @@
|
||||
---
|
||||
id: generating-types
|
||||
title: 'Generating Types'
|
||||
description: How to generate types for your API and Supabase libraries.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'generating-types',
|
||||
title: 'Generating Types',
|
||||
description: 'How to generate types for your API and Supabase libraries.',
|
||||
}
|
||||
|
||||
Supabase APIs are generated from your database, which means that we can use database introspection to generate type-safe API definitions.
|
||||
|
||||
@@ -105,3 +107,7 @@ Alternatively, you can use a community-supported GitHub action: [generate-supaba
|
||||
## Resources
|
||||
|
||||
- [Generating Supabase types with GitHub Actions](https://blog.esteetey.dev/how-to-create-and-test-a-github-action-that-generates-types-from-supabase-database)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,9 +1,11 @@
|
||||
---
|
||||
id: auth
|
||||
title: Auth
|
||||
description: Use Supabase to Authenticate and Authorize your users.
|
||||
sidebar_label: Overview
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'auth',
|
||||
title: 'Auth',
|
||||
description: 'Use Supabase to Authenticate and Authorize your users.',
|
||||
sidebar_label: 'Overview',
|
||||
}
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -120,3 +122,7 @@ When users sign up, Supabase assigns them a unique ID. You can reference this ID
|
||||
<video width="99%" muted playsInline controls="true">
|
||||
<source src="/docs/videos/auth-zoom2.mp4" type="video/mp4" muted playsInline />
|
||||
</video>
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-apple
|
||||
title: 'Login with Apple'
|
||||
description: Add Apple OAuth to your Supabase project
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'auth-apple',
|
||||
title: 'Login with Apple',
|
||||
description: 'Add Apple OAuth to your Supabase project',
|
||||
}
|
||||
|
||||
To enable Apple Auth for your project, you need to set up an Apple OAuth application and add the application credentials to your Supabase Dashboard.
|
||||
|
||||
@@ -202,3 +201,7 @@ async function signout() {
|
||||
- [Ruby](https://www.ruby-lang.org/en/) Docs.
|
||||
- [ruby-jwt](https://github.com/jwt/ruby-jwt) library.
|
||||
- Thanks to [Janak Amarasena](https://medium.com/@janakda) who did all the heavy lifting in [How to configure Sign In with Apple](https://medium.com/identity-beyond-borders/how-to-configure-sign-in-with-apple-77c61e336003).
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-azure
|
||||
title: 'Login with Azure'
|
||||
description: Add Azure OAuth to your Supabase project
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'auth-azure',
|
||||
title: 'Login with Azure',
|
||||
description: 'Add Azure OAuth to your Supabase project',
|
||||
}
|
||||
|
||||
To enable Azure Auth for your project, you need to set up an Azure OAuth application and add the application credentials to your Supabase Dashboard.
|
||||
|
||||
@@ -98,3 +97,7 @@ async function signout() {
|
||||
|
||||
- [Azure Developer Account](https://portal.azure.com)
|
||||
- [GitHub Discussion](https://github.com/supabase/gotrue/pull/54#issuecomment-757043573)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-bitbucket
|
||||
title: 'Login with Bitbucket'
|
||||
description: Add Bitbucket OAuth to your Supabase project
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
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.
|
||||
|
||||
@@ -90,3 +89,7 @@ async function signout() {
|
||||
- [Supabase Account - Free Tier OK](https://supabase.com)
|
||||
- [Supabase JS Client](https://github.com/supabase/supabase-js)
|
||||
- [Bitbucket Account](https://bitbucket.org)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-captcha
|
||||
title: 'Enable Captcha Protection'
|
||||
description: Add Captcha Protection to your Supabase project
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'auth-captcha',
|
||||
title: 'Enable Captcha Protection',
|
||||
description: 'Add Captcha Protection to your Supabase project',
|
||||
}
|
||||
|
||||
Supabase provides you with the option of adding captcha to your sign-in, sign-up, and password reset forms. This keeps your website safe from bots and malicious scripts. Supabase authentication has support for [hCaptcha](https://www.hcaptcha.com/).
|
||||
|
||||
@@ -109,3 +108,7 @@ captcha.current.resetCaptcha()
|
||||
In order to test that this works locally we will need to use something like [ngrok](https://ngrok.com/) or add an entry to your hosts file. You can read more about this in the [hCaptcha docs](https://docs.hcaptcha.com/#local-development).
|
||||
|
||||
Run the application and you should now be provided with a captcha challenge.
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-discord
|
||||
title: 'Login with Discord'
|
||||
description: Add Discord OAuth to your Supabase project
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
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.
|
||||
|
||||
@@ -92,3 +91,7 @@ async function 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 }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-email
|
||||
title: 'Login With Email'
|
||||
description: Use Supabase to Authenticate and Authorize your users using email.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'auth-email',
|
||||
title: 'Login With Email',
|
||||
description: 'Use Supabase to Authenticate and Authorize your users using email.',
|
||||
}
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -99,3 +98,7 @@ Future<void> signOut() async {
|
||||
- [Supabase Account - Free Tier 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 }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-facebook
|
||||
title: 'Login with Facebook'
|
||||
description: Add Facebook OAuth to your Supabase project
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
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.
|
||||
|
||||
@@ -107,3 +106,7 @@ async function signout() {
|
||||
- [Supabase Account - Free Tier OK](https://supabase.com)
|
||||
- [Supabase JS Client](https://github.com/supabase/supabase-js)
|
||||
- [Facebook Developers Dashboard](https://developers.facebook.com/)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-github
|
||||
title: 'Login with GitHub'
|
||||
description: Add GitHub OAuth to your Supabase project
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
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.
|
||||
|
||||
@@ -100,3 +99,7 @@ async function signout() {
|
||||
- [Supabase Account - Free Tier 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 }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-gitlab
|
||||
title: 'Login with GitLab'
|
||||
description: Add GitLab OAuth to your Supabase project
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
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.
|
||||
|
||||
@@ -87,3 +86,7 @@ async function signout() {
|
||||
- [Supabase Account - Free Tier OK](https://supabase.com)
|
||||
- [Supabase JS Client](https://github.com/supabase/supabase-js)
|
||||
- [GitLab Account](https://gitlab.com)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-google
|
||||
title: 'Login with Google'
|
||||
description: Add Google OAuth to your Supabase project
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'auth-google',
|
||||
title: 'Login with Google',
|
||||
description: 'Add Google OAuth to your Supabase project',
|
||||
}
|
||||
|
||||
To enable Google Auth for your project, you need to set up a Google OAuth application and add the application credentials to your Supabase Dashboard.
|
||||
|
||||
@@ -115,3 +114,7 @@ async function signout() {
|
||||
- [Supabase Account - Free Tier OK](https://supabase.com)
|
||||
- [Supabase JS Client](https://github.com/supabase/supabase-js)
|
||||
- [Google Cloud Platform Console](https://console.cloud.google.com/home/dashboard)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,9 +1,11 @@
|
||||
---
|
||||
id: index
|
||||
title: Auth Helpers
|
||||
description: A collection of framework-specific Auth utilities for working with Supabase.
|
||||
sidebar_label: Overview
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'index',
|
||||
title: 'Auth Helpers',
|
||||
description: 'A collection of framework-specific Auth utilities for working with Supabase.',
|
||||
sidebar_label: 'Overview',
|
||||
}
|
||||
|
||||
A collection of framework-specific Auth utilities for working with Supabase.
|
||||
|
||||
@@ -52,3 +54,7 @@ The Auth Helpers are in `beta`. They are usable in their current state, but it's
|
||||
|
||||
- [Source code](https://github.com/supabase/auth-helpers)
|
||||
- [Known bugs and issues](https://github.com/supabase/auth-helpers/issues)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,8 +1,10 @@
|
||||
---
|
||||
id: auth-ui
|
||||
title: Auth UI
|
||||
description: A prebuilt, customizable React component for authenticating users.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'auth-ui',
|
||||
title: 'Auth UI',
|
||||
description: 'A prebuilt, customizable React component for authenticating users.',
|
||||
}
|
||||
|
||||
Auth UI is a pre-built React component for authenticating users.
|
||||
It supports custom themes and extensible styles to match your brand and aesthetic.
|
||||
@@ -273,3 +275,7 @@ const App = () => (
|
||||
/>
|
||||
)
|
||||
```
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,12 +1,11 @@
|
||||
---
|
||||
id: nextjs
|
||||
title: Supabase Auth with Next.js
|
||||
description: Authentication helpers for Next.js API routes, middleware, and SSR.
|
||||
sidebar_label: 'Next.js'
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'nextjs',
|
||||
title: 'Supabase Auth with Next.js',
|
||||
description: 'Authentication helpers for Next.js API routes, middleware, and SSR.',
|
||||
sidebar_label: 'Next.js',
|
||||
}
|
||||
|
||||
This submodule provides convenience helpers for implementing user authentication in Next.js applications.
|
||||
|
||||
@@ -838,3 +837,7 @@ import { Database } from '../database.types'
|
||||
|
||||
const supabaseClient = useSupabaseClient<Database>()
|
||||
```
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,12 +1,11 @@
|
||||
---
|
||||
id: remix
|
||||
title: Supabase Auth with Remix
|
||||
description: Authentication helpers for loaders and actions in Remix.
|
||||
sidebar_label: 'Remix'
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'remix',
|
||||
title: 'Supabase Auth with Remix',
|
||||
description: 'Authentication helpers for loaders and actions in Remix.',
|
||||
sidebar_label: 'Remix',
|
||||
}
|
||||
|
||||
This submodule provides convenience helpers for implementing user authentication in Remix applications.
|
||||
|
||||
@@ -877,3 +876,7 @@ export default function ProtectedPage() {
|
||||
return <pre>{JSON.stringify({ user, allRepos }, null, 2)}</pre>;
|
||||
}
|
||||
```
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,12 +1,11 @@
|
||||
---
|
||||
id: sveltekit
|
||||
title: Supabase Auth with SvelteKit
|
||||
description: Convenience helpers for implementing user authentication in SvelteKit.
|
||||
sidebar_label: SvelteKit
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'sveltekit',
|
||||
title: 'Supabase Auth with SvelteKit',
|
||||
description: 'Convenience helpers for implementing user authentication in SvelteKit.',
|
||||
sidebar_label: 'SvelteKit',
|
||||
}
|
||||
|
||||
This submodule provides convenience helpers for implementing user authentication in [SvelteKit](https://kit.svelte.dev/) applications.
|
||||
|
||||
@@ -53,21 +52,18 @@ PUBLIC_SUPABASE_ANON_KEY=your-anon-key
|
||||
Start off by creating a `db.ts` file inside of the `src/lib` directory and instantiate the `supabaseClient`.
|
||||
|
||||
```ts title=src/lib/db.ts
|
||||
import { createClient } from '@supabase/auth-helpers-sveltekit';
|
||||
import { env } from '$env/dynamic/public';
|
||||
import { createClient } from '@supabase/auth-helpers-sveltekit'
|
||||
import { env } from '$env/dynamic/public'
|
||||
// or use the static env
|
||||
// import { PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY } from '$env/static/public';
|
||||
|
||||
export const supabaseClient = createClient(
|
||||
env.PUBLIC_SUPABASE_URL,
|
||||
env.PUBLIC_SUPABASE_ANON_KEY
|
||||
);
|
||||
export const supabaseClient = createClient(env.PUBLIC_SUPABASE_URL, env.PUBLIC_SUPABASE_ANON_KEY)
|
||||
```
|
||||
|
||||
To make sure the client is initialized on the server and the client, include this file in `src/hooks.server.js` and `src/hooks.client.js`:
|
||||
|
||||
```ts
|
||||
import '$lib/db';
|
||||
import '$lib/db'
|
||||
```
|
||||
|
||||
### Synchronizing the page store
|
||||
@@ -76,21 +72,21 @@ Edit your `+layout.svelte` file and set up the client side.
|
||||
|
||||
```html title=src/routes/+layout.svelte
|
||||
<script>
|
||||
import { supabaseClient } from '$lib/db';
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { onMount } from 'svelte';
|
||||
import { supabaseClient } from '$lib/db'
|
||||
import { invalidate } from '$app/navigation'
|
||||
import { onMount } from 'svelte'
|
||||
|
||||
onMount(() => {
|
||||
const {
|
||||
data: { subscription }
|
||||
data: { subscription },
|
||||
} = supabaseClient.auth.onAuthStateChange(() => {
|
||||
invalidate('supabase:auth');
|
||||
});
|
||||
invalidate('supabase:auth')
|
||||
})
|
||||
|
||||
return () => {
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
});
|
||||
subscription.unsubscribe()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<slot />
|
||||
@@ -105,26 +101,26 @@ If some data is not updated on signin/signout you can fall back to `invalidateAl
|
||||
To make the session available to the UI (pages, layouts), pass the session in the root layout server load function:
|
||||
|
||||
```ts title=src/routes/+layout.server.ts
|
||||
import type { LayoutServerLoad } from './$types';
|
||||
import { getServerSession } from '@supabase/auth-helpers-sveltekit';
|
||||
import type { LayoutServerLoad } from './$types'
|
||||
import { getServerSession } from '@supabase/auth-helpers-sveltekit'
|
||||
|
||||
export const load: LayoutServerLoad = async (event) => {
|
||||
return {
|
||||
session: await getServerSession(event)
|
||||
};
|
||||
};
|
||||
session: await getServerSession(event),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In addition you can create a layout load function if you are using `invalidate('supabase:auth')`:
|
||||
|
||||
```ts title=src/routes/+layout.ts
|
||||
import type { LayoutLoad } from './$types';
|
||||
import { getSupabase } from '@supabase/auth-helpers-sveltekit';
|
||||
import type { LayoutLoad } from './$types'
|
||||
import { getSupabase } from '@supabase/auth-helpers-sveltekit'
|
||||
|
||||
export const load: LayoutLoad = async (event) => {
|
||||
const { session } = await getSupabase(event);
|
||||
return { session };
|
||||
};
|
||||
const { session } = await getSupabase(event)
|
||||
return { session }
|
||||
}
|
||||
```
|
||||
|
||||
This results in fewer server calls as the client manages the session on its own.
|
||||
@@ -134,7 +130,6 @@ This results in fewer server calls as the client manages the session on its own.
|
||||
In order to get the most out of TypeScript and it´s intellisense, you should import our types into the `app.d.ts` type definition file that comes with your SvelteKit project.
|
||||
|
||||
```ts title=src/app.d.ts
|
||||
|
||||
/// <reference types="@sveltejs/kit" />
|
||||
|
||||
// See https://kit.svelte.dev/docs/types#app
|
||||
@@ -142,13 +137,13 @@ In order to get the most out of TypeScript and it´s intellisense, you should im
|
||||
// and what to do when importing types
|
||||
declare namespace App {
|
||||
interface Supabase {
|
||||
Database: import('./DatabaseDefinitions').Database;
|
||||
SchemaName: 'public';
|
||||
Database: import('./DatabaseDefinitions').Database
|
||||
SchemaName: 'public'
|
||||
}
|
||||
|
||||
// interface Locals {}
|
||||
interface PageData {
|
||||
session: import('@supabase/supabase-js').Session | null;
|
||||
session: import('@supabase/supabase-js').Session | null
|
||||
}
|
||||
// interface Error {}
|
||||
// interface Platform {}
|
||||
@@ -161,7 +156,7 @@ You can now determine if a user is authenticated on the client-side by checking
|
||||
|
||||
```html title=src/routes/+page.svelte
|
||||
<script>
|
||||
import { page } from '$app/stores';
|
||||
import { page } from '$app/stores'
|
||||
</script>
|
||||
|
||||
{#if !$page.data.session}
|
||||
@@ -178,17 +173,17 @@ For [row level security](/docs/learn/auth-deep-dive/auth-row-level-security) to
|
||||
|
||||
```html
|
||||
<script>
|
||||
import { supabaseClient } from '$lib/db';
|
||||
import { page } from '$app/stores';
|
||||
import { supabaseClient } from '$lib/db'
|
||||
import { page } from '$app/stores'
|
||||
|
||||
let loadedData = [];
|
||||
let loadedData = []
|
||||
async function loadData() {
|
||||
const { data } = await supabaseClient.from('test').select('*').limit(20);
|
||||
loadedData = data;
|
||||
const { data } = await supabaseClient.from('test').select('*').limit(20)
|
||||
loadedData = data
|
||||
}
|
||||
|
||||
$: if ($page.data.session) {
|
||||
loadData();
|
||||
loadData()
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -203,8 +198,8 @@ For [row level security](/docs/learn/auth-deep-dive/auth-row-level-security) to
|
||||
```html title=src/routes/profile/+page.svelte
|
||||
<script>
|
||||
/** @type {import('./$types').PageData} */
|
||||
export let data;
|
||||
$: ({ user, tableData } = data);
|
||||
export let data
|
||||
$: ({ user, tableData } = data)
|
||||
</script>
|
||||
|
||||
<div>Protected content for {user.email}</div>
|
||||
@@ -215,22 +210,22 @@ For [row level security](/docs/learn/auth-deep-dive/auth-row-level-security) to
|
||||
For [row level security](/docs/learn/auth-deep-dive/auth-row-level-security) to work in a server environment, you need to use the `getSupabase` helper to check if the user is authenticated. The helper requires the `event` and returns `session` and `supabaseClient`:
|
||||
|
||||
```ts title=src/routes/profile/+page.ts
|
||||
import type { PageLoad } from './$types';
|
||||
import { getSupabase } from '@supabase/auth-helpers-sveltekit';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types'
|
||||
import { getSupabase } from '@supabase/auth-helpers-sveltekit'
|
||||
import { redirect } from '@sveltejs/kit'
|
||||
|
||||
export const load: PageLoad = async (event) => {
|
||||
const { session, supabaseClient } = await getSupabase(event);
|
||||
const { session, supabaseClient } = await getSupabase(event)
|
||||
if (!session) {
|
||||
throw redirect(303, '/');
|
||||
throw redirect(303, '/')
|
||||
}
|
||||
const { data: tableData } = await supabaseClient.from('test').select('*');
|
||||
const { data: tableData } = await supabaseClient.from('test').select('*')
|
||||
|
||||
return {
|
||||
user: session.user,
|
||||
tableData
|
||||
};
|
||||
};
|
||||
tableData,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Protecting API routes
|
||||
@@ -238,19 +233,19 @@ export const load: PageLoad = async (event) => {
|
||||
Wrap an API Route to check that the user has a valid session. If they're not logged in the session is `null`.
|
||||
|
||||
```ts title=src/routes/api/protected-route/+server.ts
|
||||
import type { RequestHandler } from './$types';
|
||||
import { getSupabase } from '@supabase/auth-helpers-sveltekit';
|
||||
import { json, redirect } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from './$types'
|
||||
import { getSupabase } from '@supabase/auth-helpers-sveltekit'
|
||||
import { json, redirect } from '@sveltejs/kit'
|
||||
|
||||
export const GET: RequestHandler = async (event) => {
|
||||
const { session, supabaseClient } = await getSupabase(event);
|
||||
const { session, supabaseClient } = await getSupabase(event)
|
||||
if (!session) {
|
||||
throw redirect(303, '/');
|
||||
throw redirect(303, '/')
|
||||
}
|
||||
const { data } = await supabaseClient.from('test').select('*');
|
||||
const { data } = await supabaseClient.from('test').select('*')
|
||||
|
||||
return json({ data });
|
||||
};
|
||||
return json({ data })
|
||||
}
|
||||
```
|
||||
|
||||
If you visit `/api/protected-route` without a valid session cookie, you will get a 303 response.
|
||||
@@ -260,36 +255,36 @@ If you visit `/api/protected-route` without a valid session cookie, you will get
|
||||
Wrap an Action to check that the user has a valid session. If they're not logged in the session is `null`.
|
||||
|
||||
```ts title=src/routes/posts/+page.server.ts
|
||||
import type { Actions } from './$types';
|
||||
import { getSupabase } from '@supabase/auth-helpers-sveltekit';
|
||||
import { error, invalid } from '@sveltejs/kit';
|
||||
import type { Actions } from './$types'
|
||||
import { getSupabase } from '@supabase/auth-helpers-sveltekit'
|
||||
import { error, invalid } from '@sveltejs/kit'
|
||||
|
||||
export const actions: Actions = {
|
||||
createPost: async (event) => {
|
||||
const { request } = event;
|
||||
const { session, supabaseClient } = await getSupabase(event);
|
||||
const { request } = event
|
||||
const { session, supabaseClient } = await getSupabase(event)
|
||||
if (!session) {
|
||||
// the user is not signed in
|
||||
throw error(403, { message: 'Unauthorized' });
|
||||
throw error(403, { message: 'Unauthorized' })
|
||||
}
|
||||
// we are save, let the user create the post
|
||||
const formData = await request.formData();
|
||||
const content = formData.get('content');
|
||||
const formData = await request.formData()
|
||||
const content = formData.get('content')
|
||||
|
||||
const { error: createPostError, data: newPost } = await supabaseClient
|
||||
.from('posts')
|
||||
.insert({ content });
|
||||
.insert({ content })
|
||||
|
||||
if (createPostError) {
|
||||
return invalid(500, {
|
||||
supabaseErrorMessage: createPostError.message
|
||||
});
|
||||
supabaseErrorMessage: createPostError.message,
|
||||
})
|
||||
}
|
||||
return {
|
||||
newPost
|
||||
};
|
||||
}
|
||||
};
|
||||
newPost,
|
||||
}
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
If you try to submit a form with the action `?/createPost` without a valid session cookie, you will get a 403 error response.
|
||||
@@ -297,50 +292,50 @@ If you try to submit a form with the action `?/createPost` without a valid sessi
|
||||
## Saving and deleting the session
|
||||
|
||||
```ts
|
||||
import type { Actions } from './$types';
|
||||
import { invalid, redirect } from '@sveltejs/kit';
|
||||
import { getSupabase } from '@supabase/auth-helpers-sveltekit';
|
||||
import type { Actions } from './$types'
|
||||
import { invalid, redirect } from '@sveltejs/kit'
|
||||
import { getSupabase } from '@supabase/auth-helpers-sveltekit'
|
||||
|
||||
export const actions: Actions = {
|
||||
signin: async (event) => {
|
||||
const { request, cookies, url } = event;
|
||||
const { session, supabaseClient } = await getSupabase(event);
|
||||
const formData = await request.formData();
|
||||
const { request, cookies, url } = event
|
||||
const { session, supabaseClient } = await getSupabase(event)
|
||||
const formData = await request.formData()
|
||||
|
||||
const email = formData.get('email') as string;
|
||||
const password = formData.get('password') as string;
|
||||
const email = formData.get('email') as string
|
||||
const password = formData.get('password') as string
|
||||
|
||||
const { error } = await supabaseClient.auth.signInWithPassword({
|
||||
email,
|
||||
password
|
||||
});
|
||||
password,
|
||||
})
|
||||
|
||||
if (error) {
|
||||
if (error instanceof AuthApiError && error.status === 400) {
|
||||
return invalid(400, {
|
||||
error: 'Invalid credentials.',
|
||||
values: {
|
||||
email
|
||||
}
|
||||
});
|
||||
email,
|
||||
},
|
||||
})
|
||||
}
|
||||
return invalid(500, {
|
||||
error: 'Server error. Try again later.',
|
||||
values: {
|
||||
email
|
||||
}
|
||||
});
|
||||
email,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
throw redirect(303, '/dashboard');
|
||||
throw redirect(303, '/dashboard')
|
||||
},
|
||||
|
||||
signout: async (event) => {
|
||||
const { supabaseClient } = await getSupabase(event);
|
||||
await supabaseClient.auth.signOut();
|
||||
throw redirect(303, '/');
|
||||
}
|
||||
};
|
||||
const { supabaseClient } = await getSupabase(event)
|
||||
await supabaseClient.auth.signOut()
|
||||
throw redirect(303, '/')
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Protecting multiple routes
|
||||
@@ -349,34 +344,31 @@ To avoid writing the same auth logic in every single route you can use the handl
|
||||
protect multiple routes at once.
|
||||
|
||||
```ts title=src/hooks.server.ts
|
||||
import type { RequestHandler } from './$types';
|
||||
import { getSupabase } from '@supabase/auth-helpers-sveltekit';
|
||||
import { redirect, error } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from './$types'
|
||||
import { getSupabase } from '@supabase/auth-helpers-sveltekit'
|
||||
import { redirect, error } from '@sveltejs/kit'
|
||||
|
||||
export const handle: Handle = async ({ event, resolve }) => {
|
||||
// protect requests to all routes that start with /protected-routes
|
||||
if (event.url.pathname.startsWith('/protected-routes')) {
|
||||
const { session, supabaseClient } = await getSupabase(event);
|
||||
const { session, supabaseClient } = await getSupabase(event)
|
||||
|
||||
if (!session) {
|
||||
throw redirect(303, '/');
|
||||
throw redirect(303, '/')
|
||||
}
|
||||
}
|
||||
|
||||
// protect POST requests to all routes that start with /protected-posts
|
||||
if (
|
||||
event.url.pathname.startsWith('/protected-posts') &&
|
||||
event.request.method === 'POST'
|
||||
) {
|
||||
const { session, supabaseClient } = await getSupabase(event);
|
||||
if (event.url.pathname.startsWith('/protected-posts') && event.request.method === 'POST') {
|
||||
const { session, supabaseClient } = await getSupabase(event)
|
||||
|
||||
if (!session) {
|
||||
throw error(303, '/');
|
||||
throw error(303, '/')
|
||||
}
|
||||
}
|
||||
|
||||
return resolve(event);
|
||||
};
|
||||
return resolve(event)
|
||||
}
|
||||
```
|
||||
|
||||
## Migrate from 0.7.x to 0.8 {#migration}
|
||||
@@ -423,10 +415,7 @@ import { env } from '$env/dynamic/public'
|
||||
|
||||
// import { PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY } from '$env/static/public';
|
||||
|
||||
export const supabaseClient = createClient(
|
||||
env.PUBLIC_SUPABASE_URL,
|
||||
env.PUBLIC_SUPABASE_ANON_KEY
|
||||
);
|
||||
export const supabaseClient = createClient(env.PUBLIC_SUPABASE_URL, env.PUBLIC_SUPABASE_ANON_KEY)
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
@@ -465,21 +454,21 @@ export const supabaseClient = createClient(
|
||||
|
||||
```html title=src/routes/+layout.svelte
|
||||
<script>
|
||||
import { supabaseClient } from '$lib/db';
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { onMount } from 'svelte';
|
||||
import { supabaseClient } from '$lib/db'
|
||||
import { invalidate } from '$app/navigation'
|
||||
import { onMount } from 'svelte'
|
||||
|
||||
onMount(() => {
|
||||
const {
|
||||
data: { subscription }
|
||||
data: { subscription },
|
||||
} = supabaseClient.auth.onAuthStateChange(() => {
|
||||
invalidate('supabase:auth');
|
||||
});
|
||||
invalidate('supabase:auth')
|
||||
})
|
||||
|
||||
return () => {
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
});
|
||||
subscription.unsubscribe()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<slot />
|
||||
@@ -576,13 +565,13 @@ declare namespace App {
|
||||
// and what to do when importing types
|
||||
declare namespace App {
|
||||
interface Supabase {
|
||||
Database: import('./DatabaseDefinitions').Database;
|
||||
SchemaName: 'public';
|
||||
Database: import('./DatabaseDefinitions').Database
|
||||
SchemaName: 'public'
|
||||
}
|
||||
|
||||
// interface Locals {}
|
||||
interface PageData {
|
||||
session: import('@supabase/auth-helpers-sveltekit').SupabaseSession;
|
||||
session: import('@supabase/auth-helpers-sveltekit').SupabaseSession
|
||||
}
|
||||
// interface Error {}
|
||||
// interface Platform {}
|
||||
@@ -638,8 +627,8 @@ export const load: PageLoad = withAuth(async ({ session, getSupabaseClient }) =>
|
||||
```html title=src/routes/protected-route/+page.svelte
|
||||
<script>
|
||||
/** @type {import('./$types').PageData} */
|
||||
export let data;
|
||||
$: ({ user, tableData } = data);
|
||||
export let data
|
||||
$: ({ user, tableData } = data)
|
||||
</script>
|
||||
|
||||
<div>Protected content for {user.email}</div>
|
||||
@@ -649,22 +638,22 @@ export const load: PageLoad = withAuth(async ({ session, getSupabaseClient }) =>
|
||||
|
||||
```ts title=src/routes/protected-route/+page.ts
|
||||
// src/routes/profile/+page.ts
|
||||
import type { PageLoad } from './$types';
|
||||
import { getSupabase } from '@supabase/auth-helpers-sveltekit';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types'
|
||||
import { getSupabase } from '@supabase/auth-helpers-sveltekit'
|
||||
import { redirect } from '@sveltejs/kit'
|
||||
|
||||
export const load: PageLoad = async (event) => {
|
||||
const { session, supabaseClient } = await getSupabase(event);
|
||||
const { session, supabaseClient } = await getSupabase(event)
|
||||
if (!session) {
|
||||
throw redirect(303, '/');
|
||||
throw redirect(303, '/')
|
||||
}
|
||||
const { data: tableData } = await supabaseClient.from('test').select('*');
|
||||
const { data: tableData } = await supabaseClient.from('test').select('*')
|
||||
|
||||
return {
|
||||
user: session.user,
|
||||
tableData
|
||||
};
|
||||
};
|
||||
tableData,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
@@ -681,45 +670,43 @@ export const load: PageLoad = async (event) => {
|
||||
<TabPanel id="older-0-7" label="0.7.x">
|
||||
|
||||
```ts title=src/routes/api/protected-route/+server.ts
|
||||
import type { RequestHandler } from './$types';
|
||||
import { withAuth } from '@supabase/auth-helpers-sveltekit';
|
||||
import { json, redirect } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from './$types'
|
||||
import { withAuth } from '@supabase/auth-helpers-sveltekit'
|
||||
import { json, redirect } from '@sveltejs/kit'
|
||||
|
||||
interface TestTable {
|
||||
id: string;
|
||||
created_at: string;
|
||||
id: string
|
||||
created_at: string
|
||||
}
|
||||
|
||||
export const GET: RequestHandler = withAuth(async ({ session, getSupabaseClient }) => {
|
||||
if (!session.user) {
|
||||
throw redirect(303, '/');
|
||||
throw redirect(303, '/')
|
||||
}
|
||||
|
||||
const { data } = await getSupabaseClient()
|
||||
.from<TestTable>('test')
|
||||
.select('*');
|
||||
const { data } = await getSupabaseClient().from<TestTable>('test').select('*')
|
||||
|
||||
return json({ data });
|
||||
});
|
||||
return json({ data })
|
||||
})
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
<TabPanel id="0.8.0" label="0.8.0">
|
||||
|
||||
```ts title=src/routes/api/protected-route/+server.ts
|
||||
import type { RequestHandler } from './$types';
|
||||
import { getSupabase } from '@supabase/auth-helpers-sveltekit';
|
||||
import { json, redirect } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from './$types'
|
||||
import { getSupabase } from '@supabase/auth-helpers-sveltekit'
|
||||
import { json, redirect } from '@sveltejs/kit'
|
||||
|
||||
export const GET: RequestHandler = async (event) => {
|
||||
const { session, supabaseClient } = await getSupabase(event);
|
||||
const { session, supabaseClient } = await getSupabase(event)
|
||||
if (!session) {
|
||||
throw redirect(303, '/');
|
||||
throw redirect(303, '/')
|
||||
}
|
||||
const { data } = await supabaseClient.from('test').select('*');
|
||||
const { data } = await supabaseClient.from('test').select('*')
|
||||
|
||||
return json({ data });
|
||||
};
|
||||
return json({ data })
|
||||
}
|
||||
```
|
||||
|
||||
</TabPanel>
|
||||
@@ -1129,3 +1116,7 @@ export const GET: RequestHandler = withAuth(async ({ session, getSupabaseClient
|
||||
- [SvelteKit example](https://github.com/supabase/auth-helpers/tree/main/examples/sveltekit)
|
||||
- [SvelteKit Email/Password example](https://github.com/supabase/auth-helpers/tree/main/examples/sveltekit-email-password)
|
||||
- [SvelteKit Magiclink example](https://github.com/supabase/auth-helpers/tree/main/examples/sveltekit-magic-link)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-keycloak
|
||||
title: 'Login with Keycloak'
|
||||
description: Add Keycloak OAuth to your Supabase project
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
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.
|
||||
|
||||
@@ -84,3 +83,7 @@ async function signout() {
|
||||
|
||||
- You can find the keycloak openid endpoint configuration under the realm settings.
|
||||

|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-linkedin
|
||||
title: 'Login with LinkedIn'
|
||||
description: Add LinkedIn OAuth to your Supabase project
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
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.
|
||||
|
||||
@@ -86,3 +85,7 @@ async function signout() {
|
||||
- [Supabase Account - Free Tier 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 }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-magic-link
|
||||
title: 'Login With Magic Link'
|
||||
description: Use Supabase to authenticate and authorize your users using magic links.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'auth-magic-link',
|
||||
title: 'Login With Magic Link',
|
||||
description: 'Use Supabase to authenticate and authorize 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. By default, a user can only request a magic link once every 60 seconds.
|
||||
@@ -91,3 +90,7 @@ Future<void> signOut() async {
|
||||
- [Supabase Account - Free Tier 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 }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-messagebird
|
||||
title: Phone Auth with MessageBird
|
||||
description: How to set up and use Mobile OTP with MessageBird and Supabase.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'auth-messagebird',
|
||||
title: 'Phone Auth with MessageBird',
|
||||
description: 'How to set up and use Mobile OTP with MessageBird and Supabase.',
|
||||
}
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -281,3 +280,7 @@ The user does not have a password therefore will need to sign in via this method
|
||||
- [MessageBird Signup](https://dashboard.messagebird.com/en/sign-up)
|
||||
- [Supabase Dashboard](https://app.supabase.com)
|
||||
- [Supabase Row Level Security](/docs/guides/auth#row-level-security)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,11 @@
|
||||
---
|
||||
id: auth-mfa
|
||||
title: 'Multi-Factor Authentication'
|
||||
description: Add an additional layer of security to your apps with Supabase Auth multi-factor authentication.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import { Mermaid } from 'mdx-mermaid/Mermaid'
|
||||
export const meta = {
|
||||
id: 'auth-mfa',
|
||||
title: 'Multi-Factor Authentication',
|
||||
description:
|
||||
'Add an additional layer of security to your apps with Supabase Auth multi-factor authentication.',
|
||||
}
|
||||
|
||||
<Admonition type="note">
|
||||
|
||||
@@ -26,9 +27,9 @@ prone to malicious account takeovers. These can be prevented with
|
||||
MFA because they require the user to provide proof of
|
||||
both of these:
|
||||
|
||||
- Something they know.
|
||||
- Something they know.
|
||||
Password, or access to a social-login account.
|
||||
- Something they have.
|
||||
- Something they have.
|
||||
Access to an authenticator app (a.k.a. TOTP), mobile phone or recovery code.
|
||||
|
||||
## Overview
|
||||
@@ -39,9 +40,9 @@ authenticator app in the control of users.
|
||||
|
||||
Applications using MFA require two important flows:
|
||||
|
||||
1. **Enrollment flow.**
|
||||
1. **Enrollment flow.**
|
||||
This lets users set up and control MFA in your app.
|
||||
2. **Authentication flow.**
|
||||
2. **Authentication flow.**
|
||||
This lets users sign in using any factors after the conventional login step.
|
||||
|
||||
Supabase Auth provides:
|
||||
@@ -78,11 +79,11 @@ Level](https://pages.nist.gov/800-63-3-Implementation-Resources/63B/AAL/), a
|
||||
standard measure about the assurance Supabase Auth has of the user's identity
|
||||
for that particular session. There are two levels recognized today:
|
||||
|
||||
1. **Assurance Level 1: `aal1`**
|
||||
1. **Assurance Level 1: `aal1`**
|
||||
Means that the user's identity was verified using a conventional login method
|
||||
such as email+password, magic link, one-time password, phone auth or social
|
||||
login.
|
||||
2. **Assurance Level 2: `aal2`**
|
||||
2. **Assurance Level 2: `aal2`**
|
||||
Means that the user's identity was additionally verified using at least one
|
||||
second factor, such as a TOTP code.
|
||||
|
||||
@@ -95,15 +96,15 @@ for your application. JWTs without an `aal` claim are at the `aal1` level.
|
||||
|
||||
Adding MFA to your app involves these three steps:
|
||||
|
||||
1. **Add enrollment flow.**
|
||||
1. **Add enrollment flow.**
|
||||
You need to provide a UI within your app that your users will be able to set-up
|
||||
MFA in. You can add this right after sign-up, or as part of a separate flow in
|
||||
the settings portion of your app.
|
||||
2. **Add challenge step to login.**
|
||||
2. **Add challenge step to login.**
|
||||
If a user has set-up MFA, your app's login flow needs to present a challenge
|
||||
screen to the user asking them to prove they have access to the additional
|
||||
factor.
|
||||
3. **Enforce rules for MFA logins.**
|
||||
3. **Enforce rules for MFA logins.**
|
||||
Once your users have a way to enroll and log in with MFA, you need to enforce
|
||||
authorization rules across your app: on the frontend, backend, API servers or
|
||||
Row-Level Security policies.
|
||||
@@ -113,12 +114,12 @@ Adding MFA to your app involves these three steps:
|
||||
An enrollment flow provides a UI for users to set up additional authentication factors.
|
||||
Most applications add the enrollment flow in two places within their app:
|
||||
|
||||
1. Right after login or sign up.
|
||||
1. Right after login or sign up.
|
||||
This lets users quickly set up MFA immediately after they log in or create an
|
||||
account. We recommend encouraging all users to set up MFA if that makes sense
|
||||
for your application. Many applications offer this as an opt-in step in an
|
||||
effort to reduce onboarding friction.
|
||||
2. From within a settings page.
|
||||
2. From within a settings page.
|
||||
Allows users to set up, disable or modify their MFA settings.
|
||||
|
||||
We recommend building one generic flow that you can reuse in both cases with
|
||||
@@ -126,15 +127,15 @@ minor modifications.
|
||||
|
||||
Enrolling a factor for use with MFA takes three steps:
|
||||
|
||||
1. Call `supabase.auth.mfa.enroll()`.
|
||||
1. Call `supabase.auth.mfa.enroll()`.
|
||||
This method returns a QR code and a secret. Display the QR
|
||||
code to the user and ask them to scan it with their authenticator application.
|
||||
If they are unable to scan the QR code, show the secret in plain text which
|
||||
they can type or paste into their authenticator app.
|
||||
2. Calling the `supabase.auth.mfa.challenge()` API.
|
||||
2. Calling the `supabase.auth.mfa.challenge()` API.
|
||||
This prepares Supabase Auth to accept a verification code from the user
|
||||
and returns a challenge ID.
|
||||
3. Calling the `supabase.auth.mfa.verify()` API.
|
||||
3. Calling the `supabase.auth.mfa.verify()` API.
|
||||
This verifies that the user has indeed added the secret from step (1) into
|
||||
their app and is working correctly. If the verification succeeds, the factor
|
||||
immediately becomes active for the user account. If not, you should repeat
|
||||
@@ -400,15 +401,15 @@ application's database, APIs and server-side rendering.
|
||||
Depending on your application's needs, there are three ways you can choose to
|
||||
enforce MFA.
|
||||
|
||||
1. **Enforce for all users (new and existing).**
|
||||
Any user account will have to enroll MFA to continue using your app.
|
||||
1. **Enforce for all users (new and existing).**
|
||||
Any user account will have to enroll MFA to continue using your app.
|
||||
The application will not allow access without going through MFA first.
|
||||
2. **Enforce for new users only.**
|
||||
2. **Enforce for new users only.**
|
||||
Only new users will be forced to enroll MFA, while old users will be encouraged
|
||||
to do so.
|
||||
to do so.
|
||||
The application will not allow access for new users without going through MFA
|
||||
first.
|
||||
3. **Enforce only for users that have opted-in.**
|
||||
3. **Enforce only for users that have opted-in.**
|
||||
Users that want MFA can enroll in it and the application will not allow access
|
||||
without going through MFA first.
|
||||
|
||||
@@ -547,14 +548,14 @@ using Row Level Security policies will give you sufficient protection. In the
|
||||
event that you have other APIs that you wish to protect, follow these general
|
||||
guidelines:
|
||||
|
||||
1. **Use a good JWT verification and parsing library for your language.**
|
||||
1. **Use a good JWT verification and parsing library for your language.**
|
||||
This will let you securely parse JWTs and extract their claims.
|
||||
2. **Retrieve the `aal` claim from the JWT and compare its value according to
|
||||
your needs.**
|
||||
your needs.**
|
||||
If you've encountered an AAL level that can be increased, ask the user to
|
||||
continue the login process instead of logging them out.
|
||||
3. **Use the `https://<project-ref>.supabase.co/rest/v1/auth/factors` REST
|
||||
endpoint to identify if the user has enrolled any MFA factors.**
|
||||
endpoint to identify if the user has enrolled any MFA factors.**
|
||||
Only `verified` factors should be acted upon.
|
||||
|
||||
## Frequently asked questions
|
||||
@@ -627,3 +628,7 @@ Currently recognized methods are:
|
||||
- `mfa/totp` - a TOTP additional factor.
|
||||
|
||||
This list will expand in the future.
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-notion
|
||||
title: 'Login with Notion'
|
||||
description: Add Notion OAuth to your Supabase project
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
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.
|
||||
|
||||
@@ -90,3 +89,7 @@ async function 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 }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-slack
|
||||
title: 'Login with Slack'
|
||||
description: Add Slack OAuth to your Supabase project
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
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.
|
||||
|
||||
@@ -99,3 +98,7 @@ async function signout() {
|
||||
- [Supabase Account - Free Tier 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 }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-spotify
|
||||
title: 'Login with Spotify'
|
||||
description: Add Spotify OAuth to your Supabase project
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
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.
|
||||
|
||||
@@ -94,3 +93,7 @@ async function signout() {
|
||||
- [Supabase Account - Free Tier OK](https://supabase.com)
|
||||
- [Supabase JS Client](https://github.com/supabase/supabase-js)
|
||||
- [Spotify Developer Dashboard](https://developer.spotify.com/dashboard/)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-twilio
|
||||
title: Phone Auth with Twilio
|
||||
description: How to set up and use Mobile OTP with Twilio and Supabase.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'auth-twilio',
|
||||
title: 'Phone Auth with Twilio',
|
||||
description: 'How to set up and use Mobile OTP with Twilio and Supabase.',
|
||||
}
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -300,3 +299,7 @@ The user does not have a password therefore will need to sign in via this method
|
||||
- [Twilio Signup](https://www.twilio.com/try-twilio)
|
||||
- [Supabase Dashboard](https://app.supabase.com)
|
||||
- [Supabase Row Level Security](/docs/guides/auth#row-level-security)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-twitch
|
||||
title: 'Login with Twitch'
|
||||
description: Add Twitch OAuth to your Supabase project
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
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.
|
||||
|
||||
@@ -106,3 +105,7 @@ async function 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 }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-twitter
|
||||
title: 'Login with Twitter'
|
||||
description: Add Twitter OAuth to your Supabase project
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
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 and add the application credentials to your Supabase Dashboard.
|
||||
|
||||
@@ -95,3 +94,7 @@ async function signout() {
|
||||
- [Supabase Account - Free Tier 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 }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-vonage
|
||||
title: Phone Auth with Vonage
|
||||
description: How to set up and use Mobile OTP with Vonage and Supabase.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'auth-vonage',
|
||||
title: 'Phone Auth with Vonage',
|
||||
description: 'How to set up and use Mobile OTP with Vonage and Supabase.',
|
||||
}
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -272,3 +271,7 @@ The user does not have a password therefore will need to sign in via this method
|
||||
- [Vonage Signup](https://dashboard.nexmo.com/sign-up)
|
||||
- [Supabase Dashboard](https://app.supabase.com)
|
||||
- [Supabase Row Level Security](/docs/guides/auth#row-level-security)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-workos
|
||||
title: 'Login with WorkOS'
|
||||
description: Add WorkOS OAuth to your Supabase project
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
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.
|
||||
|
||||
@@ -88,3 +87,7 @@ async function signout() {
|
||||
## Resources
|
||||
|
||||
- [WorkOS Documentation](https://workos.com/docs/sso/guide)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: auth-zoom
|
||||
title: 'Login with Zoom'
|
||||
description: Add Zoom OAuth to your Supabase project
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
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.
|
||||
|
||||
@@ -95,3 +94,7 @@ async function signout() {
|
||||
- [Supabase Account - Free Tier OK](https://supabase.com)
|
||||
- [Supabase JS Client](https://github.com/supabase/supabase-js)
|
||||
- [Zoom App Marketplace](https://marketplace.zoom.us/)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,8 +1,10 @@
|
||||
---
|
||||
id: managing-user-data
|
||||
title: Managing User Data
|
||||
description: Securing your user data with Row Level Security.
|
||||
---
|
||||
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.',
|
||||
}
|
||||
|
||||
For security purposes, the `auth` schema is not exposed on the auto-generated API.
|
||||
|
||||
@@ -59,9 +61,7 @@ The nice thing about this pattern? We can now query this table via the API and w
|
||||
|
||||
```js
|
||||
// This will return nothing while the user is logged out
|
||||
const { data } = await supabase
|
||||
.from('profiles')
|
||||
.select('id, username, avatar_url, website')
|
||||
const { data } = await supabase.from('profiles').select('id, username, avatar_url, website')
|
||||
|
||||
// After the user is logged in, this will only return
|
||||
// the logged-in user's data - in this case a single row
|
||||
@@ -105,3 +105,7 @@ create trigger on_auth_user_created
|
||||
after insert on auth.users
|
||||
for each row execute procedure public.handle_new_user();
|
||||
```
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,8 +1,10 @@
|
||||
---
|
||||
id: row-level-security
|
||||
title: Row Level Security
|
||||
description: Secure your data using Postgres Row Level Security.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'row-level-security',
|
||||
title: 'Row Level Security',
|
||||
description: 'Secure your data using Postgres Row Level Security.',
|
||||
}
|
||||
|
||||
When you need granular authorization rules, nothing beats PostgreSQL's [Row Level Security (RLS)](https://www.postgresql.org/docs/current/ddl-rowsecurity.html).
|
||||
|
||||
@@ -363,3 +365,7 @@ Deprecated. Use `auth.jwt() ->> 'email'` instead.
|
||||
</Admonition>
|
||||
|
||||
Returns the email of the user making the request.
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,8 +1,10 @@
|
||||
---
|
||||
id: server-side-rendering
|
||||
title: Server-Side Rendering
|
||||
description: Render pages with user information on the server.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
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.
|
||||
@@ -205,3 +207,7 @@ data belonging to different users!
|
||||
|
||||
Also be sure you set proper cache control headers. We recommend invalidating
|
||||
cache keys every hour or less.
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,10 +1,13 @@
|
||||
---
|
||||
id: cli
|
||||
title: Supabase CLI
|
||||
description: The Supabase CLI provides tools to develop your project locally and deploy to the Supabase Platform.
|
||||
sidebar_label: Overview
|
||||
toc_max_heading_level: 2
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'cli',
|
||||
title: 'Supabase CLI',
|
||||
description:
|
||||
'The Supabase CLI provides tools to develop your project locally and deploy to the Supabase Platform.',
|
||||
sidebar_label: 'Overview',
|
||||
toc_max_heading_level: 2,
|
||||
}
|
||||
|
||||
The Supabase CLI provides tools to develop your project locally and deploy to the Supabase Platform.
|
||||
You can also use the CLI to manage your Supabase projects, handle database migrations and CI/CD workflows, and generate types directly from your database schema.
|
||||
@@ -20,6 +23,7 @@ You can also use the CLI to manage your Supabase projects, handle database migra
|
||||
<TabPanel id="npm" label="npm">
|
||||
|
||||
Install the CLI as dev dependency via [npm](https://www.npmjs.com/package/supabase):
|
||||
|
||||
```sh
|
||||
npm install supabase --save-dev
|
||||
```
|
||||
@@ -112,3 +116,7 @@ brew upgrade supabase
|
||||
- [Supabase CLI Reference](/docs/reference/cli/usage)
|
||||
- [Local Development](/docs/guides/cli/local-development)
|
||||
- [Managing Environments](/docs/guides/cli/managing-environments)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: local-development
|
||||
title: Local Development
|
||||
description: How to use Supabase on your local development machine.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'local-development',
|
||||
title: 'Local Development',
|
||||
description: 'How to use Supabase on your local development machine.',
|
||||
}
|
||||
|
||||
Learn how to use the Supabase CLI to develop your project locally and deploy to the Supabase Platform.
|
||||
|
||||
@@ -46,7 +45,7 @@ git init
|
||||
supabase init
|
||||
```
|
||||
|
||||
Make sure Docker is running. The [start](/docs/reference/cli/usage#supabase-start) command uses Docker to start the Supabase [services](/architecture).
|
||||
Make sure Docker is running. The [start](/docs/reference/cli/usage#supabase-start) command uses Docker to start the Supabase [services](/docs/architecture).
|
||||
This command may take a while to run if this is the first time using the CLI.
|
||||
|
||||
```bash
|
||||
@@ -238,3 +237,7 @@ The local development environment is not as feature-complete as the Supabase Pla
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: managing-environments
|
||||
title: Managing Environments
|
||||
description: How to deploy Supabase schema changes with a CI / CD pipeline.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'managing-environments',
|
||||
title: 'Managing Environments',
|
||||
description: 'How to deploy Supabase schema changes with a CI / CD pipeline.',
|
||||
}
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -415,3 +414,7 @@ supabase db reset
|
||||
In case [`reset`](/docs/reference/cli/usage#supabase-db-reset) fails, you can manually resolve conflicts by editing `<t+2>_dev_A.sql` file.
|
||||
|
||||
Once validated locally, commit your changes to Git and push to GitHub.
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,9 +1,11 @@
|
||||
---
|
||||
id: database
|
||||
title: Database
|
||||
description: Use Supabase to manage your data.
|
||||
sidebar_label: Overview
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'database',
|
||||
title: 'Database',
|
||||
description: 'Use Supabase to manage your data.',
|
||||
sidebar_label: 'Overview',
|
||||
}
|
||||
|
||||
Every Supabase project comes with a full [Postgres](https://www.postgresql.org/) database, a free and open source
|
||||
database which is considered one of the world's most stable and advanced databases.
|
||||
@@ -85,3 +87,7 @@ Read about resetting your database password [here](/docs/guides/database/managin
|
||||
|
||||
- Read more about [Postgres](/docs/postgres/server/about)
|
||||
- Sign in: [app.supabase.com](https://app.supabase.com)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: arrays
|
||||
title: 'Working With Arrays'
|
||||
description: How to use arrays in PostgreSQL and the Supabase API.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'arrays',
|
||||
title: 'Working With Arrays',
|
||||
description: 'How to use arrays in PostgreSQL and the Supabase API.',
|
||||
}
|
||||
|
||||
PostgreSQL supports flexible [array types](https://www.postgresql.org/docs/12/arrays.html). These arrays are also supported in the Supabase Dashboard and in the JavaScript API.
|
||||
|
||||
@@ -160,3 +159,7 @@ returns:
|
||||
- [Supabase JS Client](https://github.com/supabase/supabase-js)
|
||||
- [Supabase Account - Free Tier OK](https://supabase.com)
|
||||
- [PostgreSQL Arrays](https://www.postgresql.org/docs/12/arrays.html)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,8 +1,10 @@
|
||||
---
|
||||
id: connecting-to-postgres
|
||||
title: 'Database Connections'
|
||||
description: There are various ways to connect to your Postgres database.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'connecting-to-postgres',
|
||||
title: 'Database Connections',
|
||||
description: 'There are various ways to connect to your Postgres database.',
|
||||
}
|
||||
|
||||
Supabase provides several options for programmatically connecting to your Postgres database:
|
||||
|
||||
@@ -121,7 +123,7 @@ SSL enabled as illustrated below:
|
||||
psql "sslmode=verify-full sslrootcert=$HOME/Downloads/prod-ca-2021.cer host=db.abcdefghijklm.supabase.co dbname=postgres user=postgres"
|
||||
```
|
||||
|
||||
2. With `pgAdmin`
|
||||
2. With `pgAdmin`
|
||||
a. Register a new Postgres server
|
||||

|
||||
|
||||
@@ -133,3 +135,7 @@ psql "sslmode=verify-full sslrootcert=$HOME/Downloads/prod-ca-2021.cer host=db.a
|
||||
file-picker modal. Select the certificate you downloaded from your Supabase dashboard and save the server details. PgAdmin
|
||||
should now be able to connect to your Postgres via SSL.
|
||||

|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,12 +1,10 @@
|
||||
---
|
||||
id: extensions
|
||||
title: Overview
|
||||
description: Using Postgres extensions.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import ExtensionsComponent from '@site/src/components/Extensions'
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'extensions',
|
||||
title: 'Overview',
|
||||
description: 'Using Postgres extensions.',
|
||||
}
|
||||
|
||||
Extensions are exactly as they sound - they "extend" the database with functionality which isn't part of the Postgres core.
|
||||
Supabase has pre-installed some of the most useful open source extensions.
|
||||
@@ -56,4 +54,8 @@ Enabling some extensions with `create extension <extension-name> with schema ext
|
||||
|
||||
Supabase is pre-configured with over 50 extensions. You can also install your own SQL extensions directly in the database through our SQL editor.
|
||||
|
||||
<ExtensionsComponent />
|
||||
<Extensions />
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: http
|
||||
title: 'http: RESTful Client'
|
||||
description: An HTTP Client for PostgreSQL Functions.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'http',
|
||||
title: 'http: RESTful Client',
|
||||
description: 'An HTTP Client for PostgreSQL Functions.',
|
||||
}
|
||||
|
||||
The `http` extension allows you to call RESTful endpoints within Postgres.
|
||||
|
||||
@@ -114,3 +113,7 @@ from
|
||||
## Resources
|
||||
|
||||
- Official [`http` GitHub Repository](https://github.com/pramsey/pgsql-http)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
id: pgcron
|
||||
title: 'pg_cron: Job Scheduling'
|
||||
description: 'pgnet: a simple cron-based job scheduler for PostgreSQL that runs inside the database.'
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'pgcron',
|
||||
title: 'pg_cron: Job Scheduling',
|
||||
description:
|
||||
'pgnet: a simple cron-based job scheduler for PostgreSQL that runs inside the database.',
|
||||
}
|
||||
|
||||
The `pg_cron` extension is a simple cron-based job scheduler for PostgreSQL that runs inside the database.
|
||||
|
||||
@@ -96,3 +96,7 @@ SELECT cron.unschedule('nightly-vacuum');
|
||||
## Resources
|
||||
|
||||
- [pg_cron GitHub Repository](https://github.com/citusdata/pg_cron)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: pgnet
|
||||
title: 'pg_net: Async Networking'
|
||||
description: 'pg_net: an async networking extension for PostgreSQL.'
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'pgnet',
|
||||
title: 'pg_net: Async Networking',
|
||||
description: 'pg_net: an async networking extension for PostgreSQL.',
|
||||
}
|
||||
|
||||
<Admonition type="caution">
|
||||
|
||||
@@ -251,3 +250,7 @@ Possible values for `net.http_response_result.status` are `('PENDING', 'SUCCESS'
|
||||
|
||||
- Source code: [github.com/supabase/pg_net](https://github.com/supabase/pg_net/)
|
||||
- Official Docs: [supabase.github.io/pg_net](https://supabase.github.io/pg_net/)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: pgtap
|
||||
title: 'pgTAP: Unit Testing'
|
||||
description: Unit testing in PostgreSQL.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'pgtap',
|
||||
title: 'pgTAP: Unit Testing',
|
||||
description: 'Unit testing in PostgreSQL.',
|
||||
}
|
||||
|
||||
`pgTAP` is a unit testing extension for PostgreSQL.
|
||||
|
||||
@@ -156,3 +155,7 @@ API:
|
||||
## Resources
|
||||
|
||||
- Official [`pgTAP` documentation](https://pgtap.org/)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: plv8
|
||||
title: 'plv8: JavaScript Language'
|
||||
description: JavaScript language for PostgreSQL.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'plv8',
|
||||
title: 'plv8: JavaScript Language',
|
||||
description: 'JavaScript language for PostgreSQL.',
|
||||
}
|
||||
|
||||
The `plv8` extension allows you use JavaScript within Postgres.
|
||||
|
||||
@@ -142,3 +141,7 @@ $$ language plv8;
|
||||
|
||||
- Official [`plv8` documentation](https://plv8.github.io/)
|
||||
- [plv8 GitHub Repository](https://github.com/plv8/plv8)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: uuid-ossp
|
||||
title: 'uuid-ossp: Unique Identifiers'
|
||||
description: A UUID generator for PostgreSQL.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'uuid-ossp',
|
||||
title: 'uuid-ossp: Unique Identifiers',
|
||||
description: 'A UUID generator for PostgreSQL.',
|
||||
}
|
||||
|
||||
The `uuid-ossp` extension can be used to generate a `UUID`.
|
||||
|
||||
@@ -63,9 +62,10 @@ Once the extension is enabled, you now have access to a `uuid` type.
|
||||
|
||||
Creates a UUID value based on the combination of computer’s MAC address, current timestamp, and a random value.
|
||||
|
||||
:::note
|
||||
UUIDv1 leaks identifiable details, which might make it unsuitable for certain security-sensitive applications.
|
||||
:::
|
||||
<Admonition type="note">
|
||||
UUIDv1 leaks identifiable details, which might make it unsuitable for certain security-sensitive
|
||||
applications.
|
||||
</Admonition>
|
||||
|
||||
### `uuid_generate_v4()`
|
||||
|
||||
@@ -97,3 +97,7 @@ create table contacts (
|
||||
|
||||
- [Choosing a Postgres Primary Key](https://supabase.com/blog/choosing-a-postgres-primary-key)
|
||||
- [The Basics Of PostgreSQL `UUID` Data Type](https://www.postgresqltutorial.com/postgresql-uuid/)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: full-text-search
|
||||
title: 'Full Text Search'
|
||||
description: How to use full text search in PostgreSQL.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'full-text-search',
|
||||
title: 'Full Text Search',
|
||||
description: 'How to use full text search in PostgreSQL.',
|
||||
}
|
||||
|
||||
Postgres has built-in functions to handle `Full Text Search` queries. This is like a "search engine" within Postgres.
|
||||
|
||||
@@ -588,3 +587,7 @@ final result = await client
|
||||
## Resources
|
||||
|
||||
- [PostgreSQL: Text Search Functions and Operators](https://www.postgresql.org/docs/12/functions-textsearch.html)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: functions
|
||||
title: Database Functions
|
||||
description: Creating and using Postgres functions.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'functions',
|
||||
title: 'Database Functions',
|
||||
description: 'Creating and using Postgres functions.',
|
||||
}
|
||||
|
||||
Postgres has built-in support for [SQL functions](https://www.postgresql.org/docs/current/sql-createfunction.html).
|
||||
These functions live inside your database, and they can be [used with the API](../../reference/javascript/rpc).
|
||||
@@ -344,3 +343,7 @@ GRANT EXECUTE ON FUNCTION hello_world TO service_role;
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: json
|
||||
title: 'JSON'
|
||||
description: Using the JSON data type in PostgreSQL.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'json',
|
||||
title: 'JSON',
|
||||
description: 'Using the JSON data type in PostgreSQL.',
|
||||
}
|
||||
|
||||
PostgreSQL supports [JSON functions and operators](https://www.postgresql.org/docs/current/functions-json.html) which gives flexibility when storing data inside a database column.
|
||||
|
||||
@@ -266,3 +265,7 @@ Note that the `->` operator returns JSONB data. If you want TEXT/STRING data ret
|
||||
- [Supabase JS Client](https://github.com/supabase/supabase-js)
|
||||
- [PostgreSQL: JSON Functions and Operators](https://www.postgresql.org/docs/12/functions-json.html)
|
||||
- [PostgreSQL JSON types](https://www.postgresql.org/docs/12/datatype-json.html)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: managing-passwords
|
||||
title: 'Passwords'
|
||||
description: How to change your PostgreSQL database password.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'managing-passwords',
|
||||
title: 'Passwords',
|
||||
description: 'How to change your PostgreSQL database password.',
|
||||
}
|
||||
|
||||
Your PostgreSQL database is the core of your Supabase project, so it's important that it has a strong, secure password at all times.
|
||||
|
||||
@@ -28,3 +27,7 @@ It's absolutely critical that you store your customers' data safely. Here are so
|
||||
## Resources
|
||||
|
||||
- [PostgreSQL `ALTER USER` Documentation](https://www.postgresql.org/docs/12/sql-alteruser.html)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,12 +1,11 @@
|
||||
---
|
||||
id: managing-timezones
|
||||
title: 'Timezones'
|
||||
slug: managing-timezones
|
||||
description: How to change your database timezone.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'managing-timezones',
|
||||
title: 'Timezones',
|
||||
slug: 'managing-timezones',
|
||||
description: 'How to change your database timezone.',
|
||||
}
|
||||
|
||||
Every Supabase database is set to UTC timezone by default. We strongly recommend keeping it this way, even if your users are in a different location.
|
||||
This is because it makes it much easier to calculate differences between timezones if you adopt the mental model that "everything in my database is in UTC time".
|
||||
@@ -75,3 +74,7 @@ where name ilike '%york%';
|
||||
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: replication
|
||||
title: 'Replication'
|
||||
slug: replication
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'replication',
|
||||
title: 'Replication',
|
||||
slug: 'replication',
|
||||
}
|
||||
|
||||
Replication is a technique for copying the data from one database to another. Supabase uses replication functionality to provide a real-time API. Replication is useful for:
|
||||
|
||||
@@ -22,12 +21,7 @@ Replication is done through _publications_, a method of choosing which changes t
|
||||
4. Control which tables broadcast changes by selecting **Source** and toggling each table.
|
||||
|
||||
<video width="99%" muted playsInline controls="true">
|
||||
<source
|
||||
src="/docs/videos/api/api-realtime.mp4"
|
||||
type="video/mp4"
|
||||
muted
|
||||
playsInline
|
||||
/>
|
||||
<source src="/docs/videos/api/api-realtime.mp4" type="video/mp4" muted playsInline />
|
||||
</video>
|
||||
|
||||
## Create a publication
|
||||
@@ -96,3 +90,7 @@ begin;
|
||||
create publication publication_name;
|
||||
commit;
|
||||
```
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: sql-to-api
|
||||
title: 'Converting SQL to JavaScript API'
|
||||
description: Implementing common SQL patterns in the JavaScript API
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'sql-to-api',
|
||||
title: 'Converting SQL to JavaScript API',
|
||||
description: 'Implementing common SQL patterns in the JavaScript API',
|
||||
}
|
||||
|
||||
<!-- @TODO: this one is a very daunting read on first attempt. Need to check what is the purpose of it? -->
|
||||
|
||||
@@ -81,3 +80,7 @@ const { data, error } = await supabase
|
||||
- [Supabase API: JavaScript select](/docs/reference/javascript/select)
|
||||
- [Supabase API: JavaScript modifiers](/docs/reference/javascript/using-modifiers)
|
||||
- [Supabase API: JavaScript filters](/docs/reference/javascript/using-filters)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: tables
|
||||
title: Tables and Data
|
||||
description: Creating and using Postgres tables.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'tables',
|
||||
title: 'Tables and Data',
|
||||
description: 'Creating and using Postgres tables.',
|
||||
}
|
||||
|
||||
Tables are where you store your data.
|
||||
|
||||
@@ -504,3 +503,7 @@ Creating a materialized view is not a solution to inefficient queries. You shoul
|
||||
- [PostgreSQL Tutorial: Create tables](https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-create-table/)
|
||||
- [PostgreSQL Tutorial: Add column](https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-add-column/)
|
||||
- [PostgreSQL Tutorial: Views](https://www.postgresqltutorial.com/postgresql-views/)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: testing
|
||||
title: Testing Your Database
|
||||
description: Test your database schema, tables, functions, and policies.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'testing',
|
||||
title: 'Testing Your Database',
|
||||
description: 'Test your database schema, tables, functions, and policies.',
|
||||
}
|
||||
|
||||
You can use the Supabase CLI to test your database. The minimum required version of the CLI is [v1.11.4](https://github.com/supabase/cli/releases). To get started:
|
||||
|
||||
@@ -68,3 +67,7 @@ Result: PASS
|
||||
|
||||
- [pgTAP extension](/docs/guides/database/extensions/pgtap)
|
||||
- Official [pgTAP documentation](https://pgtap.org/)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,8 +1,10 @@
|
||||
---
|
||||
id: timeouts
|
||||
title: Timeouts
|
||||
description: Timeouts and optimization
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'timeouts',
|
||||
title: 'Timeouts',
|
||||
description: 'Timeouts and optimization',
|
||||
}
|
||||
|
||||
By default, Supabase limits the maximum statement execution time to _3 seconds_ for users accessing the API using the anon key, and _8 seconds_ for authenticated users. Additionally, all users are subject to a global limit of _2 minutes_. This serves as a backstop against resource exhaustion due to either poorly written queries, or abusive usage.
|
||||
|
||||
@@ -25,3 +27,7 @@ set statement_timeout to 60000; -- 1 minute in milliseconds
|
||||
All Supabase projects come with the [`pg_stat_statements`](https://www.postgresql.org/docs/current/pgstatstatements.html) extension installed, which tracks planning and execution statistics for all statements executed against it. These statistics can be used in order to diagnose the performance of your project.
|
||||
|
||||
This data can further be used in conjunction with the [`explain`](https://www.postgresql.org/docs/current/using-explain.html) functionality of Postgres to optimize your usage.
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
id: webhooks
|
||||
title: 'Database Webhooks'
|
||||
description: Trigger external payloads on database events.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'webhooks',
|
||||
title: 'Database Webhooks',
|
||||
description: 'Trigger external payloads on database events.',
|
||||
}
|
||||
|
||||
Database Webhooks allow you to send real-time data from your database to another system whenever a table event occurs.
|
||||
|
||||
@@ -71,3 +70,7 @@ type DeletePayload = {
|
||||
## Resources
|
||||
|
||||
- [pg_net](/docs/guides/database/extensions/pgnet): an async networking extension for PostgreSQL
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,8 +1,10 @@
|
||||
---
|
||||
id: examples
|
||||
title: Examples and Resources
|
||||
description: 'Examples you can use to get started with Supabase'
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'examples',
|
||||
title: 'Examples and Resources',
|
||||
description: 'Examples you can use to get started with Supabase',
|
||||
}
|
||||
|
||||
<!-- This page is outdated and should not be added to the sidebar until it has been reworked -->
|
||||
|
||||
@@ -153,3 +155,7 @@ Build a basic Todo List with Supabase and your favorite frontend framework:
|
||||
- [Heavy Bit](https://www.heavybit.com/library/podcasts/jamstack-radio/ep-71-open-source-firebase-alternative-with-paul-copplestone-of-supabase/)
|
||||
- [Log Rocket](https://podrocket.logrocket.com/9)
|
||||
- [FS Jam](https://fsjam.org/episodes/episode-33-supabase-with-paul-copplestone)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,12 +1,11 @@
|
||||
---
|
||||
id: functions
|
||||
title: Edge Functions
|
||||
description: 'Globally distributed TypeScript functions.'
|
||||
sidebar_label: Overview
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
import Tabs from '@theme/Tabs'
|
||||
import TabItem from '@theme/TabItem'
|
||||
export const meta = {
|
||||
id: 'functions',
|
||||
title: 'Edge Functions',
|
||||
description: 'Globally distributed TypeScript functions.',
|
||||
sidebar_label: 'Overview',
|
||||
}
|
||||
|
||||
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).
|
||||
|
||||
@@ -275,3 +274,7 @@ Edge Functions supports `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, and `OPTIONS`.
|
||||
- Edge Functions
|
||||
- Local development - only one function at a time
|
||||
- Serving of HTML content is not supported (`GET` requests that return `text/html` will be rewritten to `text/plain`).
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,8 +1,10 @@
|
||||
---
|
||||
id: auth
|
||||
title: Auth
|
||||
description: Supabase Edge Functions and Auth.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'auth',
|
||||
title: 'Auth',
|
||||
description: 'Supabase Edge Functions and Auth.',
|
||||
}
|
||||
|
||||
Edge Functions work seamlessly with [Supabase Auth](/docs/guides/auth), allowing you to identify which user called your function.
|
||||
|
||||
@@ -56,3 +58,7 @@ serve(async (req: Request) => {
|
||||
```
|
||||
|
||||
See the [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 }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,8 +1,10 @@
|
||||
---
|
||||
id: cicd-workflow
|
||||
title: CI / CD Workflow
|
||||
description: How to deploy Supabase Edge Functions with a CI / CD pipeline.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'cicd-workflow',
|
||||
title: 'CI / CD Workflow',
|
||||
description: 'How to deploy Supabase Edge Functions with a CI / CD pipeline.',
|
||||
}
|
||||
|
||||
As described in the Supabase CLI [Environments Guide](/docs/guides/cli/managing-environments), you can use the [`setup-cli` GitHub Action](https://github.com/marketplace/actions/supabase-cli-action) to run Supabase CLI commands in your GitHub Actions, for example to deploy a Supabase Edge Function:
|
||||
|
||||
@@ -34,3 +36,7 @@ jobs:
|
||||
```
|
||||
|
||||
See the [example on GitHub](https://github.com/supabase/supabase/blob/master/examples/edge-functions/.github/workflows/deploy.yaml).
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
17
apps/docs/pages/guides/functions/examples.mdx
Normal file
17
apps/docs/pages/guides/functions/examples.mdx
Normal file
@@ -0,0 +1,17 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'examples',
|
||||
title: 'Examples',
|
||||
description: 'Useful Supabase Edge Functions Examples',
|
||||
}
|
||||
|
||||
You can find a list of useful [Edge Function Examples](https://github.com/supabase/supabase/tree/master/examples/edge-functions) in our GitHub repository.
|
||||
|
||||
<div className="container" style={{ padding: 0 }}>
|
||||
<FunctionsExamples />
|
||||
</div>
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,9 +1,11 @@
|
||||
---
|
||||
id: docker
|
||||
title: Self-hosting with Docker
|
||||
description: How to configure and deploy Supabase.
|
||||
sidebar_label: Docker
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'docker',
|
||||
title: 'Self-hosting with Docker',
|
||||
description: 'How to configure and deploy Supabase.',
|
||||
sidebar_label: 'Docker',
|
||||
}
|
||||
|
||||
Docker is the easiest way to get started with self-hosted Supabase.
|
||||
|
||||
@@ -112,3 +114,7 @@ See the following guides to deploy Docker Compose setup using your preferred too
|
||||
|
||||
- Got a question? [Ask here](https://github.com/supabase/supabase/discussions).
|
||||
- Sign in: [app.supabase.com](https://app.supabase.com)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,9 +1,11 @@
|
||||
---
|
||||
id: overview
|
||||
title: Self Hosting
|
||||
sidebar_label: Overview
|
||||
description: Getting started with Self Hosting.
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'overview',
|
||||
title: 'Self Hosting',
|
||||
sidebar_label: 'Overview',
|
||||
description: 'Getting started with Self Hosting.',
|
||||
}
|
||||
|
||||
There are several ways to use Supabase:
|
||||
|
||||
@@ -153,3 +155,7 @@ While Supabase officially supports Docker, we have several other deployment stra
|
||||
- [supabase-kubernetes](https://github.com/supabase-community/supabase-kubernetes) (Unofficial)
|
||||
- [supabase-terraform](https://github.com/supabase-community/supabase-terraform) (Unofficial)
|
||||
- [supabase-traefik](https://github.com/supabase-community/supabase-traefik) (Unofficial)
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,9 +1,11 @@
|
||||
---
|
||||
id: platform
|
||||
title: Supabase Platform
|
||||
description: Getting started with the Supabase Platform.
|
||||
sidebar_label: Overview
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'platform',
|
||||
title: 'Supabase Platform',
|
||||
description: 'Getting started with the Supabase Platform.',
|
||||
sidebar_label: 'Overview',
|
||||
}
|
||||
|
||||
Supabase is a hosted platform which makes it very simple to get started without needing to manage any infrastructure.
|
||||
|
||||
@@ -29,12 +31,7 @@ Organizations are a way to group your projects. Each organization can be configu
|
||||
You can invite your team members into your organizations to collaborate on projects.
|
||||
|
||||
<video width="99%" muted playsInline controls="true">
|
||||
<source
|
||||
src="/docs/videos/invite-team.mp4"
|
||||
type="video/mp4"
|
||||
muted
|
||||
playsInline
|
||||
/>
|
||||
<source src="/docs/videos/invite-team.mp4" type="video/mp4" muted playsInline />
|
||||
</video>
|
||||
|
||||
You can also assign roles to your team members with different access levels. The table below shows the corresponding permissions for each available role in the Dashboard.
|
||||
@@ -83,3 +80,7 @@ If Supabase experiences outages, we keep you as informed as possible, as early a
|
||||
- Slack Alerts: You can receive updates via the RSS feed, using Slack's [built-in RSS functionality](https://slack.com/help/articles/218688467-Add-RSS-feeds-to-Slack) <br />`/feed subscribe https://status.supabase.com/history.atom`
|
||||
|
||||
Make sure to review our [SLA](/docs/company/sla) for details on our commitment to Platform Stability.
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,8 +1,11 @@
|
||||
---
|
||||
id: appsmith
|
||||
title: 'Appsmith'
|
||||
description: 'Get started with Supabase and Appsmith, an open-source framework for building internal tools.'
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'appsmith',
|
||||
title: 'Appsmith',
|
||||
description:
|
||||
'Get started with Supabase and Appsmith, an open-source framework for building internal tools.',
|
||||
}
|
||||
|
||||
This guide explains how to quickly build a Support Dashboard by connecting a Supabase back-end to an Appsmith front-end.
|
||||
|
||||
@@ -164,3 +167,7 @@ SELECT * FROM public."tickets";
|
||||
- [Appsmith](https://www.appsmith.com/) official website.
|
||||
- [Appsmith GitHub](https://github.com/appsmithorg).
|
||||
- [Appsmith](https://docs.appsmith.com/) documentation.
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,8 +1,11 @@
|
||||
---
|
||||
id: auth0
|
||||
title: 'Auth0'
|
||||
description: 'Swap out Supabase authentication with Auth0. Let Auth0 handle tokens and signing users in and out, while Supabase enforces authorization policies with Row Level Security (RLS).'
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'auth0',
|
||||
title: 'Auth0',
|
||||
description:
|
||||
'Swap out Supabase authentication with Auth0. Let Auth0 handle tokens and signing users in and out, while Supabase enforces authorization policies with Row Level Security (RLS).',
|
||||
}
|
||||
|
||||
This guide steps through building a Next.js application with Auth0 and Supabase. We configure Auth0 to handle authenticating users and managing tokens, while writing our authorization logic in Supabase - using Row Level Security policies.
|
||||
|
||||
@@ -461,3 +464,7 @@ Now when we refresh our application, we should finally see our list of `todos`!
|
||||
- [Using Next.js and Auth0 with Supabase article](https://auth0.com/blog/using-nextjs-and-auth0-with-supabase/).
|
||||
- [Auth0 community](https://community.auth0.com/).
|
||||
- [Auth0 documentation](https://auth0.com/docs/).
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -1,8 +1,11 @@
|
||||
---
|
||||
id: authsignal
|
||||
title: 'Authsignal'
|
||||
description: 'Add an MFA step after sign-in. Use Supabase Auth to sign in with email and password and Authsignal to initiate an Authenticator App challenge.'
|
||||
---
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'authsignal',
|
||||
title: 'Authsignal',
|
||||
description:
|
||||
'Add an MFA step after sign-in. Use Supabase Auth to sign in with email and password and Authsignal to initiate an Authenticator App challenge.',
|
||||
}
|
||||
|
||||
This guide shows how to integrate [Authsignal](https://www.authsignal.com/) with [Next.js](https://nextjs.org/) and [Supabase](https://supabase.com/) in order to add an MFA step after sign-in.
|
||||
|
||||
@@ -580,3 +583,7 @@ Then if you sign out, you'll be prompted to complete an MFA challenge when signi
|
||||
|
||||
- To learn more about Authsignal take a look at the [API Documentation](https://docs.authsignal.com/).
|
||||
- You can customize the look and feel of the Authsignal Prebuilt MFA page [here](https://portal.authsignal.com/organisations/tenants/customizations).
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user