From 44db2d3f164af5cbebd85d8d04806d547a08670b Mon Sep 17 00:00:00 2001 From: Charis <26616127+charislam@users.noreply.github.com> Date: Thu, 30 Jan 2025 11:04:43 -0500 Subject: [PATCH] refactor: split guide layouts by section (#32694) Split guide layouts by section, so that nav data fetches can be pushed down to thesection where they're actually used. Limits blast radius of any data fetch problems, and also lets us push down client components in the future, since layouts now have context on the request path and we don't need a high-level usePathname. --- .../guides/(with-sidebar)/[...slug]/page.tsx | 21 - .../docs/app/guides/(with-sidebar)/layout.tsx | 61 --- .../local-development/cli/config/page.tsx | 106 ----- .../platform/terraform/[[...slug]]/page.tsx | 146 ------- .../platform/terraform/reference/page.tsx | 410 ------------------ .../platform/terraform/terraformConstants.ts | 9 - apps/docs/app/guides/ai/[[...slug]]/page.tsx | 25 ++ apps/docs/app/guides/ai/layout.tsx | 5 + .../ai/python/[slug]/page.tsx | 2 + apps/docs/app/guides/api/[[...slug]]/page.tsx | 25 ++ apps/docs/app/guides/api/layout.tsx | 5 + .../docs/app/guides/auth/[[...slug]]/page.tsx | 25 ++ apps/docs/app/guides/auth/layout.tsx | 5 + .../docs/app/guides/cron/[[...slug]]/page.tsx | 25 ++ apps/docs/app/guides/cron/layout.tsx | 5 + .../app/guides/database/[[...slug]]/page.tsx | 25 ++ .../database/database-advisors/page.tsx | 0 .../extensions/wrappers/[[...slug]]/page.tsx | 2 + apps/docs/app/guides/database/layout.tsx | 5 + .../guides/deployment/[[...slug]]/page.tsx | 25 ++ .../deployment/ci/[slug]/page.tsx | 2 + apps/docs/app/guides/deployment/layout.tsx | 5 + .../deployment/terraform/[[...slug]]/page.tsx | 2 + .../deployment/terraform/reference/page.tsx | 0 .../terraform/terraformConstants.ts | 0 .../app/guides/functions/[[...slug]]/page.tsx | 25 ++ apps/docs/app/guides/functions/layout.tsx | 5 + .../getting-started/[[...slug]]/page.tsx | 25 ++ .../ai-prompts/[slug]/AiPrompts.utils.ts | 0 .../ai-prompts/[slug]/AiPromptsIndex.tsx | 0 .../ai-prompts/[slug]/page.tsx | 0 .../app/guides/getting-started/layout.tsx | 20 + .../graphql/[[...slug]]/page.tsx | 2 + apps/docs/app/guides/graphql/layout.tsx | 5 + .../guides/integrations/[[...slug]]/page.tsx | 25 ++ apps/docs/app/guides/integrations/layout.tsx | 39 ++ .../local-development/[[...slug]]/page.tsx | 25 ++ .../cli}/config/page.tsx | 0 .../app/guides/local-development/layout.tsx | 5 + .../[[...slug]]/page.tsx | 25 ++ .../monitoring-troubleshooting/layout.tsx | 9 + .../app/guides/platform/[[...slug]]/page.tsx | 25 ++ apps/docs/app/guides/platform/layout.tsx | 5 + .../app/guides/queues/[[...slug]]/page.tsx | 25 ++ apps/docs/app/guides/queues/layout.tsx | 5 + .../app/guides/realtime/[[...slug]]/page.tsx | 25 ++ apps/docs/app/guides/realtime/layout.tsx | 5 + .../app/guides/resources/[[...slug]]/page.tsx | 25 ++ apps/docs/app/guides/resources/layout.tsx | 5 + .../guides/self-hosting/[[...slug]]/page.tsx | 25 ++ .../self-hosting/analytics/config/page.tsx | 0 .../self-hosting/auth/config/page.tsx | 0 apps/docs/app/guides/self-hosting/layout.tsx | 5 + .../self-hosting/realtime/config/page.tsx | 0 .../self-hosting/storage/config/page.tsx | 0 .../app/guides/storage/[[...slug]]/page.tsx | 25 ++ apps/docs/app/guides/storage/layout.tsx | 5 + apps/docs/features/docs/GuidesMdx.utils.tsx | 6 +- apps/docs/features/docs/MdxBase.tsx | 2 +- apps/docs/lib/octokit.ts | 1 + 60 files changed, 585 insertions(+), 755 deletions(-) delete mode 100644 apps/docs/app/guides/(with-sidebar)/[...slug]/page.tsx delete mode 100644 apps/docs/app/guides/(with-sidebar)/layout.tsx delete mode 100644 apps/docs/app/guides/(with-sidebar)/local-development/cli/config/page.tsx delete mode 100644 apps/docs/app/guides/(with-sidebar)/platform/terraform/[[...slug]]/page.tsx delete mode 100644 apps/docs/app/guides/(with-sidebar)/platform/terraform/reference/page.tsx delete mode 100644 apps/docs/app/guides/(with-sidebar)/platform/terraform/terraformConstants.ts create mode 100644 apps/docs/app/guides/ai/[[...slug]]/page.tsx create mode 100644 apps/docs/app/guides/ai/layout.tsx rename apps/docs/app/guides/{(with-sidebar) => }/ai/python/[slug]/page.tsx (99%) create mode 100644 apps/docs/app/guides/api/[[...slug]]/page.tsx create mode 100644 apps/docs/app/guides/api/layout.tsx create mode 100644 apps/docs/app/guides/auth/[[...slug]]/page.tsx create mode 100644 apps/docs/app/guides/auth/layout.tsx create mode 100644 apps/docs/app/guides/cron/[[...slug]]/page.tsx create mode 100644 apps/docs/app/guides/cron/layout.tsx create mode 100644 apps/docs/app/guides/database/[[...slug]]/page.tsx rename apps/docs/app/guides/{(with-sidebar) => }/database/database-advisors/page.tsx (100%) rename apps/docs/app/guides/{(with-sidebar) => }/database/extensions/wrappers/[[...slug]]/page.tsx (99%) create mode 100644 apps/docs/app/guides/database/layout.tsx create mode 100644 apps/docs/app/guides/deployment/[[...slug]]/page.tsx rename apps/docs/app/guides/{(with-sidebar) => }/deployment/ci/[slug]/page.tsx (99%) create mode 100644 apps/docs/app/guides/deployment/layout.tsx rename apps/docs/app/guides/{(with-sidebar) => }/deployment/terraform/[[...slug]]/page.tsx (99%) rename apps/docs/app/guides/{(with-sidebar) => }/deployment/terraform/reference/page.tsx (100%) rename apps/docs/app/guides/{(with-sidebar) => }/deployment/terraform/terraformConstants.ts (100%) create mode 100644 apps/docs/app/guides/functions/[[...slug]]/page.tsx create mode 100644 apps/docs/app/guides/functions/layout.tsx create mode 100644 apps/docs/app/guides/getting-started/[[...slug]]/page.tsx rename apps/docs/app/guides/{(with-sidebar) => }/getting-started/ai-prompts/[slug]/AiPrompts.utils.ts (100%) rename apps/docs/app/guides/{(with-sidebar) => }/getting-started/ai-prompts/[slug]/AiPromptsIndex.tsx (100%) rename apps/docs/app/guides/{(with-sidebar) => }/getting-started/ai-prompts/[slug]/page.tsx (100%) create mode 100644 apps/docs/app/guides/getting-started/layout.tsx rename apps/docs/app/guides/{(with-sidebar) => }/graphql/[[...slug]]/page.tsx (99%) create mode 100644 apps/docs/app/guides/graphql/layout.tsx create mode 100644 apps/docs/app/guides/integrations/[[...slug]]/page.tsx create mode 100644 apps/docs/app/guides/integrations/layout.tsx create mode 100644 apps/docs/app/guides/local-development/[[...slug]]/page.tsx rename apps/docs/app/guides/{(with-sidebar) => local-development/cli}/config/page.tsx (100%) create mode 100644 apps/docs/app/guides/local-development/layout.tsx create mode 100644 apps/docs/app/guides/monitoring-troubleshooting/[[...slug]]/page.tsx create mode 100644 apps/docs/app/guides/monitoring-troubleshooting/layout.tsx create mode 100644 apps/docs/app/guides/platform/[[...slug]]/page.tsx create mode 100644 apps/docs/app/guides/platform/layout.tsx create mode 100644 apps/docs/app/guides/queues/[[...slug]]/page.tsx create mode 100644 apps/docs/app/guides/queues/layout.tsx create mode 100644 apps/docs/app/guides/realtime/[[...slug]]/page.tsx create mode 100644 apps/docs/app/guides/realtime/layout.tsx create mode 100644 apps/docs/app/guides/resources/[[...slug]]/page.tsx create mode 100644 apps/docs/app/guides/resources/layout.tsx create mode 100644 apps/docs/app/guides/self-hosting/[[...slug]]/page.tsx rename apps/docs/app/guides/{(with-sidebar) => }/self-hosting/analytics/config/page.tsx (100%) rename apps/docs/app/guides/{(with-sidebar) => }/self-hosting/auth/config/page.tsx (100%) create mode 100644 apps/docs/app/guides/self-hosting/layout.tsx rename apps/docs/app/guides/{(with-sidebar) => }/self-hosting/realtime/config/page.tsx (100%) rename apps/docs/app/guides/{(with-sidebar) => }/self-hosting/storage/config/page.tsx (100%) create mode 100644 apps/docs/app/guides/storage/[[...slug]]/page.tsx create mode 100644 apps/docs/app/guides/storage/layout.tsx diff --git a/apps/docs/app/guides/(with-sidebar)/[...slug]/page.tsx b/apps/docs/app/guides/(with-sidebar)/[...slug]/page.tsx deleted file mode 100644 index dae1201acc6..00000000000 --- a/apps/docs/app/guides/(with-sidebar)/[...slug]/page.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { - getGuidesMarkdown, - genGuideMeta, - genGuidesStaticParams, -} from '~/features/docs/GuidesMdx.utils' -import { GuideTemplate } from '~/features/docs/GuidesMdx.template' - -export const dynamicParams = false - -type Params = { slug: string[] } - -const GuidePage = async ({ params }: { params: Params }) => { - const data = await getGuidesMarkdown(params) - return -} - -const generateStaticParams = genGuidesStaticParams() -const generateMetadata = genGuideMeta(getGuidesMarkdown) - -export default GuidePage -export { generateStaticParams, generateMetadata } diff --git a/apps/docs/app/guides/(with-sidebar)/layout.tsx b/apps/docs/app/guides/(with-sidebar)/layout.tsx deleted file mode 100644 index 2824184e834..00000000000 --- a/apps/docs/app/guides/(with-sidebar)/layout.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { cache, type PropsWithChildren } from 'react' - -import { IS_PLATFORM } from 'common' - -import { NavMenuSection } from '~/components/Navigation/Navigation.types' -import Layout from '~/layouts/guides' -import { supabaseMisc } from '~/lib/supabaseMisc' -import { getAiPrompts } from './getting-started/ai-prompts/[slug]/AiPrompts.utils' - -// Revalidate occasionally to pick up changes to partners -// 60 seconds/minute * 60 minutes/hour * 24 hours/day -// export const revalidate = 86_400 - -const GuidesLayout = async ({ children }: PropsWithChildren) => { - const [partnerNavItems, promptNavItems] = await Promise.all([getPartners(), getPrompts()]) - - const additionalNavItems = - partnerNavItems.length > 0 || promptNavItems.length > 0 - ? { integrations: partnerNavItems, prompts: promptNavItems } - : undefined - - return {children} -} - -async function getPrompts() { - const prompts = await getAiPrompts() - return prompts.map( - (prompt) => - ({ - name: prompt.heading, - url: `/guides/getting-started/ai-prompts/${prompt.filename}`, - }) as Partial - ) -} - -const getPartners = cache(getPartnersImpl) -async function getPartnersImpl() { - if (!IS_PLATFORM) return [] - - const { data, error } = await supabaseMisc() - .from('partners') - .select('slug, title') - .eq('approved', true) - .eq('type', 'technology') - .order('title') - if (error) { - console.error(new Error('Error fetching partners', { cause: error })) - } - - const partnerNavItems = (data ?? []).map( - (partner) => - ({ - name: partner.title, - url: `https://supabase.com/partners/integrations/${partner.slug}` as `https://${string}`, - }) as Partial - ) - - return partnerNavItems -} - -export default GuidesLayout diff --git a/apps/docs/app/guides/(with-sidebar)/local-development/cli/config/page.tsx b/apps/docs/app/guides/(with-sidebar)/local-development/cli/config/page.tsx deleted file mode 100644 index 9ce99b1da78..00000000000 --- a/apps/docs/app/guides/(with-sidebar)/local-development/cli/config/page.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import ReactMarkdown from 'react-markdown' -import { CodeBlock } from 'ui' -import { Heading } from 'ui/src/components/CustomHTMLElements' -import { type TOCHeader } from '~/components/GuidesTableOfContents' -import { genGuideMeta } from '~/features/docs/GuidesMdx.utils' -import { GuideTemplate, newEditLink } from '~/features/docs/GuidesMdx.template' -import type { Parameter } from '~/lib/refGenerator/refTypes' -import specFile from '~/spec/cli_v1_config.yaml' with { type: 'yml' } - -const meta = { - title: 'Supabase CLI config', -} - -const generateMetadata = genGuideMeta(() => ({ - pathname: '/guides/cli/config', - meta, -})) - -const tocList: TOCHeader[] = [] -const content = specFile.info.tags.map((tag: { id: string; title: string }, id: number) => { - tocList.push({ id: `${id}`, text: tag.title, link: `${tag.id}-config`, level: 2 }) - return ( -
- {tag.title} Config - {specFile.parameters - .filter((param: Parameter) => param.tags && param.tags[0] === tag.id) - .map((parameter: Parameter, id: number) => { - tocList.push({ id: `${id}`, text: parameter.id, link: `#${parameter.id}`, level: 3 }) - return - })} -
- ) -}) - -const Config = () => { - const editLink = newEditLink('supabase/supabase/blob/master/apps/docs/spec/cli_v1_config.yaml') - - return ( - - {specFile.info.description} -
{content}
-
- ) -} - -function Info({ parameter }: { parameter: Parameter }) { - return ( -
-
- - {parameter.title} - - -
-
-
- - - - - - - - - - - - - - - -
NameDefaultRequired
{parameter.id}{parameter.default ? parameter.default.toString() : 'None'}{parameter.required !== undefined && parameter.required.toString()}
-
-
-

Description

- {parameter.description} -
- {parameter.usage && ( -
-

Usage

- - {parameter.usage} - -
- )} - {parameter.links && ( -
-

See also

-
    - {parameter.links.map((link) => ( -
  • - {link.name} -
  • - ))} -
-
- )} -
-
-
-
- ) -} - -export default Config -export { generateMetadata } diff --git a/apps/docs/app/guides/(with-sidebar)/platform/terraform/[[...slug]]/page.tsx b/apps/docs/app/guides/(with-sidebar)/platform/terraform/[[...slug]]/page.tsx deleted file mode 100644 index ef81a3efe99..00000000000 --- a/apps/docs/app/guides/(with-sidebar)/platform/terraform/[[...slug]]/page.tsx +++ /dev/null @@ -1,146 +0,0 @@ -import matter from 'gray-matter' -import { type SerializeOptions } from 'next-mdx-remote/dist/types' -import { notFound } from 'next/navigation' -import rehypeSlug from 'rehype-slug' - -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' -import { UrlTransformFunction, linkTransform } from '~/lib/mdx/plugins/rehypeLinkTransform' -import remarkMkDocsAdmonition from '~/lib/mdx/plugins/remarkAdmonition' -import { removeTitle } from '~/lib/mdx/plugins/remarkRemoveTitle' -import remarkPyMdownTabs from '~/lib/mdx/plugins/remarkTabs' -import { - terraformDocsBranch, - terraformDocsDocsDir, - terraformDocsOrg, - terraformDocsRepo, -} from '../terraformConstants' - -// Each external docs page is mapped to a local page -const pageMap = [ - { - remoteFile: 'README.md', - meta: { - title: 'Terraform Provider', - }, - useRoot: true, - }, - { - slug: 'tutorial', - remoteFile: 'tutorial.md', - meta: { - title: 'Using the Supabase Terraform Provider', - }, - }, -] - -interface Params { - slug?: string[] -} - -const TerraformDocs = async ({ params }: { params: Params }) => { - const { meta, ...data } = await getContent(params) - - const options = { - mdxOptions: { - remarkPlugins: [remarkMkDocsAdmonition, remarkPyMdownTabs, [removeTitle, meta.title]], - rehypePlugins: [[linkTransform, urlTransform], rehypeSlug], - }, - } as SerializeOptions - - return -} - -/** - * The GitHub repo uses relative links, which don't lead to the right locations - * in docs. - * - * @param url The original link, as written in the Markdown file - * @returns The rewritten link - */ -const urlTransform: UrlTransformFunction = (url: string) => { - try { - const placeholderHostname = 'placeholder' - const { hostname, pathname, hash } = new URL(url, `http://${placeholderHostname}`) - - // Don't modify a url with a FQDN or a url that's only a hash - if (hostname !== placeholderHostname || pathname === '/') { - return url - } - - const getBasename = (pathname: string) => - pathname.endsWith('.md') ? pathname.replace(/\.md$/, '') : pathname - const stripLeadingPrefix = (pathname: string) => pathname.replace(/^\//, '') - const stripLeadingDocs = (pathname: string) => pathname.replace(/^docs\//, '') - - const relativePath = stripLeadingPrefix(getBasename(pathname)) - - const page = pageMap.find( - ({ remoteFile, useRoot }) => - (useRoot && `${relativePath}.md` === remoteFile) || - (!useRoot && `${stripLeadingDocs(relativePath)}.md` === remoteFile) - ) - - if (page) { - return 'terraform' + `/${page.slug}` + hash - } - - // If we don't have this page in our docs, link to GitHub repo - return `https://github.com/${terraformDocsOrg}/${terraformDocsRepo}/blob/${terraformDocsBranch}${pathname}${hash}` - } catch (err) { - console.error('Error transforming markdown URL', err) - return url - } -} - -/** - * Fetch markdown from external repo - */ -const getContent = async ({ slug }: Params) => { - const [requestedSlug] = slug ?? [] - const page = pageMap.find((page) => page.slug === requestedSlug) - - if (!page) { - notFound() - } - - const { meta, remoteFile, useRoot } = page - - const editLink = newEditLink( - `${terraformDocsOrg}/${terraformDocsRepo}/blob/${terraformDocsBranch}/${useRoot ? '' : `${terraformDocsDocsDir}/`}${remoteFile}` - ) - - let response = await fetchRevalidatePerDay( - `https://raw.githubusercontent.com/${terraformDocsOrg}/${terraformDocsRepo}/${terraformDocsBranch}/${useRoot ? '' : `${terraformDocsDocsDir}/`}${remoteFile}` - ) - - let rawContent = await response.text() - // Strip out HTML comments - rawContent = rawContent.replace(//, '') - 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)) { - throw Error('Guide frontmatter is invalid.') - } - - return { - pathname: - `/guides/platform/terraform${slug?.length ? `/${slug.join('/')}` : ''}` satisfies `/${string}`, - meta, - content, - editLink, - } -} - -const generateStaticParams = async () => pageMap.map(({ slug }) => ({ slug: slug ? [slug] : [] })) -const generateMetadata = genGuideMeta(getContent) - -export default TerraformDocs -export { generateStaticParams, generateMetadata } diff --git a/apps/docs/app/guides/(with-sidebar)/platform/terraform/reference/page.tsx b/apps/docs/app/guides/(with-sidebar)/platform/terraform/reference/page.tsx deleted file mode 100644 index c251d8133ea..00000000000 --- a/apps/docs/app/guides/(with-sidebar)/platform/terraform/reference/page.tsx +++ /dev/null @@ -1,410 +0,0 @@ -import { codeBlock } from 'common-tags' -import { Check, PlusCircle } from 'lucide-react' -import Link from 'next/link' -import ReactMarkdown from 'react-markdown' - -import { - CodeBlock, - Heading, - PopoverContent_Shadcn_, - PopoverTrigger_Shadcn_, - Popover_Shadcn_, -} from 'ui' - -import { genGuideMeta } from '~/features/docs/GuidesMdx.utils' -import { GuideTemplate, newEditLink } from '~/features/docs/GuidesMdx.template' -import { fetchRevalidatePerDay } from '~/features/helpers.fetch' -import { TabPanel, Tabs } from '~/features/ui/Tabs' -import { - terraformDocsBranch, - terraformDocsDocsDir, - terraformDocsOrg, - terraformDocsRepo, -} from '../terraformConstants' - -const meta = { - title: 'Terraform Provider reference', - subtitle: 'Resources and data sources available through the Terraform Provider', -} - -const generateMetadata = genGuideMeta(() => ({ - pathname: '/guides/platform/terraform/reference', - meta, -})) - -function ProviderSettings({ schema }: { schema: any }) { - const attributes = schema.block.attributes - - const example = codeBlock` - provider "supabase" { - ${Object.keys(attributes).map( - (attribute) => - `${attribute} = ${attributes[attribute].type === 'string' ? `""` : ''}` - )} - } - ` - - return ( -
- Provider settings -

- Use these settings to configure your Supabase provider and authenticate to your Supabase - project. -

- Example usage - {example} - Details - {/* extra div because width restriction doesn't work on table itself */} -
- - - - - - - - - - - - {Object.keys(schema.block.attributes).map((attribute) => ( - - - - - - - - ))} - -
AttributeDescriptionTypeOptionalSensitive
{attribute} - {attributes[attribute].description} - {attributes[attribute].type} - {attributes[attribute].optional && ( - <> - - true - - )} - - {attributes[attribute].sensitive && ( - <> - - true - - )} -
-
-
- ) -} - -function Resources({ schema }: { schema: any }) { - return ( -
- Resources -

You can configure these resources using the Supabase Terraform provider:

- - {Object.keys(schema).map((resource) => ( - - Example usage - {codeBlock` - resource "${resource}" " - Details - - - - - - - - - - - - - {Object.keys(schema[resource].block.attributes).map((attribute) => ( - - - - - - - - - ))} - -
AttributeDescriptionTypeRequiredOptionalRead-only
- {attribute} - - - {schema[resource].block.attributes[attribute].description} - - - {schema[resource].block.attributes[attribute].type ?? ( - - - - - -
    - {Object.keys( - schema[resource].block.attributes[attribute].nested_type.attributes - ).map((nestedAttribute) => ( -
  • - {nestedAttribute} -
      -
    • - - { - schema[resource].block.attributes[attribute].nested_type - .attributes[nestedAttribute].description - } - -
    • -
    • - {schema[resource].block.attributes[attribute].nested_type - .attributes[nestedAttribute].type ?? 'nested type'} -
    • - {schema[resource].block.attributes[attribute].nested_type - .attributes[nestedAttribute].required &&
    • Required
    • } - {schema[resource].block.attributes[attribute].nested_type - .attributes[nestedAttribute].optional &&
    • Optional
    • } - {schema[resource].block.attributes[attribute].nested_type - .attributes[nestedAttribute].computed &&
    • Read-only
    • } -
    -
  • - ))} -
-
-
- )} -
- {schema[resource].block.attributes[attribute].required && ( - <> - - true - - )} - - {schema[resource].block.attributes[attribute].optional && ( - <> - - true - - )} - - {schema[resource].block.attributes[attribute].computed && ( - <> - - true - - )} -
-
- ))} -
-
- ) -} - -function DataSources({ schema }: { schema: any }) { - return ( -
- Data sources -

You can read these resources using the Supabase Terraform provider:

- - {Object.keys(schema).map((dataSource) => ( - - Example usage - {codeBlock` - resource "${dataSource}" "all" { - ${Object.keys(schema[dataSource].block.attributes) - .filter( - (attribute) => !schema[dataSource].block.attributes[attribute].computed - ) - .map( - (attribute) => - `${attribute} = ${ - schema[dataSource].block.attributes[attribute].type === 'string' - ? `""` - : '' - }` - )} - } - `} - Details - - - - - - - - - - - - - {Object.keys(schema[dataSource].block.attributes).map((attribute) => ( - - - - - - - - - ))} - -
AttributeDescriptionTypeRequiredOptionalRead-only
- {attribute} - - - {schema[dataSource].block.attributes[attribute].description} - - - {schema[dataSource].block.attributes[attribute].type ?? ( - - - - - - {schema[dataSource].block.attributes[attribute].nested_type - .nesting_mode === 'set' && 'Array of:'} -
    - {Object.keys( - schema[dataSource].block.attributes[attribute].nested_type - .attributes - ).map((nestedAttribute) => ( -
  • - {nestedAttribute} -
      -
    • - - { - schema[dataSource].block.attributes[attribute].nested_type - .attributes[nestedAttribute].description - } - -
    • -
    • - {schema[dataSource].block.attributes[attribute].nested_type - .attributes[nestedAttribute].type ?? 'nested type'} -
    • - {schema[dataSource].block.attributes[attribute].nested_type - .attributes[nestedAttribute].required &&
    • Required
    • } - {schema[dataSource].block.attributes[attribute].nested_type - .attributes[nestedAttribute].optional &&
    • Optional
    • } - {schema[dataSource].block.attributes[attribute].nested_type - .attributes[nestedAttribute].computed &&
    • Read-only
    • } -
    -
  • - ))} -
-
-
- )} -
- {schema[dataSource].block.attributes[attribute].required && ( - <> - - true - - )} - - {schema[dataSource].block.attributes[attribute].optional && ( - <> - - true - - )} - - {schema[dataSource].block.attributes[attribute].computed && ( - <> - - true - - )} -
-
- ))} -
-
- ) -} - -const TerraformReferencePage = async () => { - const { schema } = await getSchema() - - const editLink = newEditLink('supabase/terraform-provider-supabase') - - return ( - - The Terraform Provider provices access to{' '} - - resources - {' '} - and{' '} - - data sources - - . Resources are infrastructure objects, such as a Supabase project, that you can declaratively - configure. Data sources are sources of information about your Supabase instances. - - - - - ) -} - -/** - * Fetch JSON schema from external repo - */ -const getSchema = async () => { - let response = await fetchRevalidatePerDay( - `https://raw.githubusercontent.com/${terraformDocsOrg}/${terraformDocsRepo}/${terraformDocsBranch}/${terraformDocsDocsDir}/schema.json` - ) - if (!response.ok) throw Error('Failed to fetch Terraform JSON schema from GitHub') - - const schema = await response.json() - - return { - schema, - } -} - -export default TerraformReferencePage -export { generateMetadata } diff --git a/apps/docs/app/guides/(with-sidebar)/platform/terraform/terraformConstants.ts b/apps/docs/app/guides/(with-sidebar)/platform/terraform/terraformConstants.ts deleted file mode 100644 index 0cc7ad3125b..00000000000 --- a/apps/docs/app/guides/(with-sidebar)/platform/terraform/terraformConstants.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Information on where to fetch docs content - */ -const terraformDocsOrg = 'supabase' -const terraformDocsRepo = 'terraform-provider-supabase' -const terraformDocsBranch = 'v1.1.3' -const terraformDocsDocsDir = 'docs' - -export { terraformDocsOrg, terraformDocsRepo, terraformDocsBranch, terraformDocsDocsDir } diff --git a/apps/docs/app/guides/ai/[[...slug]]/page.tsx b/apps/docs/app/guides/ai/[[...slug]]/page.tsx new file mode 100644 index 00000000000..50198e532f3 --- /dev/null +++ b/apps/docs/app/guides/ai/[[...slug]]/page.tsx @@ -0,0 +1,25 @@ +import { + getGuidesMarkdown, + genGuideMeta, + genGuidesStaticParams, +} from '~/features/docs/GuidesMdx.utils' +import { GuideTemplate } from '~/features/docs/GuidesMdx.template' + +export const dynamicParams = false + +type Params = { slug?: string[] } + +const AiGuidePage = async ({ params }: { params: Params }) => { + const slug = ['ai', ...(params.slug ?? [])] + const data = await getGuidesMarkdown(slug) + + return +} + +const generateStaticParams = genGuidesStaticParams('ai') +const generateMetadata = genGuideMeta((params: { slug?: string[] }) => + getGuidesMarkdown(['ai', ...(params.slug ?? [])]) +) + +export default AiGuidePage +export { generateStaticParams, generateMetadata } diff --git a/apps/docs/app/guides/ai/layout.tsx b/apps/docs/app/guides/ai/layout.tsx new file mode 100644 index 00000000000..8964ce1c3a4 --- /dev/null +++ b/apps/docs/app/guides/ai/layout.tsx @@ -0,0 +1,5 @@ +import Layout from '~/layouts/guides' + +export default async function AiLayout({ children }: { children: React.ReactNode }) { + return {children} +} diff --git a/apps/docs/app/guides/(with-sidebar)/ai/python/[slug]/page.tsx b/apps/docs/app/guides/ai/python/[slug]/page.tsx similarity index 99% rename from apps/docs/app/guides/(with-sidebar)/ai/python/[slug]/page.tsx rename to apps/docs/app/guides/ai/python/[slug]/page.tsx index d6cc049c849..8ebfa5dde15 100644 --- a/apps/docs/app/guides/(with-sidebar)/ai/python/[slug]/page.tsx +++ b/apps/docs/app/guides/ai/python/[slug]/page.tsx @@ -10,6 +10,8 @@ import { UrlTransformFunction, linkTransform } from '~/lib/mdx/plugins/rehypeLin import remarkMkDocsAdmonition from '~/lib/mdx/plugins/remarkAdmonition' import { removeTitle } from '~/lib/mdx/plugins/remarkRemoveTitle' +export const dynamicParams = false + // We fetch these docs at build time from an external repo const org = 'supabase' const repo = 'vecs' diff --git a/apps/docs/app/guides/api/[[...slug]]/page.tsx b/apps/docs/app/guides/api/[[...slug]]/page.tsx new file mode 100644 index 00000000000..85ec5923214 --- /dev/null +++ b/apps/docs/app/guides/api/[[...slug]]/page.tsx @@ -0,0 +1,25 @@ +import { + getGuidesMarkdown, + genGuideMeta, + genGuidesStaticParams, +} from '~/features/docs/GuidesMdx.utils' +import { GuideTemplate } from '~/features/docs/GuidesMdx.template' + +export const dynamicParams = false + +type Params = { slug?: string[] } + +const ApiGuidePage = async ({ params }: { params: Params }) => { + const slug = ['api', ...(params.slug ?? [])] + const data = await getGuidesMarkdown(slug) + + return +} + +const generateStaticParams = genGuidesStaticParams('api') +const generateMetadata = genGuideMeta((params: { slug?: string[] }) => + getGuidesMarkdown(['api', ...(params.slug ?? [])]) +) + +export default ApiGuidePage +export { generateStaticParams, generateMetadata } diff --git a/apps/docs/app/guides/api/layout.tsx b/apps/docs/app/guides/api/layout.tsx new file mode 100644 index 00000000000..cae6afe2d43 --- /dev/null +++ b/apps/docs/app/guides/api/layout.tsx @@ -0,0 +1,5 @@ +import Layout from '~/layouts/guides' + +export default async function ApiLayout({ children }: { children: React.ReactNode }) { + return {children} +} diff --git a/apps/docs/app/guides/auth/[[...slug]]/page.tsx b/apps/docs/app/guides/auth/[[...slug]]/page.tsx new file mode 100644 index 00000000000..ddadcad5a12 --- /dev/null +++ b/apps/docs/app/guides/auth/[[...slug]]/page.tsx @@ -0,0 +1,25 @@ +import { + getGuidesMarkdown, + genGuideMeta, + genGuidesStaticParams, +} from '~/features/docs/GuidesMdx.utils' +import { GuideTemplate } from '~/features/docs/GuidesMdx.template' + +export const dynamicParams = false + +type Params = { slug?: string[] } + +const AuthGuidePage = async ({ params }: { params: Params }) => { + const slug = ['auth', ...(params.slug ?? [])] + const data = await getGuidesMarkdown(slug) + + return +} + +const generateStaticParams = genGuidesStaticParams('auth') +const generateMetadata = genGuideMeta((params: { slug?: string[] }) => + getGuidesMarkdown(['auth', ...(params.slug ?? [])]) +) + +export default AuthGuidePage +export { generateStaticParams, generateMetadata } diff --git a/apps/docs/app/guides/auth/layout.tsx b/apps/docs/app/guides/auth/layout.tsx new file mode 100644 index 00000000000..a7166e638ab --- /dev/null +++ b/apps/docs/app/guides/auth/layout.tsx @@ -0,0 +1,5 @@ +import Layout from '~/layouts/guides' + +export default async function AuthLayout({ children }: { children: React.ReactNode }) { + return {children} +} diff --git a/apps/docs/app/guides/cron/[[...slug]]/page.tsx b/apps/docs/app/guides/cron/[[...slug]]/page.tsx new file mode 100644 index 00000000000..fb55f0fac85 --- /dev/null +++ b/apps/docs/app/guides/cron/[[...slug]]/page.tsx @@ -0,0 +1,25 @@ +import { + getGuidesMarkdown, + genGuideMeta, + genGuidesStaticParams, +} from '~/features/docs/GuidesMdx.utils' +import { GuideTemplate } from '~/features/docs/GuidesMdx.template' + +export const dynamicParams = false + +type Params = { slug?: string[] } + +const CronGuidePage = async ({ params }: { params: Params }) => { + const slug = ['cron', ...(params.slug ?? [])] + const data = await getGuidesMarkdown(slug) + + return +} + +const generateStaticParams = genGuidesStaticParams('cron') +const generateMetadata = genGuideMeta((params: { slug?: string[] }) => + getGuidesMarkdown(['cron', ...(params.slug ?? [])]) +) + +export default CronGuidePage +export { generateStaticParams, generateMetadata } diff --git a/apps/docs/app/guides/cron/layout.tsx b/apps/docs/app/guides/cron/layout.tsx new file mode 100644 index 00000000000..23446ce2fef --- /dev/null +++ b/apps/docs/app/guides/cron/layout.tsx @@ -0,0 +1,5 @@ +import Layout from '~/layouts/guides' + +export default async function CronLayout({ children }: { children: React.ReactNode }) { + return {children} +} diff --git a/apps/docs/app/guides/database/[[...slug]]/page.tsx b/apps/docs/app/guides/database/[[...slug]]/page.tsx new file mode 100644 index 00000000000..0f92d872d92 --- /dev/null +++ b/apps/docs/app/guides/database/[[...slug]]/page.tsx @@ -0,0 +1,25 @@ +import { + getGuidesMarkdown, + genGuideMeta, + genGuidesStaticParams, +} from '~/features/docs/GuidesMdx.utils' +import { GuideTemplate } from '~/features/docs/GuidesMdx.template' + +export const dynamicParams = false + +type Params = { slug?: string[] } + +const DatabaseGuidePage = async ({ params }: { params: Params }) => { + const slug = ['database', ...(params.slug ?? [])] + const data = await getGuidesMarkdown(slug) + + return +} + +const generateStaticParams = genGuidesStaticParams('database') +const generateMetadata = genGuideMeta((params: { slug?: string[] }) => + getGuidesMarkdown(['database', ...(params.slug ?? [])]) +) + +export default DatabaseGuidePage +export { generateStaticParams, generateMetadata } diff --git a/apps/docs/app/guides/(with-sidebar)/database/database-advisors/page.tsx b/apps/docs/app/guides/database/database-advisors/page.tsx similarity index 100% rename from apps/docs/app/guides/(with-sidebar)/database/database-advisors/page.tsx rename to apps/docs/app/guides/database/database-advisors/page.tsx diff --git a/apps/docs/app/guides/(with-sidebar)/database/extensions/wrappers/[[...slug]]/page.tsx b/apps/docs/app/guides/database/extensions/wrappers/[[...slug]]/page.tsx similarity index 99% rename from apps/docs/app/guides/(with-sidebar)/database/extensions/wrappers/[[...slug]]/page.tsx rename to apps/docs/app/guides/database/extensions/wrappers/[[...slug]]/page.tsx index 548a836ea1f..ca59f1707c2 100644 --- a/apps/docs/app/guides/(with-sidebar)/database/extensions/wrappers/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/database/extensions/wrappers/[[...slug]]/page.tsx @@ -18,6 +18,8 @@ import remarkMkDocsAdmonition from '~/lib/mdx/plugins/remarkAdmonition' import { removeTitle } from '~/lib/mdx/plugins/remarkRemoveTitle' import remarkPyMdownTabs from '~/lib/mdx/plugins/remarkTabs' +export const dynamicParams = false + // We fetch these docs at build time from an external repo const org = 'supabase' const repo = 'wrappers' diff --git a/apps/docs/app/guides/database/layout.tsx b/apps/docs/app/guides/database/layout.tsx new file mode 100644 index 00000000000..530c23748d5 --- /dev/null +++ b/apps/docs/app/guides/database/layout.tsx @@ -0,0 +1,5 @@ +import Layout from '~/layouts/guides' + +export default async function DatabaseLayout({ children }: { children: React.ReactNode }) { + return {children} +} diff --git a/apps/docs/app/guides/deployment/[[...slug]]/page.tsx b/apps/docs/app/guides/deployment/[[...slug]]/page.tsx new file mode 100644 index 00000000000..5c4311b6ede --- /dev/null +++ b/apps/docs/app/guides/deployment/[[...slug]]/page.tsx @@ -0,0 +1,25 @@ +import { + getGuidesMarkdown, + genGuideMeta, + genGuidesStaticParams, +} from '~/features/docs/GuidesMdx.utils' +import { GuideTemplate } from '~/features/docs/GuidesMdx.template' + +export const dynamicParams = false + +type Params = { slug?: string[] } + +const DeploymentGuidePage = async ({ params }: { params: Params }) => { + const slug = ['deployment', ...(params.slug ?? [])] + const data = await getGuidesMarkdown(slug) + + return +} + +const generateStaticParams = genGuidesStaticParams('deployment') +const generateMetadata = genGuideMeta((params: { slug?: string[] }) => + getGuidesMarkdown(['deployment', ...(params.slug ?? [])]) +) + +export default DeploymentGuidePage +export { generateStaticParams, generateMetadata } diff --git a/apps/docs/app/guides/(with-sidebar)/deployment/ci/[slug]/page.tsx b/apps/docs/app/guides/deployment/ci/[slug]/page.tsx similarity index 99% rename from apps/docs/app/guides/(with-sidebar)/deployment/ci/[slug]/page.tsx rename to apps/docs/app/guides/deployment/ci/[slug]/page.tsx index 670219d4896..c505be8f3bf 100644 --- a/apps/docs/app/guides/(with-sidebar)/deployment/ci/[slug]/page.tsx +++ b/apps/docs/app/guides/deployment/ci/[slug]/page.tsx @@ -11,6 +11,8 @@ import remarkMkDocsAdmonition from '~/lib/mdx/plugins/remarkAdmonition' import { removeTitle } from '~/lib/mdx/plugins/remarkRemoveTitle' import remarkPyMdownTabs from '~/lib/mdx/plugins/remarkTabs' +export const dynamicParams = false + // We fetch these docs at build time from an external repo const org = 'supabase' const repo = 'setup-cli' diff --git a/apps/docs/app/guides/deployment/layout.tsx b/apps/docs/app/guides/deployment/layout.tsx new file mode 100644 index 00000000000..aa230536e47 --- /dev/null +++ b/apps/docs/app/guides/deployment/layout.tsx @@ -0,0 +1,5 @@ +import Layout from '~/layouts/guides' + +export default async function DeploymentLayout({ children }: { children: React.ReactNode }) { + return {children} +} diff --git a/apps/docs/app/guides/(with-sidebar)/deployment/terraform/[[...slug]]/page.tsx b/apps/docs/app/guides/deployment/terraform/[[...slug]]/page.tsx similarity index 99% rename from apps/docs/app/guides/(with-sidebar)/deployment/terraform/[[...slug]]/page.tsx rename to apps/docs/app/guides/deployment/terraform/[[...slug]]/page.tsx index ef81a3efe99..bd8e51bde05 100644 --- a/apps/docs/app/guides/(with-sidebar)/deployment/terraform/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/deployment/terraform/[[...slug]]/page.tsx @@ -18,6 +18,8 @@ import { terraformDocsRepo, } from '../terraformConstants' +export const dynamicParams = false + // Each external docs page is mapped to a local page const pageMap = [ { diff --git a/apps/docs/app/guides/(with-sidebar)/deployment/terraform/reference/page.tsx b/apps/docs/app/guides/deployment/terraform/reference/page.tsx similarity index 100% rename from apps/docs/app/guides/(with-sidebar)/deployment/terraform/reference/page.tsx rename to apps/docs/app/guides/deployment/terraform/reference/page.tsx diff --git a/apps/docs/app/guides/(with-sidebar)/deployment/terraform/terraformConstants.ts b/apps/docs/app/guides/deployment/terraform/terraformConstants.ts similarity index 100% rename from apps/docs/app/guides/(with-sidebar)/deployment/terraform/terraformConstants.ts rename to apps/docs/app/guides/deployment/terraform/terraformConstants.ts diff --git a/apps/docs/app/guides/functions/[[...slug]]/page.tsx b/apps/docs/app/guides/functions/[[...slug]]/page.tsx new file mode 100644 index 00000000000..e6f2c65a84b --- /dev/null +++ b/apps/docs/app/guides/functions/[[...slug]]/page.tsx @@ -0,0 +1,25 @@ +import { + getGuidesMarkdown, + genGuideMeta, + genGuidesStaticParams, +} from '~/features/docs/GuidesMdx.utils' +import { GuideTemplate } from '~/features/docs/GuidesMdx.template' + +export const dynamicParams = false + +type Params = { slug?: string[] } + +const FunctionsGuidePage = async ({ params }: { params: Params }) => { + const slug = ['functions', ...(params.slug ?? [])] + const data = await getGuidesMarkdown(slug) + + return +} + +const generateStaticParams = genGuidesStaticParams('functions') +const generateMetadata = genGuideMeta((params: { slug?: string[] }) => + getGuidesMarkdown(['functions', ...(params.slug ?? [])]) +) + +export default FunctionsGuidePage +export { generateStaticParams, generateMetadata } diff --git a/apps/docs/app/guides/functions/layout.tsx b/apps/docs/app/guides/functions/layout.tsx new file mode 100644 index 00000000000..b2fc2296797 --- /dev/null +++ b/apps/docs/app/guides/functions/layout.tsx @@ -0,0 +1,5 @@ +import Layout from '~/layouts/guides' + +export default async function FunctionsLayout({ children }: { children: React.ReactNode }) { + return {children} +} diff --git a/apps/docs/app/guides/getting-started/[[...slug]]/page.tsx b/apps/docs/app/guides/getting-started/[[...slug]]/page.tsx new file mode 100644 index 00000000000..429055c817a --- /dev/null +++ b/apps/docs/app/guides/getting-started/[[...slug]]/page.tsx @@ -0,0 +1,25 @@ +import { + getGuidesMarkdown, + genGuideMeta, + genGuidesStaticParams, +} from '~/features/docs/GuidesMdx.utils' +import { GuideTemplate } from '~/features/docs/GuidesMdx.template' + +export const dynamicParams = false + +type Params = { slug?: string[] } + +const GettingStartedGuidePage = async ({ params }: { params: Params }) => { + const slug = ['getting-started', ...(params.slug ?? [])] + const data = await getGuidesMarkdown(slug) + + return +} + +const generateStaticParams = genGuidesStaticParams('getting-started') +const generateMetadata = genGuideMeta((params: { slug?: string[] }) => + getGuidesMarkdown(['getting-started', ...(params.slug ?? [])]) +) + +export default GettingStartedGuidePage +export { generateStaticParams, generateMetadata } diff --git a/apps/docs/app/guides/(with-sidebar)/getting-started/ai-prompts/[slug]/AiPrompts.utils.ts b/apps/docs/app/guides/getting-started/ai-prompts/[slug]/AiPrompts.utils.ts similarity index 100% rename from apps/docs/app/guides/(with-sidebar)/getting-started/ai-prompts/[slug]/AiPrompts.utils.ts rename to apps/docs/app/guides/getting-started/ai-prompts/[slug]/AiPrompts.utils.ts diff --git a/apps/docs/app/guides/(with-sidebar)/getting-started/ai-prompts/[slug]/AiPromptsIndex.tsx b/apps/docs/app/guides/getting-started/ai-prompts/[slug]/AiPromptsIndex.tsx similarity index 100% rename from apps/docs/app/guides/(with-sidebar)/getting-started/ai-prompts/[slug]/AiPromptsIndex.tsx rename to apps/docs/app/guides/getting-started/ai-prompts/[slug]/AiPromptsIndex.tsx diff --git a/apps/docs/app/guides/(with-sidebar)/getting-started/ai-prompts/[slug]/page.tsx b/apps/docs/app/guides/getting-started/ai-prompts/[slug]/page.tsx similarity index 100% rename from apps/docs/app/guides/(with-sidebar)/getting-started/ai-prompts/[slug]/page.tsx rename to apps/docs/app/guides/getting-started/ai-prompts/[slug]/page.tsx diff --git a/apps/docs/app/guides/getting-started/layout.tsx b/apps/docs/app/guides/getting-started/layout.tsx new file mode 100644 index 00000000000..ba83678f3b7 --- /dev/null +++ b/apps/docs/app/guides/getting-started/layout.tsx @@ -0,0 +1,20 @@ +import { type NavMenuSection } from '~/components/Navigation/Navigation.types' +import Layout from '~/layouts/guides' +import { getAiPrompts } from '../getting-started/ai-prompts/[slug]/AiPrompts.utils' + +export default async function GettingStartedLayout({ children }: { children: React.ReactNode }) { + const additionalNavItems = { prompts: await getPrompts() } + + return {children} +} + +async function getPrompts() { + const prompts = await getAiPrompts() + return prompts.map( + (prompt) => + ({ + name: prompt.heading, + url: `/guides/getting-started/ai-prompts/${prompt.filename}`, + }) as Partial + ) +} diff --git a/apps/docs/app/guides/(with-sidebar)/graphql/[[...slug]]/page.tsx b/apps/docs/app/guides/graphql/[[...slug]]/page.tsx similarity index 99% rename from apps/docs/app/guides/(with-sidebar)/graphql/[[...slug]]/page.tsx rename to apps/docs/app/guides/graphql/[[...slug]]/page.tsx index e45d272a948..fbf0d930735 100644 --- a/apps/docs/app/guides/(with-sidebar)/graphql/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/graphql/[[...slug]]/page.tsx @@ -11,6 +11,8 @@ import remarkMkDocsAdmonition from '~/lib/mdx/plugins/remarkAdmonition' import { removeTitle } from '~/lib/mdx/plugins/remarkRemoveTitle' import remarkPyMdownTabs from '~/lib/mdx/plugins/remarkTabs' +export const dynamicParams = false + // We fetch these docs at build time from an external repo const org = 'supabase' const repo = 'pg_graphql' diff --git a/apps/docs/app/guides/graphql/layout.tsx b/apps/docs/app/guides/graphql/layout.tsx new file mode 100644 index 00000000000..59db0623dac --- /dev/null +++ b/apps/docs/app/guides/graphql/layout.tsx @@ -0,0 +1,5 @@ +import Layout from '~/layouts/guides' + +export default async function GraphQlLayout({ children }: { children: React.ReactNode }) { + return {children} +} diff --git a/apps/docs/app/guides/integrations/[[...slug]]/page.tsx b/apps/docs/app/guides/integrations/[[...slug]]/page.tsx new file mode 100644 index 00000000000..34f193e076b --- /dev/null +++ b/apps/docs/app/guides/integrations/[[...slug]]/page.tsx @@ -0,0 +1,25 @@ +import { + getGuidesMarkdown, + genGuideMeta, + genGuidesStaticParams, +} from '~/features/docs/GuidesMdx.utils' +import { GuideTemplate } from '~/features/docs/GuidesMdx.template' + +export const dynamicParams = false + +type Params = { slug?: string[] } + +const IntegrationsGuidePage = async ({ params }: { params: Params }) => { + const slug = ['integrations', ...(params.slug ?? [])] + const data = await getGuidesMarkdown(slug) + + return +} + +const generateStaticParams = genGuidesStaticParams('integrations') +const generateMetadata = genGuideMeta((params: { slug?: string[] }) => + getGuidesMarkdown(['integrations', ...(params.slug ?? [])]) +) + +export default IntegrationsGuidePage +export { generateStaticParams, generateMetadata } diff --git a/apps/docs/app/guides/integrations/layout.tsx b/apps/docs/app/guides/integrations/layout.tsx new file mode 100644 index 00000000000..7b5943f2253 --- /dev/null +++ b/apps/docs/app/guides/integrations/layout.tsx @@ -0,0 +1,39 @@ +import { IS_PLATFORM } from 'common' +import { unstable_cache } from 'next/cache' + +import { type NavMenuSection } from '~/components/Navigation/Navigation.types' +import Layout from '~/layouts/guides' +import { supabaseMisc } from '~/lib/supabaseMisc' + +export default async function IntegrationsLayout({ children }: { children: React.ReactNode }) { + const additionalNavItems = { integrations: await getPartners() } + + return {children} +} + +// Will need to turn on revalidation later, just turning it off for now so we +// can slowly turn things back on while monitoring usage +const getPartners = unstable_cache(getPartnersImpl, [], { revalidate: false }) +async function getPartnersImpl() { + if (!IS_PLATFORM) return [] + + const { data, error } = await supabaseMisc() + .from('partners') + .select('slug, title') + .eq('approved', true) + .eq('type', 'technology') + .order('title') + if (error) { + console.error(new Error('Error fetching partners', { cause: error })) + } + + const partnerNavItems = (data ?? []).map( + (partner) => + ({ + name: partner.title, + url: `https://supabase.com/partners/integrations/${partner.slug}` as `https://${string}`, + }) as Partial + ) + + return partnerNavItems +} diff --git a/apps/docs/app/guides/local-development/[[...slug]]/page.tsx b/apps/docs/app/guides/local-development/[[...slug]]/page.tsx new file mode 100644 index 00000000000..1bd6814e8c1 --- /dev/null +++ b/apps/docs/app/guides/local-development/[[...slug]]/page.tsx @@ -0,0 +1,25 @@ +import { + getGuidesMarkdown, + genGuideMeta, + genGuidesStaticParams, +} from '~/features/docs/GuidesMdx.utils' +import { GuideTemplate } from '~/features/docs/GuidesMdx.template' + +export const dynamicParams = false + +type Params = { slug?: string[] } + +const LocalDevelopmentGuidePage = async ({ params }: { params: Params }) => { + const slug = ['local-development', ...(params.slug ?? [])] + const data = await getGuidesMarkdown(slug) + + return +} + +const generateStaticParams = genGuidesStaticParams('local-development') +const generateMetadata = genGuideMeta((params: { slug?: string[] }) => + getGuidesMarkdown(['local-development', ...(params.slug ?? [])]) +) + +export default LocalDevelopmentGuidePage +export { generateStaticParams, generateMetadata } diff --git a/apps/docs/app/guides/(with-sidebar)/config/page.tsx b/apps/docs/app/guides/local-development/cli/config/page.tsx similarity index 100% rename from apps/docs/app/guides/(with-sidebar)/config/page.tsx rename to apps/docs/app/guides/local-development/cli/config/page.tsx diff --git a/apps/docs/app/guides/local-development/layout.tsx b/apps/docs/app/guides/local-development/layout.tsx new file mode 100644 index 00000000000..b73f4d90a5c --- /dev/null +++ b/apps/docs/app/guides/local-development/layout.tsx @@ -0,0 +1,5 @@ +import Layout from '~/layouts/guides' + +export default async function LocalDevelopmentLayout({ children }: { children: React.ReactNode }) { + return {children} +} diff --git a/apps/docs/app/guides/monitoring-troubleshooting/[[...slug]]/page.tsx b/apps/docs/app/guides/monitoring-troubleshooting/[[...slug]]/page.tsx new file mode 100644 index 00000000000..3936f2e8110 --- /dev/null +++ b/apps/docs/app/guides/monitoring-troubleshooting/[[...slug]]/page.tsx @@ -0,0 +1,25 @@ +import { + getGuidesMarkdown, + genGuideMeta, + genGuidesStaticParams, +} from '~/features/docs/GuidesMdx.utils' +import { GuideTemplate } from '~/features/docs/GuidesMdx.template' + +export const dynamicParams = false + +type Params = { slug?: string[] } + +const MonitoringTroubleshootingGuidePage = async ({ params }: { params: Params }) => { + const slug = ['monitoring-troubleshooting', ...(params.slug ?? [])] + const data = await getGuidesMarkdown(slug) + + return +} + +const generateStaticParams = genGuidesStaticParams('monitoring-troubleshooting') +const generateMetadata = genGuideMeta((params: { slug?: string[] }) => + getGuidesMarkdown(['monitoring-troubleshooting', ...(params.slug ?? [])]) +) + +export default MonitoringTroubleshootingGuidePage +export { generateStaticParams, generateMetadata } diff --git a/apps/docs/app/guides/monitoring-troubleshooting/layout.tsx b/apps/docs/app/guides/monitoring-troubleshooting/layout.tsx new file mode 100644 index 00000000000..f3deff839e7 --- /dev/null +++ b/apps/docs/app/guides/monitoring-troubleshooting/layout.tsx @@ -0,0 +1,9 @@ +import Layout from '~/layouts/guides' + +export default async function MonitoringTroubleshootingLayout({ + children, +}: { + children: React.ReactNode +}) { + return {children} +} diff --git a/apps/docs/app/guides/platform/[[...slug]]/page.tsx b/apps/docs/app/guides/platform/[[...slug]]/page.tsx new file mode 100644 index 00000000000..0c76803590a --- /dev/null +++ b/apps/docs/app/guides/platform/[[...slug]]/page.tsx @@ -0,0 +1,25 @@ +import { + getGuidesMarkdown, + genGuideMeta, + genGuidesStaticParams, +} from '~/features/docs/GuidesMdx.utils' +import { GuideTemplate } from '~/features/docs/GuidesMdx.template' + +export const dynamicParams = false + +type Params = { slug?: string[] } + +const PlatformGuidePage = async ({ params }: { params: Params }) => { + const slug = ['platform', ...(params.slug ?? [])] + const data = await getGuidesMarkdown(slug) + + return +} + +const generateStaticParams = genGuidesStaticParams('platform') +const generateMetadata = genGuideMeta((params: { slug?: string[] }) => + getGuidesMarkdown(['platform', ...(params.slug ?? [])]) +) + +export default PlatformGuidePage +export { generateStaticParams, generateMetadata } diff --git a/apps/docs/app/guides/platform/layout.tsx b/apps/docs/app/guides/platform/layout.tsx new file mode 100644 index 00000000000..5af6fa712c6 --- /dev/null +++ b/apps/docs/app/guides/platform/layout.tsx @@ -0,0 +1,5 @@ +import Layout from '~/layouts/guides' + +export default async function PlatformLayout({ children }: { children: React.ReactNode }) { + return {children} +} diff --git a/apps/docs/app/guides/queues/[[...slug]]/page.tsx b/apps/docs/app/guides/queues/[[...slug]]/page.tsx new file mode 100644 index 00000000000..364dbb83475 --- /dev/null +++ b/apps/docs/app/guides/queues/[[...slug]]/page.tsx @@ -0,0 +1,25 @@ +import { + getGuidesMarkdown, + genGuideMeta, + genGuidesStaticParams, +} from '~/features/docs/GuidesMdx.utils' +import { GuideTemplate } from '~/features/docs/GuidesMdx.template' + +export const dynamicParams = false + +type Params = { slug?: string[] } + +const QueuesGuidePage = async ({ params }: { params: Params }) => { + const slug = ['queues', ...(params.slug ?? [])] + const data = await getGuidesMarkdown(slug) + + return +} + +const generateStaticParams = genGuidesStaticParams('queues') +const generateMetadata = genGuideMeta((params: { slug?: string[] }) => + getGuidesMarkdown(['queues', ...(params.slug ?? [])]) +) + +export default QueuesGuidePage +export { generateStaticParams, generateMetadata } diff --git a/apps/docs/app/guides/queues/layout.tsx b/apps/docs/app/guides/queues/layout.tsx new file mode 100644 index 00000000000..ac9d5c9042f --- /dev/null +++ b/apps/docs/app/guides/queues/layout.tsx @@ -0,0 +1,5 @@ +import Layout from '~/layouts/guides' + +export default async function QueuesLayout({ children }: { children: React.ReactNode }) { + return {children} +} diff --git a/apps/docs/app/guides/realtime/[[...slug]]/page.tsx b/apps/docs/app/guides/realtime/[[...slug]]/page.tsx new file mode 100644 index 00000000000..7a19de3cd7b --- /dev/null +++ b/apps/docs/app/guides/realtime/[[...slug]]/page.tsx @@ -0,0 +1,25 @@ +import { + getGuidesMarkdown, + genGuideMeta, + genGuidesStaticParams, +} from '~/features/docs/GuidesMdx.utils' +import { GuideTemplate } from '~/features/docs/GuidesMdx.template' + +export const dynamicParams = false + +type Params = { slug?: string[] } + +const RealtimeGuidePage = async ({ params }: { params: Params }) => { + const slug = ['realtime', ...(params.slug ?? [])] + const data = await getGuidesMarkdown(slug) + + return +} + +const generateStaticParams = genGuidesStaticParams('realtime') +const generateMetadata = genGuideMeta((params: { slug?: string[] }) => + getGuidesMarkdown(['realtime', ...(params.slug ?? [])]) +) + +export default RealtimeGuidePage +export { generateStaticParams, generateMetadata } diff --git a/apps/docs/app/guides/realtime/layout.tsx b/apps/docs/app/guides/realtime/layout.tsx new file mode 100644 index 00000000000..cb5d8dbada2 --- /dev/null +++ b/apps/docs/app/guides/realtime/layout.tsx @@ -0,0 +1,5 @@ +import Layout from '~/layouts/guides' + +export default async function RealtimeLayout({ children }: { children: React.ReactNode }) { + return {children} +} diff --git a/apps/docs/app/guides/resources/[[...slug]]/page.tsx b/apps/docs/app/guides/resources/[[...slug]]/page.tsx new file mode 100644 index 00000000000..ca23754cc5a --- /dev/null +++ b/apps/docs/app/guides/resources/[[...slug]]/page.tsx @@ -0,0 +1,25 @@ +import { + getGuidesMarkdown, + genGuideMeta, + genGuidesStaticParams, +} from '~/features/docs/GuidesMdx.utils' +import { GuideTemplate } from '~/features/docs/GuidesMdx.template' + +export const dynamicParams = false + +type Params = { slug?: string[] } + +const ResourcesGuidePage = async ({ params }: { params: Params }) => { + const slug = ['resources', ...(params.slug ?? [])] + const data = await getGuidesMarkdown(slug) + + return +} + +const generateStaticParams = genGuidesStaticParams('resources') +const generateMetadata = genGuideMeta((params: { slug?: string[] }) => + getGuidesMarkdown(['resources', ...(params.slug ?? [])]) +) + +export default ResourcesGuidePage +export { generateStaticParams, generateMetadata } diff --git a/apps/docs/app/guides/resources/layout.tsx b/apps/docs/app/guides/resources/layout.tsx new file mode 100644 index 00000000000..8b9d1ae4678 --- /dev/null +++ b/apps/docs/app/guides/resources/layout.tsx @@ -0,0 +1,5 @@ +import Layout from '~/layouts/guides' + +export default async function ResourcesLayout({ children }: { children: React.ReactNode }) { + return {children} +} diff --git a/apps/docs/app/guides/self-hosting/[[...slug]]/page.tsx b/apps/docs/app/guides/self-hosting/[[...slug]]/page.tsx new file mode 100644 index 00000000000..df826de3827 --- /dev/null +++ b/apps/docs/app/guides/self-hosting/[[...slug]]/page.tsx @@ -0,0 +1,25 @@ +import { + getGuidesMarkdown, + genGuideMeta, + genGuidesStaticParams, +} from '~/features/docs/GuidesMdx.utils' +import { GuideTemplate } from '~/features/docs/GuidesMdx.template' + +export const dynamicParams = false + +type Params = { slug?: string[] } + +const SelfHostingGuidePage = async ({ params }: { params: Params }) => { + const slug = ['self-hosting', ...(params.slug ?? [])] + const data = await getGuidesMarkdown(slug) + + return +} + +const generateStaticParams = genGuidesStaticParams('self-hosting') +const generateMetadata = genGuideMeta((params: { slug?: string[] }) => + getGuidesMarkdown(['self-hosting', ...(params.slug ?? [])]) +) + +export default SelfHostingGuidePage +export { generateStaticParams, generateMetadata } diff --git a/apps/docs/app/guides/(with-sidebar)/self-hosting/analytics/config/page.tsx b/apps/docs/app/guides/self-hosting/analytics/config/page.tsx similarity index 100% rename from apps/docs/app/guides/(with-sidebar)/self-hosting/analytics/config/page.tsx rename to apps/docs/app/guides/self-hosting/analytics/config/page.tsx diff --git a/apps/docs/app/guides/(with-sidebar)/self-hosting/auth/config/page.tsx b/apps/docs/app/guides/self-hosting/auth/config/page.tsx similarity index 100% rename from apps/docs/app/guides/(with-sidebar)/self-hosting/auth/config/page.tsx rename to apps/docs/app/guides/self-hosting/auth/config/page.tsx diff --git a/apps/docs/app/guides/self-hosting/layout.tsx b/apps/docs/app/guides/self-hosting/layout.tsx new file mode 100644 index 00000000000..14a59eb8dd1 --- /dev/null +++ b/apps/docs/app/guides/self-hosting/layout.tsx @@ -0,0 +1,5 @@ +import Layout from '~/layouts/guides' + +export default async function SelfHostingLayout({ children }: { children: React.ReactNode }) { + return {children} +} diff --git a/apps/docs/app/guides/(with-sidebar)/self-hosting/realtime/config/page.tsx b/apps/docs/app/guides/self-hosting/realtime/config/page.tsx similarity index 100% rename from apps/docs/app/guides/(with-sidebar)/self-hosting/realtime/config/page.tsx rename to apps/docs/app/guides/self-hosting/realtime/config/page.tsx diff --git a/apps/docs/app/guides/(with-sidebar)/self-hosting/storage/config/page.tsx b/apps/docs/app/guides/self-hosting/storage/config/page.tsx similarity index 100% rename from apps/docs/app/guides/(with-sidebar)/self-hosting/storage/config/page.tsx rename to apps/docs/app/guides/self-hosting/storage/config/page.tsx diff --git a/apps/docs/app/guides/storage/[[...slug]]/page.tsx b/apps/docs/app/guides/storage/[[...slug]]/page.tsx new file mode 100644 index 00000000000..bf1754495ac --- /dev/null +++ b/apps/docs/app/guides/storage/[[...slug]]/page.tsx @@ -0,0 +1,25 @@ +import { + getGuidesMarkdown, + genGuideMeta, + genGuidesStaticParams, +} from '~/features/docs/GuidesMdx.utils' +import { GuideTemplate } from '~/features/docs/GuidesMdx.template' + +export const dynamicParams = false + +type Params = { slug?: string[] } + +const StorageGuidePage = async ({ params }: { params: Params }) => { + const slug = ['storage', ...(params.slug ?? [])] + const data = await getGuidesMarkdown(slug) + + return +} + +const generateStaticParams = genGuidesStaticParams('storage') +const generateMetadata = genGuideMeta((params: { slug?: string[] }) => + getGuidesMarkdown(['storage', ...(params.slug ?? [])]) +) + +export default StorageGuidePage +export { generateStaticParams, generateMetadata } diff --git a/apps/docs/app/guides/storage/layout.tsx b/apps/docs/app/guides/storage/layout.tsx new file mode 100644 index 00000000000..0a59848fbeb --- /dev/null +++ b/apps/docs/app/guides/storage/layout.tsx @@ -0,0 +1,5 @@ +import Layout from '~/layouts/guides' + +export default async function StorageLayout({ children }: { children: React.ReactNode }) { + return {children} +} diff --git a/apps/docs/features/docs/GuidesMdx.utils.tsx b/apps/docs/features/docs/GuidesMdx.utils.tsx index 1c8b28a4282..63ab629dc43 100644 --- a/apps/docs/features/docs/GuidesMdx.utils.tsx +++ b/apps/docs/features/docs/GuidesMdx.utils.tsx @@ -42,7 +42,7 @@ const PUBLISHED_SECTIONS = [ 'storage', ] as const -const getGuidesMarkdownInternal = async ({ slug }: { slug: string[] }) => { +const getGuidesMarkdownInternal = async (slug: string[]) => { const relPath = slug.join(sep).replace(/\/$/, '') const fullPath = join(GUIDES_DIRECTORY, relPath + '.mdx') /** @@ -60,6 +60,7 @@ const getGuidesMarkdownInternal = async ({ slug }: { slug: string[] }) => { try { mdx = await readFile(fullPath, 'utf-8') } catch { + console.error('Error reading Markdown at path: %s', fullPath) notFound() } @@ -96,6 +97,9 @@ const genGuidesStaticParams = (directory?: string) => async () => { ? (await readdir(join(GUIDES_DIRECTORY, directory), { recursive: true })) .filter((file) => extname(file) === '.mdx' && !file.split(sep).at(-1).startsWith('_')) .map((file) => ({ slug: file.replace(/\.mdx$/, '').split(sep) })) + .concat( + (await existsFile(join(GUIDES_DIRECTORY, `${directory}.mdx`))) ? [{ slug: [] }] : [] + ) : PUBLISHED_SECTIONS.map(async (section) => (await readdir(join(GUIDES_DIRECTORY, section), { recursive: true })) .filter((file) => extname(file) === '.mdx' && !file.split(sep).at(-1).startsWith('_')) diff --git a/apps/docs/features/docs/MdxBase.tsx b/apps/docs/features/docs/MdxBase.tsx index 3077c0a59ae..e3f15e1b10d 100644 --- a/apps/docs/features/docs/MdxBase.tsx +++ b/apps/docs/features/docs/MdxBase.tsx @@ -7,7 +7,7 @@ import remarkGfm from 'remark-gfm' import rehypeKatex from 'rehype-katex' import remarkMath from 'remark-math' -import { AiPromptsIndex } from '~/app/guides/(with-sidebar)/getting-started/ai-prompts/[slug]/AiPromptsIndex' +import { AiPromptsIndex } from '~/app/guides/getting-started/ai-prompts/[slug]/AiPromptsIndex' import { preprocessMdxWithDefaults } from '~/features/directives/utils' import { components } from '~/features/docs/MdxBase.shared' diff --git a/apps/docs/lib/octokit.ts b/apps/docs/lib/octokit.ts index 7f18c36e327..bfe5a0f1b88 100644 --- a/apps/docs/lib/octokit.ts +++ b/apps/docs/lib/octokit.ts @@ -10,6 +10,7 @@ let octokitInstance: Octokit function octokit() { if (!octokitInstance) { + // https://github.com/gr2m/universal-github-app-jwt?tab=readme-ov-file#converting-pkcs1-to-pkcs8 const privateKeyPkcs8 = crypto .createPrivateKey(process.env.DOCS_GITHUB_APP_PRIVATE_KEY) .export({