diff --git a/apps/docs/app/contributing/page.tsx b/apps/docs/app/contributing/page.tsx index 666836b4d07ae..851706f228a90 100644 --- a/apps/docs/app/contributing/page.tsx +++ b/apps/docs/app/contributing/page.tsx @@ -12,7 +12,7 @@ export default async function ContributingPage() { const content = await readFile(contentFile, 'utf-8') return ( - +
diff --git a/apps/docs/app/guides/database/extensions/wrappers/[[...slug]]/page.tsx b/apps/docs/app/guides/database/extensions/wrappers/[[...slug]]/page.tsx index 16a6e7ce50e8d..548a836ea1f46 100644 --- a/apps/docs/app/guides/database/extensions/wrappers/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/database/extensions/wrappers/[[...slug]]/page.tsx @@ -1,14 +1,15 @@ import matter from 'gray-matter' -import { type Heading } from 'mdast' -import { fromMarkdown } from 'mdast-util-from-markdown' -import { toMarkdown } from 'mdast-util-to-markdown' import { type SerializeOptions } from 'next-mdx-remote/dist/types' import { readFile } from 'node:fs/promises' import { join, relative } from 'node:path' import rehypeSlug from 'rehype-slug' import emoji from 'remark-emoji' -import { genGuideMeta, genGuidesStaticParams } from '~/features/docs/GuidesMdx.utils' +import { + genGuideMeta, + genGuidesStaticParams, + removeRedundantH1, +} from '~/features/docs/GuidesMdx.utils' import { GuideTemplate, newEditLink } from '~/features/docs/GuidesMdx.template' import { fetchRevalidatePerDay } from '~/features/helpers.fetch' import { GUIDES_DIRECTORY, isValidGuideFrontmatter } from '~/lib/docs' @@ -16,7 +17,6 @@ import { UrlTransformFunction, linkTransform } from '~/lib/mdx/plugins/rehypeLin import remarkMkDocsAdmonition from '~/lib/mdx/plugins/remarkAdmonition' import { removeTitle } from '~/lib/mdx/plugins/remarkRemoveTitle' import remarkPyMdownTabs from '~/lib/mdx/plugins/remarkTabs' -import remarkGfm from 'remark-gfm' // We fetch these docs at build time from an external repo const org = 'supabase' @@ -184,22 +184,7 @@ const getContent = async (params: Params) => { const rawContent = await response.text() const { content: contentWithoutFrontmatter } = matter(rawContent) - - // This is the more robust way of doing it, but problems with the rewritten - // Markdown and handling of tables this way, so saving it for later. - // - // const mdxTree = fromMarkdown(contentWithoutFrontmatter) - // const maybeH1 = mdxTree.children[0] - // if (maybeH1 && maybeH1.type === 'heading' && (maybeH1 as Heading).depth === 1) { - // mdxTree.children.shift() - // } - // content = toMarkdown(mdxTree) - - content = contentWithoutFrontmatter - if (meta.title) { - const h1Regex = new RegExp(`(?:^|\n)# ${meta.title}\n+`) - content = content.replace(h1Regex, '') - } + content = removeRedundantH1(contentWithoutFrontmatter) } return { diff --git a/apps/docs/app/guides/cli/github-action/[slug]/page.tsx b/apps/docs/app/guides/deployment/ci/[slug]/page.tsx similarity index 96% rename from apps/docs/app/guides/cli/github-action/[slug]/page.tsx rename to apps/docs/app/guides/deployment/ci/[slug]/page.tsx index 2f229fbc8f992..670219d4896a0 100644 --- a/apps/docs/app/guides/cli/github-action/[slug]/page.tsx +++ b/apps/docs/app/guides/deployment/ci/[slug]/page.tsx @@ -3,7 +3,7 @@ import { notFound } from 'next/navigation' import { relative } from 'node:path' import rehypeSlug from 'rehype-slug' -import { genGuideMeta } from '~/features/docs/GuidesMdx.utils' +import { genGuideMeta, removeRedundantH1 } from '~/features/docs/GuidesMdx.utils' import { GuideTemplate, newEditLink } from '~/features/docs/GuidesMdx.template' import { fetchRevalidatePerDay } from '~/features/helpers.fetch' import { UrlTransformFunction, linkTransform } from '~/lib/mdx/plugins/rehypeLinkTransform' @@ -83,7 +83,7 @@ const getContent = async ({ slug }: Params) => { `https://raw.githubusercontent.com/${org}/${repo}/${branch}/${docsDir}/${remoteFile}` ) - const content = await response.text() + const content = removeRedundantH1(await response.text()) return { pathname: `/guides/cli/github-action/${slug}` satisfies `/${string}`, diff --git a/apps/docs/app/guides/platform/terraform/[[...slug]]/page.tsx b/apps/docs/app/guides/deployment/terraform/[[...slug]]/page.tsx similarity index 94% rename from apps/docs/app/guides/platform/terraform/[[...slug]]/page.tsx rename to apps/docs/app/guides/deployment/terraform/[[...slug]]/page.tsx index 489f1d7109556..ef81a3efe99cf 100644 --- a/apps/docs/app/guides/platform/terraform/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/deployment/terraform/[[...slug]]/page.tsx @@ -3,7 +3,7 @@ import { type SerializeOptions } from 'next-mdx-remote/dist/types' import { notFound } from 'next/navigation' import rehypeSlug from 'rehype-slug' -import { genGuideMeta } from '~/features/docs/GuidesMdx.utils' +import { genGuideMeta, removeRedundantH1 } from '~/features/docs/GuidesMdx.utils' import { GuideTemplate, newEditLink } from '~/features/docs/GuidesMdx.template' import { fetchRevalidatePerDay } from '~/features/helpers.fetch' import { isValidGuideFrontmatter } from '~/lib/docs' @@ -119,7 +119,11 @@ const getContent = async ({ slug }: Params) => { let rawContent = await response.text() // Strip out HTML comments rawContent = rawContent.replace(//, '') - const { content, data } = matter(rawContent) + let { content, data } = matter(rawContent) + + // Remove the title from the content so it isn't duplicated in the final display + content = removeRedundantH1(content) + Object.assign(meta, data) if (!isValidGuideFrontmatter(meta)) { diff --git a/apps/docs/app/guides/platform/terraform/reference/page.tsx b/apps/docs/app/guides/deployment/terraform/reference/page.tsx similarity index 100% rename from apps/docs/app/guides/platform/terraform/reference/page.tsx rename to apps/docs/app/guides/deployment/terraform/reference/page.tsx diff --git a/apps/docs/app/guides/platform/terraform/terraformConstants.ts b/apps/docs/app/guides/deployment/terraform/terraformConstants.ts similarity index 100% rename from apps/docs/app/guides/platform/terraform/terraformConstants.ts rename to apps/docs/app/guides/deployment/terraform/terraformConstants.ts diff --git a/apps/docs/app/guides/layout.tsx b/apps/docs/app/guides/layout.tsx index 8df012ac97c97..b67a47c2fda9e 100644 --- a/apps/docs/app/guides/layout.tsx +++ b/apps/docs/app/guides/layout.tsx @@ -1,16 +1,29 @@ -'use client' - -import { usePathname } from 'next/navigation' import { type PropsWithChildren } from 'react' -import { getMenuId } from '~/components/Navigation/NavigationMenu/NavigationMenu.utils' +import { supabaseMisc } from '~/lib/supabaseMisc' import Layout from '~/layouts/guides' -const GuidesLayout = ({ children }: PropsWithChildren) => { - const pathname = usePathname() - const menuId = getMenuId(pathname) +const GuidesLayout = async ({ children }: PropsWithChildren) => { + const partners = await getPartners() + const partnerNavItems = partners.map((partner) => ({ + name: partner.title, + url: `https://supabase.com/partners/integrations/${partner.slug}` as `https://${string}`, + })) + + return {children} +} + +async function getPartners() { + const { data, error } = await supabaseMisc() + .from('partners') + .select('slug, title') + .eq('type', 'technology') + .order('title') + if (error) { + console.error(new Error('Error fetching partners', { cause: error })) + } - return {children} + return data ?? [] } export default GuidesLayout diff --git a/apps/docs/app/guides/cli/config/page.tsx b/apps/docs/app/guides/local-development/cli/config/page.tsx similarity index 100% rename from apps/docs/app/guides/cli/config/page.tsx rename to apps/docs/app/guides/local-development/cli/config/page.tsx diff --git a/apps/docs/app/layout.tsx b/apps/docs/app/layout.tsx index 08bcedfdcc3e0..1074889fa232a 100644 --- a/apps/docs/app/layout.tsx +++ b/apps/docs/app/layout.tsx @@ -4,12 +4,13 @@ import '../styles/main.scss' import '../styles/new-docs.scss' import '../styles/prism-okaidia.scss' -import { genFaviconData } from 'common/MetaFavicons/app-router' import { type Metadata, type Viewport } from 'next' -import { BASE_PATH, IS_PRODUCTION } from '~/lib/constants' +import { genFaviconData } from 'common/MetaFavicons/app-router' + import { GlobalProviders } from '~/features/app.providers' import { TopNavSkeleton } from '~/layouts/MainSkeleton' +import { BASE_PATH, IS_PRODUCTION } from '~/lib/constants' const metadata: Metadata = { applicationName: 'Supabase Docs', diff --git a/apps/docs/components/Navigation/Navigation.types.ts b/apps/docs/components/Navigation/Navigation.types.ts index 0b8489dacc8b7..ce2c2dec84195 100644 --- a/apps/docs/components/Navigation/Navigation.types.ts +++ b/apps/docs/components/Navigation/Navigation.types.ts @@ -9,7 +9,7 @@ export interface NavMenuGroup { export interface NavMenuSection { name: string - url?: `/${string}` + url?: `/${string}` | `https://${string}` items: Partial[] } diff --git a/apps/docs/components/Navigation/NavigationMenu/MenuIconPicker.tsx b/apps/docs/components/Navigation/NavigationMenu/MenuIconPicker.tsx index acab4cf6f9745..5f957a2b7a710 100644 --- a/apps/docs/components/Navigation/NavigationMenu/MenuIconPicker.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/MenuIconPicker.tsx @@ -1,3 +1,5 @@ +import { Heart, Server } from 'lucide-react' + import { IconBranching, IconGitHub, @@ -85,8 +87,12 @@ function getMenuIcon(menuKey: string, width: number = 16, height: number = 16, c return case 'support': return - case 'contributing': + case 'troubleshooting': return + case 'contributing': + return + case 'deployment': + return default: return } diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index f68bda1f99203..6f719533ab1d9 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts @@ -1,4 +1,4 @@ -import type { GlobalMenuItems, NavMenuConstant } from '../Navigation.types' +import type { GlobalMenuItems, NavMenuConstant, NavMenuSection } from '../Navigation.types' export const GLOBAL_MENU_ITEMS: GlobalMenuItems = [ [ @@ -60,16 +60,10 @@ export const GLOBAL_MENU_ITEMS: GlobalMenuItems = [ menuItems: [ [ { - label: 'Local Dev / CLI', + label: 'Local Development & CLI', icon: 'dev-cli', - href: '/guides/cli', - level: 'reference_javascript', - }, - { - label: 'Platform', - icon: 'platform', - href: '/guides/platform', - level: 'platform', + href: '/guides/local-development', + level: 'local_development', }, { label: 'Self-Hosting', @@ -81,9 +75,36 @@ export const GLOBAL_MENU_ITEMS: GlobalMenuItems = [ label: 'Integrations', icon: 'integrations', hasLightIcon: true, - href: 'https://supabase.com/partners/integrations', + href: '/guides/integrations', level: 'integrations', }, + { + label: 'Deployment', + icon: 'deployment', + href: '/guides/deployment', + level: 'deployment', + }, + ], + ], + }, + ], + [ + { + label: 'Manage', + menuItems: [ + [ + { + label: 'Platform Management', + icon: 'platform', + href: '/guides/platform', + level: 'platform', + }, + { + label: 'Monitoring & Troubleshooting', + icon: 'troubleshooting', + href: '/guides/monitoring-troubleshooting', + level: 'troubleshooting', + }, ], ], }, @@ -173,9 +194,9 @@ export const GLOBAL_MENU_ITEMS: GlobalMenuItems = [ menuItems: [ [ { - label: 'Migration guides', + label: 'Glossary', icon: 'resources', - href: '/guides/resources', + href: '/guides/resources/glossary', level: 'resources', }, { @@ -1692,68 +1713,62 @@ export const ai = { ], } -export const supabase_cli: NavMenuConstant = { +export const local_development: NavMenuConstant = { icon: 'dev-cli', title: 'Local Dev / CLI', - url: '/guides/cli', + url: '/guides/local-development', items: [ - { name: 'Overview', url: '/guides/cli' }, + { name: 'Overview', url: '/guides/local-development' }, { - name: 'Using the CLI', + name: 'CLI', url: undefined, items: [ - { name: 'Getting started', url: '/guides/cli/getting-started' }, - { name: 'CLI Configuration', url: '/guides/cli/config' }, + { name: 'Getting started', url: '/guides/local-development/cli/getting-started' }, + { name: 'Configuration', url: '/guides/local-development/cli/config' }, + { name: 'CLI commands', url: '/reference/cli' }, ], }, { - name: 'Developing with Supabase', + name: 'Local development', url: undefined, items: [ - { name: 'Local Development', url: '/guides/cli/local-development' }, - { - name: 'Managing environments', - url: '/guides/cli/managing-environments', - }, + { name: 'Getting started', url: '/guides/local-development/overview' }, { name: 'Managing config and secrets', - url: '/guides/cli/managing-config', + url: '/guides/local-development/managing-config', }, { name: 'Seeding your database', - url: '/guides/cli/seeding-your-database', - }, - { - name: 'Testing and linting', - url: '/guides/cli/testing-and-linting', + url: '/guides/local-development/seeding-your-database', }, { name: 'Customizing email templates', - url: '/guides/cli/customizing-email-templates', - }, - ], - }, - { - name: 'GitHub Action', - url: undefined, - items: [ - { - name: 'Generate types from your database', - url: '/guides/cli/github-action/generating-types', - }, - { - name: 'Automated testing', - url: '/guides/cli/github-action/testing', - }, - { - name: 'Backup your database', - url: '/guides/cli/github-action/backups', + url: '/guides/local-development/customizing-email-templates', }, ], }, ], } +export const MIGRATION_PAGES: Partial[] = [ + { name: 'Amazon RDS', url: '/guides/platform/migrating-to-supabase/amazon-rds' }, + { name: 'Auth0', url: '/guides/platform/migrating-to-supabase/auth0' }, + { name: 'Firebase Auth', url: '/guides/platform/migrating-to-supabase/firebase-auth' }, + { + name: 'Firebase Firestore', + url: '/guides/platform/migrating-to-supabase/firestore-data', + }, + { + name: 'Firebase Storage', + url: '/guides/platform/migrating-to-supabase/firebase-storage', + }, + { name: 'Heroku Postgres', url: '/guides/platform/migrating-to-supabase/heroku' }, + { name: 'MySQL', url: '/guides/platform/migrating-to-supabase/mysql' }, + { name: 'MSSQL', url: '/guides/platform/migrating-to-supabase/mssql' }, + { name: 'Postgres', url: '/guides/platform/migrating-to-supabase/postgres' }, + { name: 'Render', url: '/guides/platform/migrating-to-supabase/render' }, +] + export const platform: NavMenuConstant = { icon: 'platform', title: 'Platform', @@ -1771,31 +1786,28 @@ export const platform: NavMenuConstant = { ], }, { - name: 'Logging and observability', + name: 'Upgrades & Migrations', url: undefined, items: [ - { name: 'Logging', url: '/guides/platform/logs' }, - { name: 'Advanced Log Filtering', url: '/guides/platform/advanced-log-filtering' }, - { name: 'Log Drains', url: '/guides/platform/log-drains' }, - { name: 'Metrics', url: '/guides/platform/metrics' }, - { name: 'Monitoring with Sentry', url: '/guides/platform/sentry-monitoring' }, + { name: 'Upgrading', url: '/guides/platform/upgrading' }, + { + name: 'Migrating within Supabase', + url: '/guides/platform/migrating-within-supabase', + }, + { + name: 'Migrating to Supabase', + url: '/guides/platform/migrating-to-supabase', + items: MIGRATION_PAGES, + }, ], }, { - name: 'Platform Management', + name: 'Project & Account Management', url: undefined, items: [ - { name: 'Regions', url: '/guides/platform/regions' }, - { name: 'Database Size', url: '/guides/platform/database-size' }, - { name: 'Fly Postgres', url: '/guides/platform/fly-postgres' }, - { name: 'Vercel Marketplace', url: '/guides/platform/vercel-marketplace' }, { - name: 'HTTP Status Codes', - url: '/guides/platform/http-status-codes', - }, - { - name: 'Migrating and Upgrading', - url: '/guides/platform/migrating-and-upgrading-projects', + name: 'Access Control', + url: '/guides/platform/access-control', }, { name: 'Multi-factor Authentication', @@ -1806,20 +1818,33 @@ export const platform: NavMenuConstant = { url: '/guides/platform/project-transfer', }, { - name: 'Network Restrictions', - url: '/guides/platform/network-restrictions', + name: 'Single Sign-On', + url: '/guides/platform/sso', + items: [ + { name: 'SSO with Azure AD', url: '/guides/platform/sso/azure' }, + { + name: 'SSO with Google Workspace', + url: '/guides/platform/sso/gsuite', + }, + { name: 'SSO with Okta', url: '/guides/platform/sso/okta' }, + ], }, - { name: 'Performance Tuning', url: '/guides/platform/performance' }, - { name: 'Branching', url: '/guides/platform/branching' }, ], }, { - name: 'Security', + name: 'Platform Configuration', url: undefined, items: [ - { name: 'Access Control', url: '/guides/platform/access-control' }, + { name: 'Regions', url: '/guides/platform/regions' }, + { name: 'Database Size', url: '/guides/platform/database-size' }, + { name: 'Fly Postgres', url: '/guides/platform/fly-postgres' }, + { + name: 'Network Restrictions', + url: '/guides/platform/network-restrictions', + }, + { name: 'Performance Tuning', url: '/guides/platform/performance' }, { name: 'SSL Enforcement', url: '/guides/platform/ssl-enforcement' }, - { name: 'Platform-required Permissions', url: '/guides/platform/permissions' }, + { name: 'Default Platform Permissions', url: '/guides/platform/permissions' }, ], }, { @@ -1840,99 +1865,74 @@ export const platform: NavMenuConstant = { }, ], }, + ], +} + +export const monitoring_troubleshooting: NavMenuConstant = { + icon: 'troubleshooting', + title: 'Monitor & Fix', + url: '/guides/monitoring-troubleshooting', + items: [ + { name: 'Overview', url: '/guides/monitoring-troubleshooting' }, { - name: 'Single sign-on', + name: 'Logging & observability', url: undefined, items: [ { - name: 'Enable SSO for your organization', - url: '/guides/platform/sso', + name: 'Logging', + url: '/guides/monitoring-troubleshooting/logs', }, - { name: 'SSO with Azure AD', url: '/guides/platform/sso/azure' }, { - name: 'SSO with Google Workspace', - url: '/guides/platform/sso/gsuite', + name: 'Advanced log filtering', + url: '/guides/monitoring-troubleshooting/advanced-log-filtering', }, - { name: 'SSO with Okta', url: '/guides/platform/sso/okta' }, - ], - }, - { - name: 'Terraform', - url: undefined, - items: [ { - name: 'Terraform Provider', - url: '/guides/platform/terraform', + name: 'Log drains', + url: '/guides/monitoring-troubleshooting/log-drains', }, { - name: 'Terraform Tutorial', - url: '/guides/platform/terraform/tutorial', + name: 'Metrics', + url: '/guides/monitoring-troubleshooting/metrics', }, { - name: 'Reference', - url: '/guides/platform/terraform/reference', + name: 'Sentry integration', + url: '/guides/monitoring-troubleshooting/sentry-monitoring', }, ], }, { - name: 'Production Readiness', + name: 'Troubleshooting', url: undefined, items: [ { - name: 'Shared Responsibility Model', - url: '/guides/platform/shared-responsibility-model', - }, - { - name: 'Maturity Model', - url: '/guides/platform/maturity-model', + name: 'HTTP and project issues', + url: '/guides/monitoring-troubleshooting/troubleshooting', }, { - name: 'Production Checklist', - url: '/guides/platform/going-into-prod', + name: 'High disk IO consumption', + url: '/guides/monitoring-troubleshooting/exhaust-disk-io', }, - ], - }, - { - name: 'Integrations', - url: undefined, - items: [ { - name: 'Integrations Marketplace', - url: '/guides/platform/marketplace', + name: 'High CPU usage', + url: '/guides/monitoring-troubleshooting/exhaust-cpu', }, { - name: 'Build a Supabase Integration', - url: '/guides/platform/oauth-apps/build-a-supabase-integration', + name: 'High RAM usage', + url: '/guides/monitoring-troubleshooting/exhaust-ram', }, { - name: 'OAuth Scopes', - url: '/guides/platform/oauth-apps/oauth-scopes', + name: 'High swap usage', + url: '/guides/monitoring-troubleshooting/exhaust-swap', }, ], }, { - name: 'Troubleshooting', + name: 'Status codes', url: undefined, items: [ { - name: 'HTTP and Project Issues', - url: '/guides/platform/troubleshooting', - }, - { - name: 'High Disk IO Consumption', - url: '/guides/platform/exhaust-disk-io', - }, - { - name: 'High CPU Usage', - url: '/guides/platform/exhaust-cpu', - }, - { - name: 'High RAM Usage', - url: '/guides/platform/exhaust-ram', - }, - { - name: 'High Swap Usage', - url: '/guides/platform/exhaust-swap', + name: 'HTTP status codes', + url: '/guides/monitoring-troubleshooting/http-status-codes', }, ], }, @@ -1943,60 +1943,7 @@ export const resources: NavMenuConstant = { icon: 'resources', title: 'Resources', url: '/guides/resources', - items: [ - { name: 'Examples', url: '/guides/resources/examples' }, - { name: 'Glossary', url: '/guides/resources/glossary' }, - { - name: 'Migrate to Supabase', - url: '/guides/resources/migrating-to-supabase', - items: [ - { - name: 'Amazon RDS', - url: '/guides/resources/migrating-to-supabase/amazon-rds', - items: [], - }, - { - name: 'Auth0', - url: '/guides/resources/migrating-to-supabase/auth0', - }, - { - name: 'Firebase Auth', - url: '/guides/resources/migrating-to-supabase/firebase-auth', - }, - { - name: 'Firebase Firestore', - url: '/guides/resources/migrating-to-supabase/firestore-data', - }, - { - name: 'Firebase Storage', - url: '/guides/resources/migrating-to-supabase/firebase-storage', - }, - { - name: 'Heroku Postgres', - url: '/guides/resources/migrating-to-supabase/heroku', - }, - { - name: 'MySQL', - url: '/guides/resources/migrating-to-supabase/mysql', - items: [], - }, - { - name: 'MSSQL', - url: '/guides/resources/migrating-to-supabase/mssql', - items: [], - }, - { - name: 'Postgres', - url: '/guides/resources/migrating-to-supabase/postgres', - items: [], - }, - { - name: 'Render', - url: '/guides/resources/migrating-to-supabase/render', - }, - ], - }, - ], + items: [{ name: 'Glossary', url: '/guides/resources/glossary' }], } export const self_hosting: NavMenuConstant = { @@ -2061,16 +2008,86 @@ export const self_hosting: NavMenuConstant = { ], } -export const migrate = { - title: 'Migrate to Supabase', - url: '/guides/migrate', +export const deployment: NavMenuConstant = { + title: 'Deployment', + url: '/guides/deployment', + icon: 'deployment', items: [ - { name: 'Firebase Auth', url: '/guides/migrations/firebase-auth' }, - { name: 'Firestore Data', url: '/guides/migrations/firestore-data' }, - { name: 'Firebase Storage', url: '/guides/migrations/firebase-storage' }, - { name: 'Heroku', url: '/guides/migrations/heroku' }, - { name: 'Render', url: '/guides/migrations/render' }, - { name: 'Amazon RDS', url: '/guides/migrations/amazon-rds' }, + { name: 'Overview', url: '/guides/deployment' }, + { + name: 'Environments', + items: [ + { name: 'Managing environments', url: '/guides/deployment/managing-environments' }, + { name: 'Branching', url: '/guides/deployment/branching' }, + ], + }, + { + name: 'Terraform', + items: [ + { name: 'Terraform provider', url: '/guides/deployment/terraform' }, + { name: 'Terraform tutorial', url: '/guides/deployment/terraform/tutorial' }, + { name: 'Terraform reference', url: '/guides/deployment/terraform/reference' }, + ], + }, + { + name: 'Production readiness', + items: [ + { + name: 'Shared responsibility model', + url: '/guides/deployment/shared-responsibility-model', + }, + { name: 'Maturity model', url: '/guides/deployment/maturity-model' }, + { name: 'Production checklist', url: '/guides/deployment/going-into-prod' }, + ], + }, + { + name: 'CI/CD', + items: [ + { + name: 'Generate types from your database', + url: '/guides/deployment/ci/generating-types', + }, + { name: 'Automated testing', url: '/guides/deployment/ci/testing' }, + { name: 'Back up your database', url: '/guides/deployment/ci/backups' }, + ], + }, + ], +} + +export const integrations: NavMenuConstant = { + title: 'Integrations', + icon: 'integrations', + url: '/guides/integrations', + items: [ + { + name: 'Overview', + url: '/guides/integrations', + }, + { + name: 'Vercel Marketplace', + url: '/guides/integrations/vercel-marketplace', + }, + { + name: 'Supabase Marketplace', + url: '/guides/integrations/supabase-marketplace', + }, + { + name: 'Build Your Own', + url: undefined, + items: [ + { + name: 'Build a Supabase integration', + url: '/guides/integrations/build-a-supabase-integration', + items: [ + { + name: 'OAuth scopes', + url: '/guides/integrations/build-a-supabase-integration/oauth-scopes', + }, + ], + }, + ], + }, + { name: 'Integrations', url: undefined, items: [] }, ], } @@ -2413,6 +2430,7 @@ export const references = [ ] export const navDataForMdx = { + migrationPages: MIGRATION_PAGES, nativeMobileLoginItems: NativeMobileLoginItems, phoneLoginsItems: PhoneLoginsItems, socialLoginItems: SocialLoginItems, diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx index 75f1e55df129b..d47562c92298a 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx @@ -1,5 +1,6 @@ import { memo } from 'react' +import type { NavMenuSection } from '../Navigation.types' import NavigationMenuGuideList from './NavigationMenuGuideList' import NavigationMenuRefList from './NavigationMenuRefList' import { useCloseMenuOnRouteChange } from './NavigationMenu.utils' @@ -15,10 +16,12 @@ enum MenuId { Storage = 'storage', Ai = 'ai', Platform = 'platform', + Deployment = 'deployment', + MonitoringTroubleshooting = 'monitoring_troubleshooting', Resources = 'resources', SelfHosting = 'self_hosting', Integrations = 'integrations', - Cli = 'supabase_cli', + LocalDevelopment = 'local_development', RefJavaScriptV1 = 'reference_javascript_v1', RefJavaScriptV2 = 'reference_javascript_v2', RefDartV1 = 'reference_dart_v1', @@ -82,6 +85,10 @@ const menus: Menu[] = [ id: MenuId.Functions, type: 'guide', }, + { + id: MenuId.MonitoringTroubleshooting, + type: 'guide', + }, { id: MenuId.Realtime, type: 'guide', @@ -111,7 +118,11 @@ const menus: Menu[] = [ type: 'guide', }, { - id: MenuId.Cli, + id: MenuId.LocalDevelopment, + type: 'guide', + }, + { + id: MenuId.Deployment, type: 'guide', }, { @@ -222,11 +233,11 @@ function getMenuById(id: MenuId) { return menus.find((menu) => menu.id === id) } -function getMenuElement(menu: Menu | undefined) { +function getMenuElement(menu: Menu | undefined, props?: any) { const menuType = menu?.type switch (menuType) { case 'guide': - return + return case 'reference': return ( { +const NavigationMenu = ({ + menuId, + additionalNavItems, +}: { + menuId: MenuId + additionalNavItems?: Partial[] +}) => { const level = menuId const menu = getMenuById(level) useCloseMenuOnRouteChange() - return getMenuElement(menu) + return getMenuElement(menu, { additionalNavItems }) } export { MenuId, getMenuById } diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.utils.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.utils.ts index 85934ed317ea8..a723fbceb93d0 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.utils.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.utils.ts @@ -109,16 +109,22 @@ export const getMenuId = (pathname: string | null) => { return MenuId.Api case pathname.startsWith('auth'): return MenuId.Auth - case pathname.startsWith('cli'): - return MenuId.Cli + case pathname.startsWith('local-development'): + return MenuId.LocalDevelopment case pathname.startsWith('database'): return MenuId.Database + case pathname.startsWith('deployment'): + return MenuId.Deployment case pathname.startsWith('functions'): return MenuId.Functions case pathname.startsWith('getting-started'): return MenuId.GettingStarted case pathname.startsWith('graphql'): return MenuId.Graphql + case pathname.startsWith('integrations'): + return MenuId.Integrations + case pathname.startsWith('monitoring-troubleshooting'): + return MenuId.MonitoringTroubleshooting case pathname.startsWith('platform'): return MenuId.Platform case pathname.startsWith('realtime'): diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenuGuideList.tsx b/apps/docs/components/Navigation/NavigationMenu/NavigationMenuGuideList.tsx index dc1d852bb3dc3..af40ab7e9e869 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenuGuideList.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenuGuideList.tsx @@ -2,15 +2,39 @@ import * as Accordion from '@radix-ui/react-accordion' +import { type NavMenuSection } from '../Navigation.types' import * as NavItems from './NavigationMenu.constants' import NavigationMenuGuideListItems from './NavigationMenuGuideListItems' import { usePathname } from 'next/navigation' -const NavigationMenuGuideList = ({ id }: { id: string }) => { +const NavigationMenuGuideList = ({ + id, + additionalNavItems, +}: { + id: string + additionalNavItems?: Partial[] +}) => { const pathname = usePathname() const firstLevelRoute = pathname?.split('/')?.slice(0, 4)?.join('/') - const menu = NavItems[id] + let menu = NavItems[id] + + if (id === 'integrations' && additionalNavItems) { + const integrationsListIndex = menu.items.findIndex((item) => item.name === 'Integrations') + if (integrationsListIndex !== -1) { + menu = { + ...menu, + items: [ + ...menu.items.slice(0, integrationsListIndex), + { + ...menu.items[integrationsListIndex], + items: [...menu.items[integrationsListIndex].items, ...additionalNavItems], + }, + ...menu.items.slice(integrationsListIndex + 1), + ], + } + } + } return ( (null) const LinkContainer = (props) => { + const isExternal = props.url.startsWith('https://') + return ( - + {props.children} ) diff --git a/apps/docs/content/guides/deployment.mdx b/apps/docs/content/guides/deployment.mdx new file mode 100644 index 0000000000000..c1c3808370255 --- /dev/null +++ b/apps/docs/content/guides/deployment.mdx @@ -0,0 +1,29 @@ +--- +title: Deployment +--- + +Deploying your app makes it live and accessible to users. Usually, you will deploy an app to at least two environments: a production environment for users and (one or multiple) staging or preview environments for developers. + +Supabase provides several options for environment management and deployment. + +## Environment management + +You can maintain separate development, staging, and production environments for Supabase: + +- **Development**: Develop with a local Supabase stack using the [Supabase CLI](/docs/guides/local-development). +- **Staging**: Use [branching](/docs/guides/deployment/branching) to create staging or preview environments. You can use persistent branches for a long-lived staging setup, or ephemeral branches for short-lived previews (which are often tied to a pull request). +- **Production**: If you have branching enabled, you can use the Supabase GitHub integration to automatically push your migration files when you merge a pull request. Alternatively, you can set up your own continuous deployment pipeline using the Supabase CLI. + + + +See the [self-hosting guides](/docs/guides/self-hosting) for instructions on hosting your own Supabase stack. + + + +## Deployment + +You can automate deployments using: + +- The [Supabase GitHub integration](/dashboard/project/_/settings/integrations) (with branching enabled) +- The [Supabase CLI](/docs/local-development/cli) in your own continuous deployment pipeline +- The [Supabase Terraform provider](/docs/guides/deployment/terraform) diff --git a/apps/docs/content/guides/platform/branching.mdx b/apps/docs/content/guides/deployment/branching.mdx similarity index 100% rename from apps/docs/content/guides/platform/branching.mdx rename to apps/docs/content/guides/deployment/branching.mdx diff --git a/apps/docs/content/guides/platform/going-into-prod.mdx b/apps/docs/content/guides/deployment/going-into-prod.mdx similarity index 100% rename from apps/docs/content/guides/platform/going-into-prod.mdx rename to apps/docs/content/guides/deployment/going-into-prod.mdx diff --git a/apps/docs/content/guides/cli/managing-environments.mdx b/apps/docs/content/guides/deployment/managing-environments.mdx similarity index 100% rename from apps/docs/content/guides/cli/managing-environments.mdx rename to apps/docs/content/guides/deployment/managing-environments.mdx diff --git a/apps/docs/content/guides/platform/maturity-model.mdx b/apps/docs/content/guides/deployment/maturity-model.mdx similarity index 100% rename from apps/docs/content/guides/platform/maturity-model.mdx rename to apps/docs/content/guides/deployment/maturity-model.mdx diff --git a/apps/docs/content/guides/platform/shared-responsibility-model.mdx b/apps/docs/content/guides/deployment/shared-responsibility-model.mdx similarity index 100% rename from apps/docs/content/guides/platform/shared-responsibility-model.mdx rename to apps/docs/content/guides/deployment/shared-responsibility-model.mdx diff --git a/apps/docs/content/guides/integrations.mdx b/apps/docs/content/guides/integrations.mdx new file mode 100644 index 0000000000000..579b0fdcd36da --- /dev/null +++ b/apps/docs/content/guides/integrations.mdx @@ -0,0 +1,13 @@ +--- +title: Integrations +--- + +Supabase integrates with many of your favorite third-party services. + +## Vercel Marketplace + +Create and manage your Supabase projects directly through Vercel. [Get started with Vercel](/docs/guides/integrations/vercel-marketplace). + +## Supabase Marketplace + +Browse tools for extending your Supabase project. [Browse the Supabase Marketplace](/partners/integrations). diff --git a/apps/docs/content/guides/platform/oauth-apps/build-a-supabase-integration.mdx b/apps/docs/content/guides/integrations/build-a-supabase-integration.mdx similarity index 100% rename from apps/docs/content/guides/platform/oauth-apps/build-a-supabase-integration.mdx rename to apps/docs/content/guides/integrations/build-a-supabase-integration.mdx diff --git a/apps/docs/content/guides/platform/oauth-apps/oauth-scopes.mdx b/apps/docs/content/guides/integrations/build-a-supabase-integration/oauth-scopes.mdx similarity index 100% rename from apps/docs/content/guides/platform/oauth-apps/oauth-scopes.mdx rename to apps/docs/content/guides/integrations/build-a-supabase-integration/oauth-scopes.mdx diff --git a/apps/docs/content/guides/platform/marketplace.mdx b/apps/docs/content/guides/integrations/supabase-marketplace.mdx similarity index 100% rename from apps/docs/content/guides/platform/marketplace.mdx rename to apps/docs/content/guides/integrations/supabase-marketplace.mdx diff --git a/apps/docs/content/guides/platform/vercel-marketplace.mdx b/apps/docs/content/guides/integrations/vercel-marketplace.mdx similarity index 100% rename from apps/docs/content/guides/platform/vercel-marketplace.mdx rename to apps/docs/content/guides/integrations/vercel-marketplace.mdx diff --git a/apps/docs/content/guides/local-development.mdx b/apps/docs/content/guides/local-development.mdx new file mode 100644 index 0000000000000..06ac6119d8eb3 --- /dev/null +++ b/apps/docs/content/guides/local-development.mdx @@ -0,0 +1,126 @@ +--- +title: Local Development & CLI +subtitle: Learn how to develop locally and use the Supabase CLI +--- + +Develop locally while running the Supabase stack on your machine. + +## Quickstart + +1. Install the Supabase CLI: + + + + ```sh + npm install supabase --save-dev + ``` + + + + ```sh + yarn add supabase --dev + ``` + + + + ```sh + pnpm add supabase --save-dev + ``` + + + + ```sh + brew install supabase/tap/supabase + ``` + + + +2. In your repo, initialize the Supabase project: + + + + ```sh + npx supabase init + ``` + + + + ```sh + yarn supabase init + ``` + + + + ```sh + pnpm supabase init + ``` + + + + ```sh + supabase init + ``` + + + + + +3. Start the Supabase stack: + + + + ```sh + npx supabase start + ``` + + + + ```sh + yarn supabase start + ``` + + + + ```sh + pnpm supabase start + ``` + + + + ```sh + supabase start + ``` + + + + + +4. View your local Supabase instance at [http://localhost:54323](http://localhost:54323). + +## Local Development + +Local development with Supabase allows you to work on your projects in a self-contained environment on your local machine. Working locally has several advantages: + +1. Faster development: You can make changes and see results instantly without waiting for remote deployments. +2. Offline work: You can continue development even without an internet connection. +3. Cost-effective: Local development is free and doesn't consume your project's quota. +4. Enhanced privacy: Sensitive data remains on your local machine during development. +5. Easy testing: You can experiment with different configurations and features without affecting your production environment. + +To get started with local development, you'll need to install the [Supabase CLI](#cli) and Docker. The Supabase CLI allows you to start and manage your local Supabase stack, while Docker is used to run the necessary services. + +Once set up, you can initialize a new Supabase project, start the local stack, and begin developing your application using local Supabase services. This includes access to a local PostgreSQL database, Auth, Storage, and other Supabase features. + +## CLI + +The Supabase CLI is a powerful tool that enables developers to manage their Supabase projects directly from the terminal. It provides a suite of commands for various tasks, including: + +- Setting up and managing local development environments +- Generating TypeScript types for your database schema +- Handling database migrations +- Managing environment variables and secrets +- Deploying your project to the Supabase platform + +With the CLI, you can streamline your development workflow, automate repetitive tasks, and maintain consistency across different environments. It's an essential tool for both local development and CI/CD pipelines. + +See the [CLI Getting Started guide](/docs/guides/local-development/cli/getting-started) for more information. diff --git a/apps/docs/content/guides/cli/getting-started.mdx b/apps/docs/content/guides/local-development/cli/getting-started.mdx similarity index 50% rename from apps/docs/content/guides/cli/getting-started.mdx rename to apps/docs/content/guides/local-development/cli/getting-started.mdx index 7ad87f57e14f8..6319a53ddf5a3 100644 --- a/apps/docs/content/guides/cli/getting-started.mdx +++ b/apps/docs/content/guides/local-development/cli/getting-started.mdx @@ -1,12 +1,13 @@ --- title: 'Supabase CLI' -description: 'The Supabase CLI provides tools to develop your project locally and deploy to the Supabase Platform.' -subtitle: 'The Supabase CLI provides tools to develop your project locally and deploy to the Supabase Platform.' +description: 'The Supabase CLI provides tools to develop your project locally, deploy to the Supabase Platform, and set up CI/CD workflows.' +subtitle: 'Develop locally, deploy to the Supabase Platform, and set up CI/CD workflows' --- -You can use the Supabase CLI to run the entire Supabase stack locally on your machine, simply by running `supabase init` (to create a new local project) and then `supabase start`. +The Supabase CLI enables you to run the entire Supabase stack locally, on your machine or in a CI environment. With just two commands, you can set up and start a new local project: -The Supabase CLI provides tools to develop your project locally, deploy to the Supabase Platform, handle database migrations, and generate types directly from your database schema. +1. `supabase init` to create a new local project +2. `supabase start` to launch the Supabase services ## Installing the Supabase CLI @@ -125,27 +126,21 @@ npm update supabase --save-dev If you have any Supabase containers running locally, stop them and delete their data volumes before proceeding with the upgrade. This ensures that Supabase managed services can apply new migrations on a clean state of the local database. - + Remember to save any local schema and data changes before stopping because the `--no-backup` flag will delete them. ```sh supabase db diff my_schema supabase db dump --local --data-only > supabase/seed.sql +supabase stop --no-backup ``` -```sh -supabase stop --no-backup -supabase start -``` - ## Running Supabase locally -The Supabase CLI uses Docker containers to manage the local development stack. To get started, - -- Install [Docker Desktop](https://docs.docker.com/desktop) and apply the following configurations +The Supabase CLI uses Docker containers to manage the local development stack. Follow the official guide to install and configure [Docker Desktop](https://docs.docker.com/desktop): + + +Alternately, you can use a different container tool that offers Docker compatible APIs. + +- [Rancher Desktop](https://rancherdesktop.io/) (macOS, Windows, Linux) +- [Podman](https://podman.io/) (macOS, Windows, Linux) +- [OrbStack](https://orbstack.dev/) (macOS) +- [colima](https://github.com/abiosoft/colima) (macOS) + + + Inside the folder where you want to create your project, run: ```bash @@ -196,27 +202,113 @@ supabase start This takes time on your first run because the CLI needs to download the Docker images to your local machine. The CLI includes the entire Supabase toolset, and a few additional images that are useful for local development (like a local SMTP server and a database diff tool). -The local development environment includes Supabase Studio, a graphical interface for working with your database, running by default on [localhost:54323](http://localhost:54323). +## Access your project's services + +Once all of the Supabase services are running, you'll see output containing your local Supabase credentials. It should look like this, with urls and keys that you'll use in your local project: + +``` + +Started supabase local development setup. + + API URL: http://localhost:54321 + DB URL: postgresql://postgres:postgres@localhost:54322/postgres + Studio URL: http://localhost:54323 + Inbucket URL: http://localhost:54324 + anon key: eyJh...... +service_role key: eyJh...... + +``` + + + + +```sh +# Default URL: +http://localhost:54323 +``` + +The local development environment includes Supabase Studio, a graphical interface for working with your database. ![Local Studio](/docs/img/guides/cli/local-studio.png) + + + +```sh +# Default URL: +postgresql://postgres:postgres@localhost:54322/postgres +``` + +The local Postgres instance can be accessed through [`psql`](https://www.postgresql.org/docs/current/app-psql.html) or any other Postgres client, such as [pgadmin](https://www.pgadmin.org/). For example: + +```bash +psql 'postgresql://postgres:postgres@localhost:54322/postgres' +``` + + + +To access the database from an edge function in your local Supabase setup, replace `localhost` with `host.docker.internal`. + + + + + + +```sh +# Default URL: +http://localhost:54321 +``` + +If you are accessing these services without the client libraries, you may need to pass the client keys as an `Authorization` header. Learn more about [JWT headers](/docs/learn/auth-deep-dive/auth-deep-dive-jwts). + +```sh +curl 'http://localhost:54321/rest/v1/' \ + -H "apikey: " \ + -H "Authorization: Bearer " + +http://localhost:54321/rest/v1/ # REST (PostgREST) +http://localhost:54321/realtime/v1/ # Realtime +http://localhost:54321/storage/v1/ # Storage +http://localhost:54321/auth/v1/ # Auth (GoTrue) +``` + + + +`` is provided when you run the command `supabase start`. + + + + + + +Local logs rely on the Supabase Analytics Server which accesses the docker logging driver by either volume mounting `/var/run/docker.sock` domain socket on Linux and macOS, or exposing `tcp://localhost:2375` daemon socket on Windows. These settings must be configured manually after [installing](/docs/guides/cli/getting-started#installing-the-supabase-cli) the Supabase CLI. + + + +For advanced logs analysis using the Logs Explorer, it is advised to use the BigQuery backend instead of the default Postgres backend. Read about the steps [here](/docs/reference/self-hosting-analytics/introduction#bigquery). + + + +All logs will be stored in the local database under the `_analytics` schema. + + + + ## Stopping local services -When you are finished working on your Supabase project, you can stop the stack with: +When you are finished working on your Supabase project, you can stop the stack (without resetting your local database): ```bash supabase stop ``` -## Full command reference - -The CLI provides a number of commands to help you develop your project locally and deploy to the Supabase Platform. You can find all commands inside the [CLI Reference](/docs/reference/cli/introduction) docs, including: +## Learn more -- [Project](/docs/reference/cli/supabase-projects) and [Organization](/docs/reference/cli/supabase-orgs) management -- [Database management](/docs/reference/cli/supabase-db) -- [Database migrations](/docs/reference/cli/supabase-migration) and [Database Branching](/docs/reference/cli/supabase-branches) -- [Database debugging tools](/docs/reference/cli/supabase-inspect-db-calls) -- [Edge Function management](/docs/reference/cli/supabase-functions) -- [Auth management](/docs/reference/cli/supabase-sso) -- [Types Generators](/docs/reference/cli/supabase-gen) -- [Testing](/docs/reference/cli/supabase-test) +- [CLI configuration](/docs/guides/local-development/cli/config) +- [CLI reference](/docs/reference/cli) diff --git a/apps/docs/content/guides/cli/testing-and-linting.mdx b/apps/docs/content/guides/local-development/cli/testing-and-linting.mdx similarity index 100% rename from apps/docs/content/guides/cli/testing-and-linting.mdx rename to apps/docs/content/guides/local-development/cli/testing-and-linting.mdx diff --git a/apps/docs/content/guides/cli/customizing-email-templates.mdx b/apps/docs/content/guides/local-development/customizing-email-templates.mdx similarity index 100% rename from apps/docs/content/guides/cli/customizing-email-templates.mdx rename to apps/docs/content/guides/local-development/customizing-email-templates.mdx diff --git a/apps/docs/content/guides/cli/managing-config.mdx b/apps/docs/content/guides/local-development/managing-config.mdx similarity index 100% rename from apps/docs/content/guides/cli/managing-config.mdx rename to apps/docs/content/guides/local-development/managing-config.mdx diff --git a/apps/docs/content/guides/cli/local-development.mdx b/apps/docs/content/guides/local-development/overview.mdx similarity index 60% rename from apps/docs/content/guides/cli/local-development.mdx rename to apps/docs/content/guides/local-development/overview.mdx index 3846335c3e3a1..d012756bad247 100644 --- a/apps/docs/content/guides/cli/local-development.mdx +++ b/apps/docs/content/guides/local-development/overview.mdx @@ -1,169 +1,17 @@ --- -id: 'local-development' -title: 'Local Development' -description: 'How to use Supabase on your local development machine.' -subtitle: 'How to use Supabase on your local development machine.' +id: 'overview' +title: 'Local development with schema migrations' +description: 'Develop locally with the Supabase CLI and schema migrations.' +subtitle: 'Develop locally with the Supabase CLI and schema migrations.' video: 'https://www.youtube-nocookie.com/v/vyHyYpvjaks' tocVideo: 'vyHyYpvjaks' --- Supabase is a flexible platform that lets you decide how you want to build your projects. You can use the Dashboard directly to get up and running quickly, or use a proper local setup. We suggest you work locally and deploy your changes to a linked project on the [Supabase Platform](https://app.supabase.io/). -Doing things directly on the platform via the [Dashboard](https://app.supabase.io/) is fine when you're getting started, but it's a good idea to move to a proper local workflow before you get too far. Working locally, generating migrations as you change your tables, and applying those migrations to a linked project on the [Platform](https://app.supabase.io/) keeps everything nicely organized as you grow. +Develop locally using the CLI to run a local Supabase stack. You can use the integrated Studio Dashboard to make changes, then capture your changes in schema migration files, which can be saved in version control. -## Why develop locally? - -The Dashboard provides a wide range of features for setting up your project: creating tables, adding columns, changing existing columns, creating views, setting up RLS policies, and more. Given all of the Dashboard's capabilities, you might question the need to work locally. Here's a few advantages to working this way: - -1. **Faster Development**: Developing locally allows you to work without any network latency or internet disruptions. - -2. **Easier Collaboration**: Developing locally can make it easier to collaborate with others on the same project. - -3. **Cost-Effective**: Supabase provides a generous Free Plan and gives you two free projects to get started. But what if you need more than two? When you develop locally, you can spin up unlimited local projects and link them with live projects when you're ready to launch. - -4. **Configuration in code**: If you directly change your tables via the Dashboard, none of that gets captured in code. If you follow these local development practices, you'll store all of your table schemas in code. - -5. **Work offline**: Need to work from a train? A plane? An automobile? No problem. Developing your project locally allows you to work offline. - -## Log in to the Supabase CLI - -Log in if you are planning to deploy your project to the Supabase Platform. This step is optional and is not required to use the Supabase CLI. - - - -```bash Terminal -supabase login -``` - -```bash NPX -npx supabase login -``` - - - -## Initialize your project - -Create a new folder for your project and start a new git repository: - -```bash -# create your project folder -mkdir your-project - -# move into the new folder -cd your-project - -# start a new git repository — important, don't skip this step -git init -``` - -## Start Supabase services - -[Initialize](/docs/reference/cli/usage#supabase-init) Supabase to set up the configuration for developing your project locally: - -```bash -supabase init -``` - -Make sure Docker is running. - - - -There are a number of different projects available to download Docker from: - -- [Docker Desktop](https://docs.docker.com/get-docker/) (macOS, Windows, Linux) -- [Rancher Desktop](https://rancherdesktop.io/) (macOS, Windows, Linux) -- [OrbStack](https://orbstack.dev/) (macOS) -- [colima](https://github.com/abiosoft/colima) (macOS) - - - -The [start](/docs/reference/cli/usage#supabase-start) command uses Docker to start the Supabase [services](/docs/guides/getting-started/architecture). -This command may take a while to run if this is the first time using the CLI. - -```bash -supabase start -``` - -Once all of the Supabase services are running, you'll see output containing your local Supabase credentials. It should look like this, with urls and keys that you'll use in your local project: - -``` - -Started supabase local development setup. - - API URL: http://localhost:54321 - DB URL: postgresql://postgres:postgres@localhost:54322/postgres - Studio URL: http://localhost:54323 - Inbucket URL: http://localhost:54324 - anon key: eyJh...... -service_role key: eyJh...... - -``` - -You can use the [`supabase stop`](/docs/reference/cli/usage#supabase-stop) command at any time to stop all services (without resetting your local database). Use `supabase stop --no-backup` to stop all services and reset your local database. - -## Access your project's services - -You can now visit your local Dashboard at [http://localhost:54323](http://localhost:54323), and access the database directly with any Postgres client via `postgresql://postgres:postgres@localhost:54322/postgres`. - - - - -```sh -# Default URL: -postgresql://postgres:postgres@localhost:54322/postgres -``` - -The local Postgres instance can be accessed through [`psql`](https://www.postgresql.org/docs/current/app-psql.html) -or any other Postgres client, such as [pgadmin](https://www.pgadmin.org/). - -For example: - -```bash -psql 'postgresql://postgres:postgres@localhost:54322/postgres' -``` - - - -To access the database from an edge function in your local Supabase setup, replace `localhost` with `host.docker.internal`. - - - - - - -```sh -# Default URL: -http://localhost:54321 -``` - -If you are accessing these services without the client libraries, you may need to pass the client keys as an `Authorization` header. -Learn more about [JWT headers](/docs/learn/auth-deep-dive/auth-deep-dive-jwts). - -```sh -curl 'http://localhost:54321/rest/v1/' \ - -H "apikey: " \ - -H "Authorization: Bearer " - -http://localhost:54321/rest/v1/ # REST (PostgREST) -http://localhost:54321/realtime/v1/ # Realtime -http://localhost:54321/storage/v1/ # Storage -http://localhost:54321/auth/v1/ # Auth (GoTrue) -``` - - - -`` is provided when you run the command `supabase start`. - - - - - +Alternatively, if you're comfortable with migration files and SQL, you can write your own migrations and push them to the local database for testing before sharing your changes. ## Database migrations @@ -372,6 +220,20 @@ The last step is deploying these changes to a live Supabase project. You've been developing your project locally, making changes to your tables via migrations. It's time to deploy your project to the Supabase Platform and start scaling up to millions of users! Head over to [Supabase](https://supabase.com/dashboard) and create a new project to deploy to. +### Log in to the Supabase CLI + + + +```bash Terminal +supabase login +``` + +```bash npx +npx supabase login +``` + + + ### Link your project Associate your project with your remote project using [`supabase link`](/docs/reference/cli/usage#supabase-link). @@ -457,19 +319,21 @@ Your RLS policies on storage buckets can be pulled locally by specifying `storag supabase db pull --schema storage ``` -The buckets and objects themselves are rows in the storage schema so they won't be pulled automatically. - -### Local logging - -Local logs rely on the Supabase Analytics Server which accesses the docker logging driver by either volume mounting `/var/run/docker.sock` domain socket on Linux and macOS, or exposing `tcp://localhost:2375` daemon socket on Windows. These settings must be configured manually after [installing](/docs/guides/cli/getting-started#installing-the-supabase-cli) the Supabase CLI. - - +The buckets and objects themselves are rows in the storage tables so they won't appear in your schema. You can instead define them via `supabase/config.toml` file. For example, -For advanced logs analysis using the Logs Explorer, it is advised to use the BigQuery backend instead of the default Postgres backend. Read about the steps [here](/docs/reference/self-hosting-analytics/introduction#bigquery). +```bash supabase/config.toml +[storage.buckets.images] +public = false +file_size_limit = "50MiB" +allowed_mime_types = ["image/png", "image/jpeg"] +objects_path = "./images" +``` - +This will upload files from `supabase/images` directory to a bucket named `images` in your project with one command. -All logs will be stored in the local database under the `_analytics` schema. +```bash +supabase seed buckets +``` ## Limitations and considerations diff --git a/apps/docs/content/guides/cli/seeding-your-database.mdx b/apps/docs/content/guides/local-development/seeding-your-database.mdx similarity index 100% rename from apps/docs/content/guides/cli/seeding-your-database.mdx rename to apps/docs/content/guides/local-development/seeding-your-database.mdx diff --git a/apps/docs/content/guides/monitoring-troubleshooting.mdx b/apps/docs/content/guides/monitoring-troubleshooting.mdx new file mode 100644 index 0000000000000..bbe769214af84 --- /dev/null +++ b/apps/docs/content/guides/monitoring-troubleshooting.mdx @@ -0,0 +1,9 @@ +--- +title: Monitoring & Troubleshooting +--- + +Monitoring your project can help you identify issues and fix them quickly. This section provides guidance on: + +- Monitoring errors +- Working with logs in Supabase +- Troubleshooting common issues with the platform diff --git a/apps/docs/content/guides/platform/advanced-log-filtering.mdx b/apps/docs/content/guides/monitoring-troubleshooting/advanced-log-filtering.mdx similarity index 100% rename from apps/docs/content/guides/platform/advanced-log-filtering.mdx rename to apps/docs/content/guides/monitoring-troubleshooting/advanced-log-filtering.mdx diff --git a/apps/docs/content/guides/platform/exhaust-cpu.mdx b/apps/docs/content/guides/monitoring-troubleshooting/exhaust-cpu.mdx similarity index 100% rename from apps/docs/content/guides/platform/exhaust-cpu.mdx rename to apps/docs/content/guides/monitoring-troubleshooting/exhaust-cpu.mdx diff --git a/apps/docs/content/guides/platform/exhaust-disk-io.mdx b/apps/docs/content/guides/monitoring-troubleshooting/exhaust-disk-io.mdx similarity index 100% rename from apps/docs/content/guides/platform/exhaust-disk-io.mdx rename to apps/docs/content/guides/monitoring-troubleshooting/exhaust-disk-io.mdx diff --git a/apps/docs/content/guides/platform/exhaust-ram.mdx b/apps/docs/content/guides/monitoring-troubleshooting/exhaust-ram.mdx similarity index 100% rename from apps/docs/content/guides/platform/exhaust-ram.mdx rename to apps/docs/content/guides/monitoring-troubleshooting/exhaust-ram.mdx diff --git a/apps/docs/content/guides/platform/exhaust-swap.mdx b/apps/docs/content/guides/monitoring-troubleshooting/exhaust-swap.mdx similarity index 100% rename from apps/docs/content/guides/platform/exhaust-swap.mdx rename to apps/docs/content/guides/monitoring-troubleshooting/exhaust-swap.mdx diff --git a/apps/docs/content/guides/platform/http-status-codes.mdx b/apps/docs/content/guides/monitoring-troubleshooting/http-status-codes.mdx similarity index 100% rename from apps/docs/content/guides/platform/http-status-codes.mdx rename to apps/docs/content/guides/monitoring-troubleshooting/http-status-codes.mdx diff --git a/apps/docs/content/guides/platform/log-drains.mdx b/apps/docs/content/guides/monitoring-troubleshooting/log-drains.mdx similarity index 100% rename from apps/docs/content/guides/platform/log-drains.mdx rename to apps/docs/content/guides/monitoring-troubleshooting/log-drains.mdx diff --git a/apps/docs/content/guides/platform/logs.mdx b/apps/docs/content/guides/monitoring-troubleshooting/logs.mdx similarity index 100% rename from apps/docs/content/guides/platform/logs.mdx rename to apps/docs/content/guides/monitoring-troubleshooting/logs.mdx diff --git a/apps/docs/content/guides/platform/metrics.mdx b/apps/docs/content/guides/monitoring-troubleshooting/metrics.mdx similarity index 100% rename from apps/docs/content/guides/platform/metrics.mdx rename to apps/docs/content/guides/monitoring-troubleshooting/metrics.mdx diff --git a/apps/docs/content/guides/platform/sentry-monitoring.mdx b/apps/docs/content/guides/monitoring-troubleshooting/sentry-monitoring.mdx similarity index 100% rename from apps/docs/content/guides/platform/sentry-monitoring.mdx rename to apps/docs/content/guides/monitoring-troubleshooting/sentry-monitoring.mdx diff --git a/apps/docs/content/guides/platform/troubleshooting.mdx b/apps/docs/content/guides/monitoring-troubleshooting/troubleshooting.mdx similarity index 100% rename from apps/docs/content/guides/platform/troubleshooting.mdx rename to apps/docs/content/guides/monitoring-troubleshooting/troubleshooting.mdx diff --git a/apps/docs/content/guides/platform/migrating-to-supabase.mdx b/apps/docs/content/guides/platform/migrating-to-supabase.mdx new file mode 100644 index 0000000000000..494520af8aff0 --- /dev/null +++ b/apps/docs/content/guides/platform/migrating-to-supabase.mdx @@ -0,0 +1,19 @@ +--- +title: Migrating to Supabase +--- + +Learn how to migrate to Supabase from another database service. + +## Migration guides + + + {(migrationPages) => ( +
+ {migrationPages.map((page) => ( + + + + ))} +
+ )} +
diff --git a/apps/docs/content/guides/resources/migrating-to-supabase/amazon-rds.mdx b/apps/docs/content/guides/platform/migrating-to-supabase/amazon-rds.mdx similarity index 100% rename from apps/docs/content/guides/resources/migrating-to-supabase/amazon-rds.mdx rename to apps/docs/content/guides/platform/migrating-to-supabase/amazon-rds.mdx diff --git a/apps/docs/content/guides/resources/migrating-to-supabase/auth0.mdx b/apps/docs/content/guides/platform/migrating-to-supabase/auth0.mdx similarity index 100% rename from apps/docs/content/guides/resources/migrating-to-supabase/auth0.mdx rename to apps/docs/content/guides/platform/migrating-to-supabase/auth0.mdx diff --git a/apps/docs/content/guides/resources/migrating-to-supabase/firebase-auth.mdx b/apps/docs/content/guides/platform/migrating-to-supabase/firebase-auth.mdx similarity index 100% rename from apps/docs/content/guides/resources/migrating-to-supabase/firebase-auth.mdx rename to apps/docs/content/guides/platform/migrating-to-supabase/firebase-auth.mdx diff --git a/apps/docs/content/guides/resources/migrating-to-supabase/firebase-storage.mdx b/apps/docs/content/guides/platform/migrating-to-supabase/firebase-storage.mdx similarity index 100% rename from apps/docs/content/guides/resources/migrating-to-supabase/firebase-storage.mdx rename to apps/docs/content/guides/platform/migrating-to-supabase/firebase-storage.mdx diff --git a/apps/docs/content/guides/resources/migrating-to-supabase/firestore-data.mdx b/apps/docs/content/guides/platform/migrating-to-supabase/firestore-data.mdx similarity index 100% rename from apps/docs/content/guides/resources/migrating-to-supabase/firestore-data.mdx rename to apps/docs/content/guides/platform/migrating-to-supabase/firestore-data.mdx diff --git a/apps/docs/content/guides/resources/migrating-to-supabase/heroku.mdx b/apps/docs/content/guides/platform/migrating-to-supabase/heroku.mdx similarity index 100% rename from apps/docs/content/guides/resources/migrating-to-supabase/heroku.mdx rename to apps/docs/content/guides/platform/migrating-to-supabase/heroku.mdx diff --git a/apps/docs/content/guides/resources/migrating-to-supabase/mssql.mdx b/apps/docs/content/guides/platform/migrating-to-supabase/mssql.mdx similarity index 100% rename from apps/docs/content/guides/resources/migrating-to-supabase/mssql.mdx rename to apps/docs/content/guides/platform/migrating-to-supabase/mssql.mdx diff --git a/apps/docs/content/guides/resources/migrating-to-supabase/mysql.mdx b/apps/docs/content/guides/platform/migrating-to-supabase/mysql.mdx similarity index 100% rename from apps/docs/content/guides/resources/migrating-to-supabase/mysql.mdx rename to apps/docs/content/guides/platform/migrating-to-supabase/mysql.mdx diff --git a/apps/docs/content/guides/resources/migrating-to-supabase/postgres.mdx b/apps/docs/content/guides/platform/migrating-to-supabase/postgres.mdx similarity index 100% rename from apps/docs/content/guides/resources/migrating-to-supabase/postgres.mdx rename to apps/docs/content/guides/platform/migrating-to-supabase/postgres.mdx diff --git a/apps/docs/content/guides/resources/migrating-to-supabase/render.mdx b/apps/docs/content/guides/platform/migrating-to-supabase/render.mdx similarity index 100% rename from apps/docs/content/guides/resources/migrating-to-supabase/render.mdx rename to apps/docs/content/guides/platform/migrating-to-supabase/render.mdx diff --git a/apps/docs/content/guides/platform/migrating-within-supabase.mdx b/apps/docs/content/guides/platform/migrating-within-supabase.mdx new file mode 100644 index 0000000000000..d441ac7bc1355 --- /dev/null +++ b/apps/docs/content/guides/platform/migrating-within-supabase.mdx @@ -0,0 +1,157 @@ +--- +title: Migrating within Supabase +subtitle: Migrate from one Supabase project to another +--- + +Migrating projects can be achieved using the Supabase CLI. This is particularly useful for older projects (e.g. to use a newer Postgres version). + +### Before you begin + +- Install [Postgres](https://www.postgresql.org/download/) so you can run `psql` and `pg_dump`. +- Install the latest version of [Supabase CLI](/docs/guides/cli#installation). +- Create a new [Supabase project](https://supabase.com/dashboard). +- Install [Docker Desktop](https://www.docker.com) for your platform. +- Set environment variables for the old project's database URL as `$OLD_DB_URL` and the new project's as `$NEW_DB_URL`. + To find the database URL for a project, go to the project's dashboard page [Project Settings/Database](https://supabase.com/dashboard/project/_/settings/database) and look under `Connection string`. If your network provider supports IPv6, you can disable `Use connection pooling`. Otherwise, enable `Use connection pooling`. For the pooler mode, `Transaction` will work. + +### Backup your old database + +1. Run the following command from your terminal: + +```bash +supabase db dump --db-url "$OLD_DB_URL" -f roles.sql --role-only +supabase db dump --db-url "$OLD_DB_URL" -f schema.sql +supabase db dump --db-url "$OLD_DB_URL" -f data.sql --use-copy --data-only +``` + +### Restore to your new project + +In your new project: + +1. Enable [Database Webhooks](https://supabase.com/dashboard/project/_/database/hooks) if you enabled them in your old project. +2. Enable any [extensions](https://supabase.com/dashboard/project/_/database/extensions) that were enabled in your old project. + +If you use [column encryption](/docs/guides/database/column-encryption), first copy the root encryption key to your new project using your [Personal Access Token](https://supabase.com/dashboard/account/tokens). + +```bash +export OLD_PROJECT_REF="" +export NEW_PROJECT_REF="" +export SUPABASE_ACCESS_TOKEN="" + +curl "https://api.supabase.com/v1/projects/$OLD_PROJECT_REF/pgsodium" \ + -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" | +curl "https://api.supabase.com/v1/projects/$NEW_PROJECT_REF/pgsodium" \ + -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \ + -X PUT --json @- +``` + +Then run the following command from your terminal: + +```bash +psql \ + --single-transaction \ + --variable ON_ERROR_STOP=1 \ + --file roles.sql \ + --file schema.sql \ + --command 'SET session_replication_role = replica' \ + --file data.sql \ + --dbname "$NEW_DB_URL" +``` + +Setting the `session_replication_role` to `replica` disables all triggers so that columns are not double encrypted. + +Troubleshooting notes: + +- If you have created any [custom roles](https://supabase.com/dashboard/project/_/database/roles) with `login` attribute, you have to manually set their passwords in the new project. +- If you run into any permission errors related to `supabase_admin` during restore, edit the `schema.sql` file and comment out any lines containing `ALTER ... OWNER TO "supabase_admin"`. + +### Preserving migration history + +If you were using Supabase CLI for managing migrations on your old database and would like to preserve the migration history in your newly restored project, you need to insert the migration records separately using the following commands. + +```bash +supabase db dump --db-url "$OLD_DB_URL" -f history_schema.sql --schema supabase_migrations +supabase db dump --db-url "$OLD_DB_URL" -f history_data.sql --use-copy --data-only --schema supabase_migrations +psql \ + --single-transaction \ + --variable ON_ERROR_STOP=1 \ + --file history_schema.sql \ + --file history_data.sql \ + --dbname "$NEW_DB_URL" +``` + +### Schema changes to `auth` and `storage` + +If you have modified the `auth` and `storage` schemas in your old project, such as adding triggers or RLS policies, you have to restore them separately. The Supabase CLI can help you diff the changes to these schemas using the following commands. + +```bash +supabase link --project-ref "$OLD_PROJECT_REF" +supabase db diff --linked --schema auth,storage > changes.sql +``` + +### Enable publication on tables + +Replication for Realtime is disabled for all tables in your new project. On the [Publications](https://supabase.com/dashboard/project/_/database/publications) page in the Dashboard, select your new project and enable replication for tables that were enabled in your old project. + +### Migrate storage objects + +The new project has the old project's Storage buckets, but the Storage objects need to be migrated manually. Use this script to move storage objects from one project to another. + +```js +// npm install @supabase/supabase-js@1 +const { createClient } = require('@supabase/supabase-js') + +const OLD_PROJECT_URL = 'https://xxx.supabase.co' +const OLD_PROJECT_SERVICE_KEY = 'old-project-service-key-xxx' + +const NEW_PROJECT_URL = 'https://yyy.supabase.co' +const NEW_PROJECT_SERVICE_KEY = 'new-project-service-key-yyy' + +;(async () => { + const oldSupabaseRestClient = createClient(OLD_PROJECT_URL, OLD_PROJECT_SERVICE_KEY, { + db: { + schema: 'storage', + }, + }) + const oldSupabaseClient = createClient(OLD_PROJECT_URL, OLD_PROJECT_SERVICE_KEY) + const newSupabaseClient = createClient(NEW_PROJECT_URL, NEW_PROJECT_SERVICE_KEY) + + // make sure you update max_rows in postgrest settings if you have a lot of objects + // or paginate here + const { data: oldObjects, error } = await oldSupabaseRestClient.from('objects').select() + if (error) { + console.log('error getting objects from old bucket') + throw error + } + + for (const objectData of oldObjects) { + console.log(`moving ${objectData.id}`) + try { + const { data, error: downloadObjectError } = await oldSupabaseClient.storage + .from(objectData.bucket_id) + .download(objectData.name) + if (downloadObjectError) { + throw downloadObjectError + } + + const { _, error: uploadObjectError } = await newSupabaseClient.storage + .from(objectData.bucket_id) + .upload(objectData.name, data, { + upsert: true, + contentType: objectData.metadata.mimetype, + cacheControl: objectData.metadata.cacheControl, + }) + if (uploadObjectError) { + throw uploadObjectError + } + } catch (err) { + console.log('error moving ', objectData) + console.log(err) + } + } +})() +``` + +### Transfer to a different organization + +Note that project migration is for transferring your projects to different regions. If you need to move your project to a different organization without touching the infrastructure, see [project transfers](/docs/guides/platform/project-transfer). diff --git a/apps/docs/content/guides/platform/migrating-and-upgrading-projects.mdx b/apps/docs/content/guides/platform/upgrading.mdx similarity index 53% rename from apps/docs/content/guides/platform/migrating-and-upgrading-projects.mdx rename to apps/docs/content/guides/platform/upgrading.mdx index 3ad20c7278fd0..0964f9281e580 100644 --- a/apps/docs/content/guides/platform/migrating-and-upgrading-projects.mdx +++ b/apps/docs/content/guides/platform/upgrading.mdx @@ -1,18 +1,20 @@ --- -id: 'migrating-and-upgrading-projects' -title: 'Migrating and Upgrading Projects' -description: 'Upgrade your project to the latest version of Supabase.' -sidebar_label: 'Migrating and upgrading' +title: Upgrading --- -Supabase ships fast and we endeavor to add all new features to existing projects wherever possible. -In some cases, access to new features require upgrading or migrating your Supabase project. +Supabase ships fast and we endeavor to add all new features to existing projects wherever possible. In some cases, access to new features require upgrading or migrating your Supabase project. -## Upgrade your project +You can upgrade your project using `pg_upgrade` or by pausing and restoring your project. -There are a few methods available to upgrade your project. + + -### `pg_upgrade` +The Migrating and Upgrading guide has been divided into two sections. To migrate between Supabase projects, see [Migrating within Supabase](/docs/guides/platform/migrating-within-supabase). + + + + +## `pg_upgrade` @@ -29,7 +31,7 @@ Additionally, if a pg_upgrade upgrade should fail, your original DB would be bro As a rough rule of thumb, pg_upgrade operates at ~100mbps (when executing an upgrade on your data). Using the size of your database, you can use this metric to derive an approximate sense of the downtime window necessary for the upgrade. During this window, you should plan for your DB and associated services to be unavailable. -### Pause + restore +## Pause and restore @@ -145,158 +147,3 @@ As part of the upgrade process, maintenance operations such as [vacuuming](https #### Post-upgrade validation Supabase performs extensive pre- and post-upgrade validations to ensure that the database has been correctly upgraded. However, you should plan for your own application-level validations, as there might be changes you might not have anticipated, and this should be budgeted for when planning your downtime window. - -## Migrate your project - -Migrating projects can be achieved using the Supabase CLI. This is particularly useful for older projects (e.g. to use a newer Postgres version). - -### Before you begin - -- Install [Postgres](https://www.postgresql.org/download/) so you can run `psql` and `pg_dump`. -- Install the latest version of [Supabase CLI](/docs/guides/cli#installation). -- Create a new [Supabase project](https://supabase.com/dashboard). -- Install [Docker Desktop](https://www.docker.com) for your platform. -- Set environment variables for the old project's database URL as `$OLD_DB_URL` and the new project's as `$NEW_DB_URL`. - To find the database URL for a project, go to the project's dashboard page [Project Settings/Database](https://supabase.com/dashboard/project/_/settings/database) and look under `Connection string`. If your network provider supports IPv6, you can disable `Use connection pooling`. Otherwise, enable `Use connection pooling`. For the pooler mode, `Transaction` will work. - -### Backup your old database - -1. Run the following command from your terminal: - -```bash -supabase db dump --db-url "$OLD_DB_URL" -f roles.sql --role-only -supabase db dump --db-url "$OLD_DB_URL" -f schema.sql -supabase db dump --db-url "$OLD_DB_URL" -f data.sql --use-copy --data-only -``` - -### Restore to your new project - -In your new project: - -1. Enable [Database Webhooks](https://supabase.com/dashboard/project/_/database/hooks) if you enabled them in your old project. -2. Enable any [extensions](https://supabase.com/dashboard/project/_/database/extensions) that were enabled in your old project. - -If you use [column encryption](/docs/guides/database/column-encryption), first copy the root encryption key to your new project using your [Personal Access Token](https://supabase.com/dashboard/account/tokens). - -```bash -export OLD_PROJECT_REF="" -export NEW_PROJECT_REF="" -export SUPABASE_ACCESS_TOKEN="" - -curl "https://api.supabase.com/v1/projects/$OLD_PROJECT_REF/pgsodium" \ - -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" | -curl "https://api.supabase.com/v1/projects/$NEW_PROJECT_REF/pgsodium" \ - -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \ - -X PUT --json @- -``` - -Then run the following command from your terminal: - -```bash -psql \ - --single-transaction \ - --variable ON_ERROR_STOP=1 \ - --file roles.sql \ - --file schema.sql \ - --command 'SET session_replication_role = replica' \ - --file data.sql \ - --dbname "$NEW_DB_URL" -``` - -Setting the `session_replication_role` to `replica` disables all triggers so that columns are not double encrypted. - -Troubleshooting notes: - -- If you have created any [custom roles](https://supabase.com/dashboard/project/_/database/roles) with `login` attribute, you have to manually set their passwords in the new project. -- If you run into any permission errors related to `supabase_admin` during restore, edit the `schema.sql` file and comment out any lines containing `ALTER ... OWNER TO "supabase_admin"`. - -### Preserving migration history - -If you were using Supabase CLI for managing migrations on your old database and would like to preserve the migration history in your newly restored project, you need to insert the migration records separately using the following commands. - -```bash -supabase db dump --db-url "$OLD_DB_URL" -f history_schema.sql --schema supabase_migrations -supabase db dump --db-url "$OLD_DB_URL" -f history_data.sql --use-copy --data-only --schema supabase_migrations -psql \ - --single-transaction \ - --variable ON_ERROR_STOP=1 \ - --file history_schema.sql \ - --file history_data.sql \ - --dbname "$NEW_DB_URL" -``` - -### Schema changes to `auth` and `storage` - -If you have modified the `auth` and `storage` schemas in your old project, such as adding triggers or RLS policies, you have to restore them separately. The Supabase CLI can help you diff the changes to these schemas using the following commands. - -```bash -supabase link --project-ref "$OLD_PROJECT_REF" -supabase db diff --linked --schema auth,storage > changes.sql -``` - -### Enable publication on tables - -Replication for Realtime is disabled for all tables in your new project. On the [Publications](https://supabase.com/dashboard/project/_/database/publications) page in the Dashboard, select your new project and enable replication for tables that were enabled in your old project. - -### Migrate storage objects - -The new project has the old project's Storage buckets, but the Storage objects need to be migrated manually. Use this script to move storage objects from one project to another. - -```js -// npm install @supabase/supabase-js@1 -const { createClient } = require('@supabase/supabase-js') - -const OLD_PROJECT_URL = 'https://xxx.supabase.co' -const OLD_PROJECT_SERVICE_KEY = 'old-project-service-key-xxx' - -const NEW_PROJECT_URL = 'https://yyy.supabase.co' -const NEW_PROJECT_SERVICE_KEY = 'new-project-service-key-yyy' - -;(async () => { - const oldSupabaseRestClient = createClient(OLD_PROJECT_URL, OLD_PROJECT_SERVICE_KEY, { - db: { - schema: 'storage', - }, - }) - const oldSupabaseClient = createClient(OLD_PROJECT_URL, OLD_PROJECT_SERVICE_KEY) - const newSupabaseClient = createClient(NEW_PROJECT_URL, NEW_PROJECT_SERVICE_KEY) - - // make sure you update max_rows in postgrest settings if you have a lot of objects - // or paginate here - const { data: oldObjects, error } = await oldSupabaseRestClient.from('objects').select() - if (error) { - console.log('error getting objects from old bucket') - throw error - } - - for (const objectData of oldObjects) { - console.log(`moving ${objectData.id}`) - try { - const { data, error: downloadObjectError } = await oldSupabaseClient.storage - .from(objectData.bucket_id) - .download(objectData.name) - if (downloadObjectError) { - throw downloadObjectError - } - - const { _, error: uploadObjectError } = await newSupabaseClient.storage - .from(objectData.bucket_id) - .upload(objectData.name, data, { - upsert: true, - contentType: objectData.metadata.mimetype, - cacheControl: objectData.metadata.cacheControl, - }) - if (uploadObjectError) { - throw uploadObjectError - } - } catch (err) { - console.log('error moving ', objectData) - console.log(err) - } - } -})() -``` - -### Transfer to a different organization - -Note that project migration is for transferring your projects to different regions. If you need to move your project to a different organization without touching the infrastructure, see [project transfers](/docs/guides/platform/project-transfer). diff --git a/apps/docs/content/guides/resources/examples.mdx b/apps/docs/content/guides/resources/examples.mdx deleted file mode 100644 index 177df12f0c33a..0000000000000 --- a/apps/docs/content/guides/resources/examples.mdx +++ /dev/null @@ -1,173 +0,0 @@ ---- -id: 'examples' -title: 'Examples and Resources' -description: 'Examples you can use to get started with Supabase' -video: 'https://www.youtube.com/v/7uKQBl9uZ00' ---- - -{/* */} - -We have a [set of examples](https://github.com/supabase/supabase/tree/master/examples) in our [main repository](https://github.com/supabase/supabase) to help you get started. - -## Featured - -## Build a Twitter clone with the Next.js App Router and Supabase - -By [Jon Meyers](https://twitter.com/jonmeyers_io) - - - Build a Twitter Clone with the Next.js App Router and Supabase - - -### Supabase crash course - -By [Traversy Media](https://www.youtube.com/watch?v=7uKQBl9uZ00). - -
- -
- -### Build an app with Supabase and Next.js - -By [@jlengstorf](https://twitter.com/jlengstorf) and [@jonmeyers_io](https://twitter.com/jonmeyers_io). - -
- -
- -### Is Supabase legit - -By [Fireship](https://www.youtube.com/watch?v=WiwfiVdfRIc). - -
- -
- -## Official examples - -### Todo list - -Build a basic Todo List with Supabase and your favorite frontend framework: - -- [Expo Todo List.](https://github.com/supabase/examples/tree/main/supabase-js-v1/todo-list/expo-todo-list) -- [Next.js Todo List.](https://github.com/supabase/supabase/tree/master/examples/todo-list/nextjs-todo-list) -- [React Todo List.](https://github.com/supabase/examples/tree/main/supabase-js-v1/todo-list/react-todo-list) -- [Svelte Todo List.](https://github.com/supabase/supabase/tree/master/examples/todo-list/sveltejs-todo-list) -- [Vue 3 Todo List (Typescript).](https://github.com/supabase/examples/tree/main/supabase-js-v1/todo-list/vue3-ts-todo-list) -- [Angular Todo List.](https://github.com/supabase/examples/tree/main/supabase-js-v1/todo-list/angular-todo-list) -- [Nuxt 3 Todo List.](https://github.com/nuxt-modules/supabase/tree/main/demo) - -### Auth examples - -- [Supabase Auth with vanilla JavaScript.](https://github.com/supabase/examples/tree/main/supabase-js-v1/auth/javascript-auth). Use Supabase without any frontend frameworks. -- [Supabase Auth with Next.js](https://github.com/supabase/supabase/tree/master/examples/user-management/nextjs-user-management). -- [Supabase Auth with RedwoodJS.](https://redwood-playground-auth.netlify.app/supabase) Try out Supabase authentication in the [RedwoodJS](https://redwoodjs.com) Authentication Playground complete with OAuth support and code samples. - -### Collaborative - -- [Next.js Slack Clone.](https://github.com/supabase/examples/tree/main/supabase-js-v1/slack-clone/nextjs-slack-clone) - -## Community - -### Courses - -- [Build a Twitter Clone with the Next.js App Router and Supabase - free egghead course](https://egghead.io/courses/build-a-twitter-clone-with-the-next-js-app-router-and-supabase-19bebadb) - -### Libraries - -- D (in development): [GitHub](https://github.com/csharpdf/dupabase) -- Flutter (in development): [GitHub](https://github.com/supabase/supabase-flutter) -- Python (in development): [GitHub](https://github.com/supabase/supabase-py) -- C# (in development): [GitHub](https://github.com/supabase/supabase-csharp) -- Kotlin (in development): [GitHub](https://github.com/supabase-community/supabase-kt) -- `useSupabase`: Supabase React Hooks. [GitHub](https://github.com/gbibeaul/use-supabase) -- `vue-supabase`: Supabase Vue wrapper. [GitHub](https://github.com/supabase/vue-supabase) -- `vue-3-supabase`: Supabase Vue 3 wrapper. [GitHub](https://github.com/DidoMarchet/vue-3-supabase) -- `nuxt-supabase`: Supabase Nuxt wrapper. [GitHub](https://github.com/supabase-community/nuxt-supabase) -- `@nuxtjs/supabase`: Supabase Nuxt 3 module. [GitHub](https://github.com/nuxt-modules/supabase) -- `react-supabase`: Supabase React Hooks. [Docs](https://react-supabase.vercel.app) [GitHub](https://github.com/tmm/react-supabase) -- ` @triniwiz/nativescript-supabase`: Supabase NativeScript. [GitHub](https://github.com/triniwiz/nativescript-plugins/tree/master/packages/nativescript-supabase) - -### Guides - -- Supabase Auth with Redwood. [Docs](https://redwoodjs.com/tutorial/authentication) -- Supabase Auth with Sapper SSR. [Blog](https://dev.to/jakobbouchard/how-to-setup-supabase-auth-with-sapper-ssr-13od) -- Switch from Firebase Auth to Supabase Auth. [Blog](https://msyyn.medium.com/switch-from-firebase-auth-to-supabase-auth-the-open-source-firebase-alternative-509746952b1b) -- Setting up Umami Analytics with Supabase. [Blog](https://dev.to/jakobbouchard/setting-up-umami-with-vercel-and-supabase-3a73) -- Creating New Supabase Users In Next.js. [Blog](https://www.aboutmonica.com/blog/creating-new-supabase-users-in-next-js) -- Creating Protected Routes In Next.js With Supabase. [Blog](https://www.aboutmonica.com/blog/creating-protected-routes-in-next-js-with-supabase) -- Migrate from Google Cloud Storage (GCS) to Supabase Storage [Gist](https://gist.github.com/danalloway/86f79efd5ca336ff7364554ac3104014) -- Subscriptions with Supabase and Stripe Billing [Blog](https://www.sandromaglione.com/2021/04/29/supabase-auth-create-stripe-customer-subscription-supabase-stripe-billing-part-1/) -- Flutter Supabase Authentication [Blog](https://www.sandromaglione.com/2021/04/24/flutter-supabase-authentication/) -- Supabase in 6 minutes [Video](https://www.youtube.com/watch?v=c8DNV9yl0mg) -- Supabase React Auth UI Tutorial [Video](https://youtu.be/6ch1PtIqCUw) -- Supabase React File Upload Tutorial [Video](https://youtu.be/HvOvdD2nX1k) -- Let's build SupaAuth - Build an Authentication System using Supabase, Next.js and Typescript [6-part Blog Series](https://aalam.in/blog/supabase-auth-intro-setup-next) -- In-depth self-hosting guide using Nginx [Blog](https://dev.to/chronsyn/self-hosting-with-supabase-1aii) -- Build an Email and Social Auth for Next JS with Supabase, Tailwind CSS 3.0 and TypeScript [Blog](https://creativedesignsguru.com/next-js-supabase-auth/) -- Link Shortener using Supabase and Ory [3-part Blog Series](https://www.ory.sh/tutorial-url-shortener-supabase-ory-integration-backend/) -- Building a CRUD API with FastAPI and Supabase: A Step-by-Step Guide [Blog](https://blog.theinfosecguy.xyz/building-a-crud-api-with-fastapi-and-supabase-a-step-by-step-guide) - -### Example apps - -- Supabase + Stripe + Next.js. [GitHub](https://github.com/vercel/nextjs-subscription-payments) -- Supabase + Svelte Trello clone. [GitHub](https://github.com/joshnuss/supabase-kanban) -- Supabase + Expo Starter. [GitHub](https://github.com/codingki/react-native-expo-template/tree/master/template-typescript-bottom-tabs-supabase-auth-flow) -- Supabase + Nest.js. [GitHub](https://github.com/hiro1107/nestjs-supabase-auth) -- Supabase + Cloudflare Workers. [GitHub](https://github.com/supabase/examples/tree/main/supabase-js-v1/with-cloudflare-workers) -- Supabase + Cloudflare Workers + Webpack. [GitHub](https://github.com/signalnerve/supabase-workers-proxy) -- Realtime chat app with Supabase + React. [GitHub](https://github.com/shwosner/realtime-chat-supabase-react) -- Repository.surf: GitHub insights dashboard. [GitHub](https://github.com/supabase/repository.surf) -- Supabase + React Native Instagram Clone. [GitHub](https://github.com/NiketanG/instaclone) -- KeepLink: Simple bookmark service with tags and archive. [GitHub](https://github.com/fengkx/keeplink) -- Supabase + Next.js (Next.js Starter Kit) [GitHub](https://github.com/one-aalam/next-starter-kit/tree/auth-supabase) -- Supabase + Svelte (Svelte Starter Kit) [GitHub](https://github.com/one-aalam/svelte-starter-kit) -- Supabase + SolidJS (SolidJS Starter Kit) [GitHub](https://github.com/one-aalam/solid-starter-kit) -- Supabase + Nuxt3 (Nuxt Starter Kit) [GitHub](https://github.com/one-aalam/nuxt-starter-kit) -- Supabase + Remix (Remix Starter Kit) [GitHub](https://github.com/one-aalam/remix-starter-kit) -- Supabase + Angular (Angular Starter Kit) [GitHub](https://github.com/one-aalam/ng-starter-kit) -- Supabase + Nuxt3 + nuxtjs/supabase [Github](https://github.com/nuxt-modules/supabase/tree/main/demo) -- Supabase + Ory Kratos & Ory Oathkeeper [Github](https://github.com/ory/examples/tree/master/kratos-keto-oathkeeper-supabase) -- Supabase + Ory Cloud [Github](https://github.com/ory/examples/tree/master/supabase-ory-cloud) -- Supabase Auth with React Native + Next.js (Monorepo) [Github](https://github.com/mateoguzmana/react-native-next-supabase-auth-monorepo) -- Supabase Auth with Nuxt3 [Github](https://github.com/zackha/supaAuth) -- Supabase Auth with Hono [Github](https://github.com/CarlosZiegler/hono-supabase) - -### Blog posts - -- Realtime Subscriptions using Vue + Supabase. [Blog](https://dev.to/ftonato/realtime-subscriptions-using-vue-supabase-1e11) -- Creating a microblog using Vue + Supabase. [Blog](https://dev.to/ftonato/creating-a-microblog-using-vue-supabase-31p) -- Track Real-time Page Views. [Blog](https://codebycorey.com/blog/page-views-nextjs-supabase) -- Supabase as a Sentry alternative. [Blog](http://kopi.cloud/blog/2021/sentry-supabase/) -- Using Supabase with Chartbrew. [Blog](https://chartbrew.com/blog/how-to-visualize-your-supabase-data-with-chartbrew/) -- Authentication with Supabase and React. [Blog](https://hyperfoo.io/posts/supabase-authentication-react) -- Supabase Schema Visualizer. [Blog](https://dev.to/zernonia/supabase-schema-visualizer-no-installation-login-49kg) -- Create a real-time UI using Next.js + Supabase. [Blog](https://pablopunk.com/posts/how-to-create-a-real-time-ui-with-nextjs-and-supabase) -- How to add Twitter auth quickly with Supabase to your Next.js site ⚡ [Blog](https://blog.avneesh.tech/how-to-add-twitter-auth-quickly-with-supabase-to-your-nextjs-site) -- Under the hood: Architecture and Technology Stack of Supabase ⚡ [Blog](https://www.workingsoftware.dev/tech-stack-and-architecture-of-supabase/) - -### Podcasts - -- [Software Engineering Daily](https://softwareengineeringdaily.com/2020/10/15/supabase-open-source-firebase-with-paul-copplestone/) -- [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) diff --git a/apps/docs/features/docs/GuidesMdx.utils.tsx b/apps/docs/features/docs/GuidesMdx.utils.tsx index 4b6061d3f3b13..d21e7fe6e9eb3 100644 --- a/apps/docs/features/docs/GuidesMdx.utils.tsx +++ b/apps/docs/features/docs/GuidesMdx.utils.tsx @@ -1,4 +1,8 @@ import matter from 'gray-matter' +import { fromMarkdown } from 'mdast-util-from-markdown' +import { gfmFromMarkdown, gfmToMarkdown } from 'mdast-util-gfm' +import { toMarkdown } from 'mdast-util-to-markdown' +import { gfm } from 'micromark-extension-gfm' import { type Metadata, type ResolvingMetadata } from 'next' import { notFound } from 'next/navigation' import { readFile, readdir } from 'node:fs/promises' @@ -22,11 +26,14 @@ const PUBLISHED_SECTIONS = [ 'ai', 'api', 'auth', - 'cli', 'database', + 'deployment', 'functions', 'getting-started', // 'graphql', -- technically published, but completely federated + 'integrations', + 'local-development', + 'monitoring-troubleshooting', 'platform', 'realtime', 'resources', @@ -143,4 +150,18 @@ const genGuideMeta = } } -export { getGuidesMarkdown, genGuidesStaticParams, genGuideMeta } +function removeRedundantH1(content: string) { + const mdxTree = fromMarkdown(content, 'utf-8', { + extensions: [gfm()], + mdastExtensions: [gfmFromMarkdown()], + }) + + const maybeH1 = mdxTree.children[0] + if (maybeH1 && maybeH1.type === 'heading' && maybeH1.depth === 1) { + content = content.slice(maybeH1.position?.end?.offset) + } + + return content +} + +export { getGuidesMarkdown, genGuidesStaticParams, genGuideMeta, removeRedundantH1 } diff --git a/apps/docs/features/docs/MdxBase.shared.tsx b/apps/docs/features/docs/MdxBase.shared.tsx index 3458d36ead948..d90dfdca25e92 100644 --- a/apps/docs/features/docs/MdxBase.shared.tsx +++ b/apps/docs/features/docs/MdxBase.shared.tsx @@ -38,6 +38,7 @@ import StepHikeCompact from '~/components/StepHikeCompact' import { CodeSampleWrapper } from '~/features/directives/CodeSample.client' import { Accordion, AccordionItem } from '~/features/ui/Accordion' import * as CH from '~/features/ui/CodeHike' +import { ShowUntil } from '~/features/ui/ShowUntil' import { TabPanel, Tabs } from '~/features/ui/Tabs' const components = { @@ -78,6 +79,7 @@ const components = { RealtimeLimitsEstimator, RegionsList, SharedData, + ShowUntil, SocialProviderSettingsSupabase, SocialProviderSetup, SqlToRest, diff --git a/apps/docs/features/ui/ShowUntil.tsx b/apps/docs/features/ui/ShowUntil.tsx new file mode 100644 index 0000000000000..77a5ee09e6062 --- /dev/null +++ b/apps/docs/features/ui/ShowUntil.tsx @@ -0,0 +1,12 @@ +import { type ReactNode } from 'react' + +export function ShowUntil({ children, date }: { children: ReactNode; date: string }) { + const currentDate = new Date() + const untilDate = new Date(date) + + if (isNaN(untilDate.getTime()) || currentDate < untilDate) { + return <>{children} + } else { + return null + } +} diff --git a/apps/docs/layouts/HomeLayout.tsx b/apps/docs/layouts/HomeLayout.tsx index 4c04c9fc9cd1d..ad8def21de742 100644 --- a/apps/docs/layouts/HomeLayout.tsx +++ b/apps/docs/layouts/HomeLayout.tsx @@ -6,7 +6,7 @@ import { SidebarSkeleton } from './MainSkeleton' const HomeLayout = ({ children }: PropsWithChildren) => { return ( - +
diff --git a/apps/docs/layouts/MainSkeleton.tsx b/apps/docs/layouts/MainSkeleton.tsx index 257805a5aec84..81fd1c5ff0fa2 100644 --- a/apps/docs/layouts/MainSkeleton.tsx +++ b/apps/docs/layouts/MainSkeleton.tsx @@ -1,6 +1,7 @@ 'use client' import dynamic from 'next/dynamic' +import { usePathname } from 'next/navigation' import { memo, useEffect, type PropsWithChildren, type ReactNode } from 'react' import { cn } from 'ui' @@ -8,6 +9,8 @@ import { cn } from 'ui' import DefaultNavigationMenu, { MenuId, } from '~/components/Navigation/NavigationMenu/NavigationMenu' +import { getMenuId } from '~/components/Navigation/NavigationMenu/NavigationMenu.utils' +import { type NavMenuSection } from '~/components/Navigation/Navigation.types' import TopNavBar from '~/components/Navigation/NavigationMenu/TopNavBar' import { DOCS_CONTENT_CONTAINER_ID } from '~/features/ui/helpers.constants' import { menuState, useMenuMobileOpen } from '~/hooks/useMenuState' @@ -59,9 +62,9 @@ const levelsData = { icon: 'ai', name: 'AI & Vectors', }, - supabase_cli: { + local_development: { icon: 'reference-cli', - name: 'Supabase CLI', + name: 'Local Development', }, platform: { icon: 'platform', @@ -325,8 +328,10 @@ const NavContainer = memo(function NavContainer({ children }: PropsWithChildren) }) interface SkeletonProps extends PropsWithChildren { - menuId?: MenuId + hideSideNav?: boolean NavigationMenu?: ReactNode + additionalNavItems?: Partial[] + menuId?: MenuId } function TopNavSkeleton({ children }) { @@ -340,14 +345,26 @@ function TopNavSkeleton({ children }) { ) } -function SidebarSkeleton({ children, menuId, NavigationMenu }: SkeletonProps) { +function SidebarSkeleton({ + children, + hideSideNav, + NavigationMenu, + additionalNavItems, + menuId: _menuId, +}: SkeletonProps) { + const pathname = usePathname() + const menuId = _menuId ?? getMenuId(pathname) + const mobileMenuOpen = useMenuMobileOpen() - const hideSideNav = !menuId return (
{!hideSideNav && ( - {NavigationMenu ?? } + + {NavigationMenu ?? ( + + )} + )}
= (props) => { - const menuId = props.menuId - +const Layout = ({ + children, + additionalNavItems, +}: PropsWithChildren<{ additionalNavItems?: Partial[] }>) => { return ( - - {props.children} + + {children} ) } diff --git a/apps/docs/lib/supabaseMisc.ts b/apps/docs/lib/supabaseMisc.ts new file mode 100644 index 0000000000000..2c70c480b9dd2 --- /dev/null +++ b/apps/docs/lib/supabaseMisc.ts @@ -0,0 +1,14 @@ +import { createClient, type SupabaseClient } from '@supabase/supabase-js' + +let _supabaseMisc: SupabaseClient + +export function supabaseMisc() { + if (!_supabaseMisc) { + _supabaseMisc = createClient( + process.env.NEXT_PUBLIC_MISC_URL!, + process.env.NEXT_PUBLIC_MISC_ANON_KEY! + ) + } + + return _supabaseMisc +} diff --git a/apps/docs/next.config.mjs b/apps/docs/next.config.mjs index f6df4d065a1de..965e5c8705969 100644 --- a/apps/docs/next.config.mjs +++ b/apps/docs/next.config.mjs @@ -60,16 +60,16 @@ const nextConfig = { '/api/crawlers': ['./features/docs/generated/**/*', './docs/ref/**/*'], }, }, - /** - * The SQL to REST API translator relies on libpg-query, which packages a - * native Node.js module that wraps the Postgres query parser. - * - * The default webpack config can't load native modules, so we need a custom - * loader for it, which calls process.dlopen to load C++ Addons. - * - * See https://github.com/eisberg-labs/nextjs-node-loader - */ - webpack: (config) => { + webpack: (config, options) => { + /** + * The SQL to REST API translator relies on libpg-query, which packages a + * native Node.js module that wraps the Postgres query parser. + * + * The default webpack config can't load native modules, so we need a custom + * loader for it, which calls process.dlopen to load C++ Addons. + * + * See https://github.com/eisberg-labs/nextjs-node-loader + */ config.module.rules.push({ test: /\.node$/, use: [ diff --git a/apps/docs/scripts/orphans/detect-orphan-mdx.ts b/apps/docs/scripts/orphans/detect-orphan-mdx.ts index 3041d54d284f6..c10494e044915 100644 --- a/apps/docs/scripts/orphans/detect-orphan-mdx.ts +++ b/apps/docs/scripts/orphans/detect-orphan-mdx.ts @@ -12,11 +12,9 @@ import { realtime, storage, ai, - supabase_cli, platform, resources, self_hosting, - migrate, } from '../../components/Navigation/NavigationMenu/NavigationMenu.constants' const DOCS_ROOT_DIR = join(__dirname, '..', '..') @@ -73,11 +71,9 @@ const main = async () => { realtime.items, storage.items, ai.items, - supabase_cli.items, platform.items, resources.items, self_hosting.items, - migrate.items, ] .flatMap((items) => recGetUrl(items)) // Remove initial slash diff --git a/apps/www/lib/redirects.js b/apps/www/lib/redirects.js index b3dc17eee656a..e5a93e4b8daf9 100644 --- a/apps/www/lib/redirects.js +++ b/apps/www/lib/redirects.js @@ -2589,6 +2589,156 @@ module.exports = [ source: '/docs/guides/platform/enterprise-billing', destination: '/docs/guides/platform/org-based-billing', }, + { + permanent: true, + source: '/docs/guides/cli', + destination: '/docs/guides/local-development', + }, + { + permanent: true, + source: '/docs/guides/cli/getting-started', + destination: '/docs/guides/local-development/cli/getting-started', + }, + { + permanent: true, + source: '/docs/guides/cli/config', + destination: '/docs/guides/local-development/cli/config', + }, + { + permanent: true, + source: '/docs/guides/cli/local-development', + destination: '/docs/guides/local-development/overview', + }, + { + permanent: true, + source: '/docs/guides/cli/:path*', + destination: '/docs/guides/local-development/cli/:path*', + }, + { + permanent: true, + source: '/docs/guides/cli/managing-environments', + destination: '/docs/guides/deployment/managing-environments', + }, + { + permanent: true, + source: '/docs/guides/platform/branching', + destination: '/docs/guides/deployment/branching', + }, + { + permanent: true, + source: '/docs/guides/platform/terraform', + destination: '/docs/guides/deployment/terraform', + }, + { + permanent: true, + source: '/docs/guides/platform/terraform/:path*', + destination: '/docs/guides/deployment/terraform/:path*', + }, + { + permanent: true, + source: '/docs/guides/platform/going-into-prod', + destination: '/docs/guides/deployment/going-into-prod', + }, + { + permanent: true, + source: '/docs/guides/platform/maturity-model', + destination: '/docs/guides/deployment/maturity-model', + }, + { + permanent: true, + source: '/docs/guides/platform/shared-responsibility-model', + destination: '/docs/guides/deployment/shared-responsibility-model', + }, + { + permanent: true, + source: '/docs/guides/cli/github-actions/:path*', + destination: '/docs/guides/deployment/ci/:path*', + }, + { + permanent: true, + source: '/docs/guides/resources/migrating-to-supabase/:path*', + destination: '/docs/guides/platform/migrating-to-supabase/:path*', + }, + { + permanent: true, + source: '/docs/guides/platform/migrating-and-upgrading-projects', + destination: '/docs/guides/platform/upgrading', + }, + { + permanent: true, + source: '/docs/guides/platform/vercel-marketplace', + destination: '/docs/guides/integrations/vercel-marketplace', + }, + { + permanent: true, + source: '/docs/guides/platform/marketplace', + destination: '/docs/guides/integrations/supabase-marketplace', + }, + { + permanent: true, + source: '/docs/guides/platform/oauth-apps/build-a-supabase-integration', + destination: '/docs/guides/integrations/build-a-supabase-integration', + }, + { + permanent: true, + source: '/docs/guides/platform/oauth-apps/oauth-scopes', + destination: '/docs/guides/integrations/build-a-supabase-integration/oauth-scopes', + }, + { + permanent: true, + source: '/docs/guides/platform/logs', + destination: '/docs/guides/monitoring-troubleshooting/logs', + }, + { + permanent: true, + source: '/docs/guides/platform/metrics', + destination: '/docs/guides/monitoring-troubleshooting/metrics', + }, + { + permanent: true, + source: '/docs/guides/platform/sentry-monitoring', + destination: '/docs/guides/monitoring-troubleshooting/sentry-monitoring', + }, + { + permanent: true, + source: '/docs/guides/platform/advanced-log-filtering', + destination: '/docs/guides/monitoring-troubleshooting/advanced-log-filtering', + }, + { + permanent: true, + source: '/docs/guides/platform/exhaust-disk-io', + destination: '/docs/guides/monitoring-troubleshooting/exhaust-disk-io', + }, + { + permanent: true, + source: '/docs/guides/platform/exhaust-cpu', + destination: '/docs/guides/monitoring-troubleshooting/exhaust-cpu', + }, + { + permanent: true, + source: '/docs/guides/platform/exhaust-ram', + destination: '/docs/guides/monitoring-troubleshooting/exhaust-ram', + }, + { + permanent: true, + source: '/docs/guides/platform/exhaust-swap', + destination: '/docs/guides/monitoring-troubleshooting/exhaust-swap', + }, + { + permanent: true, + source: '/docs/guides/platform/http-status-codes', + destination: '/docs/guides/monitoring-troubleshooting/http-status-codes', + }, + { + permanent: true, + source: '/docs/guides/platform/troubleshooting', + destination: '/docs/guides/monitoring-troubleshooting/troubleshooting', + }, + { + permanent: true, + source: '/docs/guides/platform/log-drains', + destination: '/docs/guides/monitoring-troubleshooting/log-drains', + }, // marketing diff --git a/package-lock.json b/package-lock.json index 8870c9d25420c..840c29bec7848 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15846,6 +15846,14 @@ "@types/node": "*" } }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "dev": true, + "optional": true, + "peer": true + }, "node_modules/@types/parse-numeric-range": { "version": "0.0.1", "dev": true, @@ -17743,6 +17751,23 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.11", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", @@ -18956,6 +18981,35 @@ "version": "1.0.3", "license": "MIT" }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cosmiconfig/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/create-jest": { "version": "29.7.0", "dev": true, @@ -43333,6 +43387,7 @@ "@babel/preset-env": "^7.23.6", "@jest/globals": "^29.7.0", "@types/common-tags": "^1.8.4", + "api-types": "*", "babel-jest": "^29.7.0", "babel-plugin-transform-import-meta": "^2.2.1", "chalk": "^5.3.0", diff --git a/package.json b/package.json index 479c31a951a25..591bec4f72efc 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,13 @@ "author": "Supabase, Inc.", "license": "Apache-2.0", "private": true, - "workspaces": ["apps/*", "apps/docs/spec/parser", "tests", "playwright-tests", "packages/*"], + "workspaces": [ + "apps/*", + "apps/docs/spec/parser", + "tests", + "playwright-tests", + "packages/*" + ], "scripts": { "build": "turbo run build", "build:studio": "turbo run build --filter=studio", @@ -51,6 +57,13 @@ "npm": "^10.0.0", "node": "^20.0.0" }, - "keywords": ["postgres", "firebase", "storage", "functions", "database", "auth"], + "keywords": [ + "postgres", + "firebase", + "storage", + "functions", + "database", + "auth" + ], "packageManager": "npm@10.7.0" } diff --git a/packages/ui-patterns/GlassPanel/index.tsx b/packages/ui-patterns/GlassPanel/index.tsx index d83e73c051b2b..c28771a7863bf 100644 --- a/packages/ui-patterns/GlassPanel/index.tsx +++ b/packages/ui-patterns/GlassPanel/index.tsx @@ -7,7 +7,6 @@ import { cn } from 'ui' interface Props { title: string - span?: string icon?: string | React.ReactNode children?: React.ReactNode header?: string @@ -22,7 +21,6 @@ interface Props { export const GlassPanel = ({ title, - span, icon, children, header,