mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 01:15:03 +03:00
feat(docs): migrate resources and getting-started to ContentListings (#48517)
## What kind of change does this PR introduce? Docs update / follow-up to #48379. ## What is the current behavior? `/guides/resources` and `/guides/getting-started` hand-roll `GlassPanel` grids in MDX. They look like ContentListings cards after the chrome PR, but they do not use the shared data files, so they miss PostHog `docs_content_listing_clicked` telemetry and the CONTRIBUTING contribution path. ## What is the new behavior? Those pages use `<ContentListings id="…" />` backed by `resources.data.ts` and `getting-started.data.ts`, same pattern as storage. - Section-level `$Show` wrappers stay for framework / web / mobile blocks - Nimbus stays a `$Partial` behind `$Show` - New optional per-item `feature` field gates SDK links (e.g. Flutter / Swift / Kotlin) without splitting whole sections - CONTRIBUTING notes when to use `feature` vs a partial-level `$Show` ## To test Compare the following against `master`: - [Resources](https://docs-git-dnywh-docs-content-listings-resources-239158-supabase.vercel.app/docs/guides/resources): overview, migrate, and postgres grids; icons in light/dark - [Getting started](https://docs-git-dnywh-docs-content-listings-resources-239158-supabase.vercel.app/docs/guides/getting-started): overview, use cases, framework quickstarts, web demos, mobile tutorials; nimbus partial when enabled - Click a card and confirm `docs_content_listing_clicked` fires with the expected `listingId` Everything should look and feel the same. It’s just that we’re using `ContentListings` instead of `GlassPanel` grids. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added centralized Getting Started and Resources content listings, including quickstarts, demos, tutorials, migration guides, and Postgres resources. - Added feature-based visibility controls for individual content listing items. - **Improvements** - Disabled content is now automatically hidden from documentation pages and generated Markdown. - Pages and sections with no available content are omitted entirely. - External documentation links are more secure. - Updated contribution guidance with instructions and examples for feature flags. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
1 parent
e7796315d2
commit
c0f1ef51fb
11 files changed
+581
-557
No files matched your search
@@ -260,7 +260,7 @@ Run `pnpm test:local lib/content-listings.test.ts` from apps/docs.
|
||||
**Manually add content listings:**
|
||||
|
||||
1. Add or update a `ContentListingGroup` export in [`data/content-listings/[topic].data.ts`](data/content-listings/). The `id` field must be globally unique across all listing groups. For example, use `storage-get-started` rather than `get-started`. The ID is both the lookup key and the telemetry `listingId`.
|
||||
2. Place the component inline in guide MDX, for example `<ContentListings id="storage-get-started" />`. Use a partial only when the block is reused or gated with `$Show` at the partial level.
|
||||
2. Place the component inline in guide MDX, for example `<ContentListings id="storage-get-started" />`. Use a partial only when the block is reused or gated with `$Show` at the partial level. For individual items that depend on a feature flag (for example `sdk:dart`), set `feature` on the item instead of wrapping the whole listing.
|
||||
3. Run `pnpm test:local lib/content-listings.test.ts` from `apps/docs`.
|
||||
|
||||
Code snippets for manually adding content listings are available in [`.vscode/content-listing.code-snippets`](../../.vscode/content-listing.code-snippets). Use `cl-data` for a data export with a namespaced ID. Use `cl-inline` for an MDX component.
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
|
||||
import type { ContentListingGroup, ContentListingItem } from '~/lib/content-listings.schema'
|
||||
import {
|
||||
filterContentListingItems,
|
||||
getContentListingById,
|
||||
getContentListingGroupLabel,
|
||||
isExternalContentListingHref,
|
||||
} from '~/lib/content-listings.utils'
|
||||
import { useSendTelemetryEvent } from '~/lib/telemetry'
|
||||
import Link from 'next/link'
|
||||
import { useCallback } from 'react'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { Badge } from 'ui'
|
||||
import { GlassPanel } from 'ui-patterns/GlassPanel'
|
||||
import { Heading } from 'ui/src/components/CustomHTMLElements'
|
||||
@@ -52,10 +53,13 @@ function ContentListingGroupHeading({ group }: { group: ContentListingGroup }) {
|
||||
|
||||
function ContentListingsGroup({ group }: { group: ContentListingGroup }) {
|
||||
const { trackClick } = useContentListingClickHandler(group)
|
||||
const items = useMemo(() => filterContentListingItems(group.items), [group.items])
|
||||
const isGrid = group.type === 'grid'
|
||||
const listClassName = isGrid ? 'grid md:grid-cols-12 gap-4' : 'list-disc pl-6 space-y-2'
|
||||
const gridItemClassName = isGrid ? GRID_ITEM_CLASS[group.columns ?? 3] : undefined
|
||||
|
||||
if (!items.length) return null
|
||||
|
||||
// Heading stays outside `not-prose` so it inherits the surrounding MDX prose
|
||||
// typography. The list itself opts out so its explicit Tailwind layout wins.
|
||||
return (
|
||||
@@ -64,7 +68,7 @@ function ContentListingsGroup({ group }: { group: ContentListingGroup }) {
|
||||
<div className="not-prose space-y-4">
|
||||
{group.description && <p className="text-foreground-light">{group.description}</p>}
|
||||
<ul className={listClassName}>
|
||||
{group.items.map((item) => {
|
||||
{items.map((item) => {
|
||||
const external = isExternalContentListingHref(item.href)
|
||||
const key = `${group.id}-${item.href}`
|
||||
|
||||
@@ -77,6 +81,7 @@ function ContentListingsGroup({ group }: { group: ContentListingGroup }) {
|
||||
className="block h-full"
|
||||
onClick={() => trackClick(item)}
|
||||
target={external ? '_blank' : undefined}
|
||||
rel={external ? 'noopener noreferrer' : undefined}
|
||||
>
|
||||
<GlassPanel
|
||||
title={item.title}
|
||||
@@ -106,6 +111,7 @@ function ContentListingsGroup({ group }: { group: ContentListingGroup }) {
|
||||
href={item.href}
|
||||
onClick={() => trackClick(item)}
|
||||
target={external ? '_blank' : undefined}
|
||||
rel={external ? 'noopener noreferrer' : undefined}
|
||||
>
|
||||
<strong>{item.title}</strong>: {item.description}
|
||||
</Link>
|
||||
@@ -120,7 +126,7 @@ function ContentListingsGroup({ group }: { group: ContentListingGroup }) {
|
||||
|
||||
export function ContentListings({ id }: { id: string }) {
|
||||
const group = getContentListingById(id)
|
||||
if (!group || !group.items.length) return null
|
||||
if (!group || !filterContentListingItems(group.items).length) return null
|
||||
|
||||
return (
|
||||
<div className="my-10 space-y-10">
|
||||
|
||||
@@ -5,214 +5,13 @@ description: 'Resources for getting started with Supabase.'
|
||||
hideToc: true
|
||||
---
|
||||
|
||||
<div className="flex flex-col gap-12 my-12">
|
||||
<ContentListings id="getting-started-overview" />
|
||||
|
||||
<div>
|
||||
|
||||
<div className="grid grid-cols-12 gap-6 not-prose">
|
||||
<Link href="/guides/ai-tools" className="col-span-12 md:col-span-6 xl:col-span-4" passHref>
|
||||
<GlassPanel title="Build with AI tools" hasLightIcon={true} showIconBg={true}>
|
||||
Develop with Supabase AI-first using plugins, MCP, and skills.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/getting-started/api-keys"
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
passHref
|
||||
>
|
||||
<GlassPanel title="API Keys" hasLightIcon={true} showIconBg={true}>
|
||||
Learn about the different API keys in Supabase and how to use them.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/local-development"
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
passHref
|
||||
>
|
||||
<GlassPanel title="Local Development" hasLightIcon={true} showIconBg={true}>
|
||||
Use the Supabase CLI to develop locally and collaborate between teams.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
## Use cases
|
||||
|
||||
<div className="grid lg:grid-cols-12 gap-6 not-prose">
|
||||
<Link href="/guides/ai#examples" passHref className="col-span-12 md:col-span-6 xl:col-span-4">
|
||||
<GlassPanel
|
||||
title="AI, Vectors, and embeddings"
|
||||
icon="/docs/img/icons/openai_logo"
|
||||
hasLightIcon={true}
|
||||
>
|
||||
Build AI-enabled applications using our Vector toolkit.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="https://github.com/vercel/nextjs-subscription-payments#nextjs-subscription-payments-starter"
|
||||
passHref
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
>
|
||||
<GlassPanel title="Subscription Payments (SaaS)" icon="/docs/img/icons/nextjs-icon">
|
||||
Clone, deploy, and fully customize a SaaS subscription application with Next.js.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="https://github.com/supabase-community/partner-gallery-example#supabase-partner-gallery-example"
|
||||
passHref
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
>
|
||||
<GlassPanel title="Partner Gallery" icon="/docs/img/icons/nextjs-icon">
|
||||
Postgres full-text search, image storage, and more.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
## Framework quickstarts
|
||||
<ContentListings id="getting-started-use-cases" />
|
||||
|
||||
<$Show if="docs:framework_quickstarts">
|
||||
|
||||
<div className="grid lg:grid-cols-12 gap-6 not-prose">
|
||||
<Link
|
||||
href="/guides/getting-started/quickstarts/reactjs"
|
||||
passHref
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
>
|
||||
<GlassPanel title="React" icon="/docs/img/icons/react-icon">
|
||||
Learn how to create a Supabase project, add some sample data to your database, and query the
|
||||
data from a React app.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/getting-started/quickstarts/nextjs"
|
||||
passHref
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
>
|
||||
<GlassPanel title="Next.js" icon="/docs/img/icons/nextjs-icon" hasLightIcon={true}>
|
||||
Learn how to create a Supabase project, add some sample data to your database, and query the
|
||||
data from a Next.js app.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/getting-started/quickstarts/nuxtjs"
|
||||
passHref
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
>
|
||||
<GlassPanel title="Nuxt" icon="/docs/img/icons/nuxt-icon">
|
||||
Learn how to create a Supabase project, add some sample data to your database, and query the
|
||||
data from a Nuxt app.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/getting-started/quickstarts/hono"
|
||||
passHref
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
>
|
||||
<GlassPanel title="Hono" icon="/docs/img/icons/hono-icon">
|
||||
Learn how to create a Supabase project, add some sample data to your database, secure it with
|
||||
auth, and query the data from a Hono app.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/getting-started/quickstarts/redwoodjs"
|
||||
passHref
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
>
|
||||
<GlassPanel title="RedwoodJS" icon="/docs/img/icons/redwood-icon">
|
||||
Learn how to create a Supabase project, add some sample data to your database using Prisma
|
||||
migration and seeds, and query the data from a RedwoodJS app.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<$Show if="sdk:dart">
|
||||
<Link
|
||||
href="/guides/getting-started/quickstarts/flutter"
|
||||
passHref
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
>
|
||||
<GlassPanel title="Flutter" icon="/docs/img/icons/flutter-icon">
|
||||
Learn how to create a Supabase project, add some sample data to your database, and query the
|
||||
data from a Flutter app.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
</$Show>
|
||||
<$Show if="sdk:swift">
|
||||
<Link
|
||||
href="/guides/getting-started/quickstarts/ios-swiftui"
|
||||
passHref
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
>
|
||||
<GlassPanel title="iOS SwiftUI" icon="/docs/img/icons/swift-icon">
|
||||
Learn how to create a Supabase project, add some sample data to your database, and query the
|
||||
data from an iOS app.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
</$Show>
|
||||
<$Show if="sdk:kotlin">
|
||||
<Link
|
||||
href="/guides/getting-started/quickstarts/kotlin"
|
||||
passHref
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
>
|
||||
<GlassPanel title="Android Kotlin" icon="/docs/img/icons/kotlin-icon">
|
||||
Learn how to create a Supabase project, add some sample data to your database, and query the
|
||||
data from an Android Kotlin app.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
</$Show>
|
||||
<Link
|
||||
href="/guides/getting-started/quickstarts/sveltekit"
|
||||
passHref
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
>
|
||||
<GlassPanel title="SvelteKit" icon="/docs/img/icons/svelte-icon">
|
||||
Learn how to create a Supabase project, add some sample data to your database, and query the
|
||||
data from a SvelteKit app.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/getting-started/quickstarts/solidjs"
|
||||
passHref
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
>
|
||||
<GlassPanel title="SolidJS" icon="/docs/img/icons/solidjs-icon">
|
||||
Learn how to create a Supabase project, add some sample data to your database, and query the
|
||||
data from a SolidJS app.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/getting-started/quickstarts/vue"
|
||||
passHref
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
>
|
||||
<GlassPanel title="Vue" icon="/docs/img/icons/vuejs-icon">
|
||||
Learn how to create a Supabase project, add some sample data to your database, and query the
|
||||
data from a Vue app.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/getting-started/quickstarts/tanstack"
|
||||
passHref
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
>
|
||||
<GlassPanel title="TanStack Start" icon="/docs/img/icons/tanstack-icon" hasLightIcon={true}>
|
||||
Learn how to create a Supabase project, add some sample data to your database, and query the
|
||||
data from a TanStack Start app.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/getting-started/quickstarts/refine"
|
||||
passHref
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
>
|
||||
<GlassPanel title="Refine" icon="/docs/img/icons/refine-icon">
|
||||
Learn how to create a Supabase project, add some sample data to your database, and query the
|
||||
data from a Refine app.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
</div>
|
||||
<ContentListings id="getting-started-framework-quickstarts" />
|
||||
|
||||
</$Show>
|
||||
|
||||
@@ -224,173 +23,12 @@ hideToc: true
|
||||
|
||||
<$Show if="docs:web_apps">
|
||||
|
||||
## Web app demos
|
||||
<ContentListings id="getting-started-web-app-demos" />
|
||||
|
||||
<div className="grid lg:grid-cols-12 gap-6 not-prose">
|
||||
<Link href="/guides/getting-started/tutorials/with-nextjs" passHref className="col-span-12 md:col-span-6 xl:col-span-4">
|
||||
<GlassPanel
|
||||
title="Next.js"
|
||||
icon="/docs/img/icons/nextjs-icon"
|
||||
hasLightIcon={true}
|
||||
>
|
||||
Learn how to build a user management app with Next.js and Supabase Database, Auth, and Storage functionality.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link href="/guides/getting-started/tutorials/with-react" passHref className="col-span-12 md:col-span-6 xl:col-span-4">
|
||||
<GlassPanel
|
||||
title="React"
|
||||
icon="/docs/img/icons/react-icon"
|
||||
>
|
||||
Learn how to build a user management app with React and Supabase Database, Auth, and Storage functionality.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link href="/guides/getting-started/tutorials/with-vue-3" passHref className="col-span-12 md:col-span-6 xl:col-span-4">
|
||||
<GlassPanel
|
||||
title="Vue 3"
|
||||
icon="/docs/img/icons/vuejs-icon"
|
||||
>
|
||||
Learn how to build a user management app with Vue 3 and Supabase Database, Auth, and Storage functionality.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link href="/guides/getting-started/tutorials/with-nuxt-3" passHref className="col-span-12 md:col-span-6 xl:col-span-4">
|
||||
<GlassPanel
|
||||
title="Nuxt 3"
|
||||
icon="/docs/img/icons/nuxt-icon"
|
||||
>
|
||||
Learn how to build a user management app with Nuxt 3 and Supabase Database, Auth, and Storage functionality.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link href="/guides/getting-started/tutorials/with-angular" passHref className="col-span-12 md:col-span-6 xl:col-span-4">
|
||||
<GlassPanel
|
||||
title="Angular"
|
||||
icon="/docs/img/icons/angular-icon"
|
||||
>
|
||||
Learn how to build a user management app with Angular and Supabase Database, Auth, and Storage functionality.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link href="/guides/getting-started/tutorials/with-redwoodjs" passHref className="col-span-12 md:col-span-6 xl:col-span-4">
|
||||
<GlassPanel
|
||||
title="RedwoodJS"
|
||||
icon="/docs/img/icons/redwood-icon"
|
||||
>
|
||||
Learn how to build a user management app with RedwoodJS and Supabase Database, Auth, and Storage functionality.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link href="/guides/getting-started/tutorials/with-svelte" passHref className="col-span-12 md:col-span-6 xl:col-span-4">
|
||||
<GlassPanel
|
||||
title="Svelte"
|
||||
icon="/docs/img/icons/svelte-icon"
|
||||
>
|
||||
Learn how to build a user management app with Svelte and Supabase Database, Auth, and Storage functionality.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link href="/guides/getting-started/tutorials/with-sveltekit" passHref className="col-span-12 md:col-span-6 xl:col-span-4">
|
||||
<GlassPanel
|
||||
title="SvelteKit"
|
||||
icon="/docs/img/icons/svelte-icon"
|
||||
>
|
||||
Learn how to build a user management app with SvelteKit and Supabase Database, Auth, and Storage functionality.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link href="/guides/getting-started/tutorials/with-refine" passHref className="col-span-12 md:col-span-6 xl:col-span-4">
|
||||
<GlassPanel
|
||||
title="Refine"
|
||||
icon="/docs/img/icons/refine-icon"
|
||||
>
|
||||
Learn how to build a user management app with Refine and Supabase Database, Auth, and Storage functionality.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
</div>
|
||||
</$Show>
|
||||
|
||||
<$Show if="docs:mobile_tutorials">
|
||||
|
||||
## Mobile tutorials
|
||||
<ContentListings id="getting-started-mobile-tutorials" />
|
||||
|
||||
<div className="grid lg:grid-cols-12 gap-6 not-prose">
|
||||
<$Show if="sdk:dart">
|
||||
<Link href="/guides/getting-started/tutorials/with-flutter" passHref className="col-span-12 md:col-span-6 xl:col-span-4">
|
||||
<GlassPanel
|
||||
title="Flutter"
|
||||
icon="/docs/img/icons/flutter-icon"
|
||||
>
|
||||
Learn how to build a user management app with Flutter and Supabase Database, Auth, and Storage functionality.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
</$Show>
|
||||
<Link
|
||||
href="/guides/getting-started/tutorials/with-expo-react-native"
|
||||
passHref
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
>
|
||||
<GlassPanel
|
||||
title="Expo React Native"
|
||||
icon="/docs/img/icons/expo-icon"
|
||||
hasLightIcon={true}
|
||||
>
|
||||
Learn how to build a user management app with Expo React Native and Supabase Database, Auth, and Storage functionality.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/auth/quickstarts/with-expo-react-native-social-auth"
|
||||
passHref
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
>
|
||||
<GlassPanel
|
||||
title="Expo React Native Social Auth"
|
||||
icon="/docs/img/icons/expo-icon"
|
||||
hasLightIcon={true}
|
||||
>
|
||||
Learn how to implement social authentication in an app with Expo React Native and Supabase Database and Auth functionality.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<$Show if="sdk:kotlin">
|
||||
<Link href="/guides/getting-started/tutorials/with-kotlin" passHref className="col-span-12 md:col-span-6 xl:col-span-4">
|
||||
<GlassPanel
|
||||
title="Android Kotlin"
|
||||
icon="/docs/img/icons/kotlin-icon"
|
||||
>
|
||||
Learn how to build a product management app with Android and Supabase Database, Auth, and Storage functionality.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
</$Show>
|
||||
<$Show if="sdk:swift">
|
||||
<Link href="/guides/getting-started/tutorials/with-swift" passHref className="col-span-12 md:col-span-6 xl:col-span-4">
|
||||
<GlassPanel
|
||||
title="iOS Swift"
|
||||
icon="/docs/img/icons/swift-icon"
|
||||
>
|
||||
Learn how to build a user management app with iOS and Supabase Database, Auth, and Storage functionality.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
</$Show>
|
||||
<Link href="/guides/getting-started/tutorials/with-ionic-react" passHref className="col-span-12 md:col-span-6 xl:col-span-4">
|
||||
<GlassPanel
|
||||
title="Ionic React"
|
||||
icon="/docs/img/icons/ionic-icon"
|
||||
>
|
||||
Learn how to build a user management app with Ionic React and Supabase Database, Auth, and Storage functionality.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link href="/guides/getting-started/tutorials/with-ionic-vue" passHref className="col-span-12 md:col-span-6 xl:col-span-4">
|
||||
<GlassPanel
|
||||
title="Ionic Vue"
|
||||
icon="/docs/img/icons/ionic-icon"
|
||||
>
|
||||
Learn how to build a user management app with Ionic Vue and Supabase Database, Auth, and Storage functionality.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/getting-started/tutorials/with-ionic-angular"
|
||||
passHref
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
>
|
||||
<GlassPanel
|
||||
title="Ionic Angular"
|
||||
icon="/docs/img/icons/ionic-icon"
|
||||
>
|
||||
Learn how to build a user management app with Ionic Angular and Supabase Database, Auth, and Storage functionality.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
</div>
|
||||
</$Show>
|
||||
@@ -6,188 +6,8 @@ hideToc: true
|
||||
|
||||
{/* <!-- vale off --> */}
|
||||
|
||||
<div className="flex flex-col gap-12 my-12">
|
||||
<ContentListings id="resources-overview" />
|
||||
|
||||
<div>
|
||||
<ContentListings id="resources-migrate" />
|
||||
|
||||
<div className="grid grid-cols-12 gap-6 not-prose">
|
||||
<Link href="/guides/getting-started" className="col-span-12 md:col-span-6 xl:col-span-4" passHref>
|
||||
<GlassPanel title="Examples" hasLightIcon={true} showIconBg={true}>
|
||||
Official GitHub examples, curated content from the community, and more.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/resources/glossary"
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
passHref
|
||||
>
|
||||
<GlassPanel title="Glossary" hasLightIcon={true} showIconBg={true}>
|
||||
Definitions for terminology and acronyms used in the Supabase documentation.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="max-w-xl mb-6">
|
||||
|
||||
## Migrate to Supabase
|
||||
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-12 gap-6 not-prose">
|
||||
<Link
|
||||
href="/guides/platform/migrating-to-supabase/auth0"
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
passHref
|
||||
>
|
||||
<GlassPanel title="Auth0" icon="/docs/img/icons/auth0-icon" hasLightIcon={true}>
|
||||
Move your auth users from Auth0 to a Supabase project.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/platform/migrating-to-supabase/firebase-auth"
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
passHref
|
||||
>
|
||||
<GlassPanel title="Firebase Auth" icon="/docs/img/icons/firebase-icon">
|
||||
Move your auth users from a Firebase project to a Supabase project.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/platform/migrating-to-supabase/firestore-data"
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
passHref
|
||||
>
|
||||
<GlassPanel title="Firestore Data" icon="/docs/img/icons/firebase-icon">
|
||||
Migrate the contents of a Firestore collection to a single Postgres table.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/platform/migrating-to-supabase/firebase-storage"
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
passHref
|
||||
>
|
||||
<GlassPanel title="Firebase Storage" icon="/docs/img/icons/firebase-icon">
|
||||
Convert your Firebase Storage files to Supabase Storage.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/platform/migrating-to-supabase/heroku"
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
passHref
|
||||
>
|
||||
<GlassPanel title="Heroku" icon="/docs/img/icons/heroku-icon">
|
||||
Migrate your Heroku Postgres database to Supabase.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/platform/migrating-to-supabase/render"
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
passHref
|
||||
>
|
||||
<GlassPanel title="Render" icon="/docs/img/icons/render-icon">
|
||||
Migrate your Render Postgres database to Supabase.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/platform/migrating-to-supabase/amazon-rds"
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
passHref
|
||||
>
|
||||
<GlassPanel title="Amazon RDS" icon="/docs/img/icons/aws-rds-icon">
|
||||
Migrate your Amazon RDS database to Supabase.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/platform/migrating-to-supabase/postgres"
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
passHref
|
||||
>
|
||||
<GlassPanel title="Postgres" icon="/docs/img/icons/postgres-icon">
|
||||
Migrate your Postgres database to Supabase.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/platform/migrating-to-supabase/mysql"
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
passHref
|
||||
>
|
||||
<GlassPanel title="MySQL" icon="/docs/img/icons/mysql-icon">
|
||||
Migrate your MySQL database to Supabase.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/platform/migrating-to-supabase/mssql"
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
passHref
|
||||
>
|
||||
<GlassPanel title="Microsoft SQL Server" icon="/docs/img/icons/mssql-icon">
|
||||
Migrate your Microsoft SQL Server database to Supabase.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="max-w-xl mb-6">
|
||||
|
||||
## Postgres resources
|
||||
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-12 gap-6 not-prose">
|
||||
<Link
|
||||
href="/guides/database/postgres/indexes"
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
passHref
|
||||
>
|
||||
<GlassPanel title="Managing Indexes" hasLightIcon={true} showIconBg={true}>
|
||||
Improve query performance using various index types in Postgres.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/database/postgres/cascade-deletes"
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
passHref
|
||||
>
|
||||
<GlassPanel title="Cascade Deletes" hasLightIcon={true} showIconBg={true}>
|
||||
Understand the types of foreign key constraint deletes.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/database/postgres/dropping-all-tables-in-schema"
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
passHref
|
||||
>
|
||||
<GlassPanel title="Drop all tables in schema" hasLightIcon={true} showIconBg={true}>
|
||||
Delete all tables in a given schema.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/database/postgres/first-row-in-group"
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
passHref
|
||||
>
|
||||
<GlassPanel title="Select first row per group" hasLightIcon={true} showIconBg={true}>
|
||||
Retrieve the first row in each distinct group.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
<Link
|
||||
href="/guides/database/postgres/which-version-of-postgres"
|
||||
className="col-span-12 md:col-span-6 xl:col-span-4"
|
||||
passHref
|
||||
>
|
||||
<GlassPanel title="Print Postgres version" hasLightIcon={true} showIconBg={true}>
|
||||
Find out which version of Postgres you are running.
|
||||
</GlassPanel>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* end of container */}
|
||||
|
||||
</div>
|
||||
<ContentListings id="resources-postgres" />
|
||||
@@ -0,0 +1,327 @@
|
||||
import type { ContentListingGroup } from '~/lib/content-listings.schema'
|
||||
|
||||
export const gettingStartedOverview: ContentListingGroup = {
|
||||
id: 'getting-started-overview',
|
||||
type: 'grid',
|
||||
items: [
|
||||
{
|
||||
title: 'Build with AI tools',
|
||||
href: '/guides/ai-tools',
|
||||
description: 'Develop with Supabase AI-first using plugins, MCP, and skills.',
|
||||
},
|
||||
{
|
||||
title: 'API Keys',
|
||||
href: '/guides/getting-started/api-keys',
|
||||
description: 'Learn about the different API keys in Supabase and how to use them.',
|
||||
},
|
||||
{
|
||||
title: 'Local Development',
|
||||
href: '/guides/local-development',
|
||||
description: 'Use the Supabase CLI to develop locally and collaborate between teams.',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export const gettingStartedUseCases: ContentListingGroup = {
|
||||
id: 'getting-started-use-cases',
|
||||
heading: 'Use cases',
|
||||
headingLevel: 'h3',
|
||||
type: 'grid',
|
||||
items: [
|
||||
{
|
||||
title: 'AI, Vectors, and embeddings',
|
||||
href: '/guides/ai#examples',
|
||||
icon: '/docs/img/icons/openai_logo',
|
||||
hasLightIcon: true,
|
||||
description: 'Build AI-enabled applications using our Vector toolkit.',
|
||||
},
|
||||
{
|
||||
title: 'Subscription Payments (SaaS)',
|
||||
href: 'https://github.com/vercel/nextjs-subscription-payments#nextjs-subscription-payments-starter',
|
||||
icon: '/docs/img/icons/nextjs-icon',
|
||||
hasLightIcon: false,
|
||||
description:
|
||||
'Clone, deploy, and fully customize a SaaS subscription application with Next.js.',
|
||||
},
|
||||
{
|
||||
title: 'Partner Gallery',
|
||||
href: 'https://github.com/supabase-community/partner-gallery-example#supabase-partner-gallery-example',
|
||||
icon: '/docs/img/icons/nextjs-icon',
|
||||
hasLightIcon: false,
|
||||
description: 'Postgres full-text search, image storage, and more.',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export const gettingStartedFrameworkQuickstarts: ContentListingGroup = {
|
||||
id: 'getting-started-framework-quickstarts',
|
||||
heading: 'Framework quickstarts',
|
||||
headingLevel: 'h3',
|
||||
type: 'grid',
|
||||
items: [
|
||||
{
|
||||
title: 'React',
|
||||
href: '/guides/getting-started/quickstarts/reactjs',
|
||||
icon: '/docs/img/icons/react-icon',
|
||||
hasLightIcon: false,
|
||||
description:
|
||||
'Learn how to create a Supabase project, add some sample data to your database, and query the data from a React app.',
|
||||
},
|
||||
{
|
||||
title: 'Next.js',
|
||||
href: '/guides/getting-started/quickstarts/nextjs',
|
||||
icon: '/docs/img/icons/nextjs-icon',
|
||||
hasLightIcon: true,
|
||||
description:
|
||||
'Learn how to create a Supabase project, add some sample data to your database, and query the data from a Next.js app.',
|
||||
},
|
||||
{
|
||||
title: 'Nuxt',
|
||||
href: '/guides/getting-started/quickstarts/nuxtjs',
|
||||
icon: '/docs/img/icons/nuxt-icon',
|
||||
hasLightIcon: false,
|
||||
description:
|
||||
'Learn how to create a Supabase project, add some sample data to your database, and query the data from a Nuxt app.',
|
||||
},
|
||||
{
|
||||
title: 'Hono',
|
||||
href: '/guides/getting-started/quickstarts/hono',
|
||||
icon: '/docs/img/icons/hono-icon',
|
||||
hasLightIcon: false,
|
||||
description:
|
||||
'Learn how to create a Supabase project, add some sample data to your database, secure it with auth, and query the data from a Hono app.',
|
||||
},
|
||||
{
|
||||
title: 'RedwoodJS',
|
||||
href: '/guides/getting-started/quickstarts/redwoodjs',
|
||||
icon: '/docs/img/icons/redwood-icon',
|
||||
hasLightIcon: false,
|
||||
description:
|
||||
'Learn how to create a Supabase project, add some sample data to your database using Prisma migration and seeds, and query the data from a RedwoodJS app.',
|
||||
},
|
||||
{
|
||||
title: 'Flutter',
|
||||
href: '/guides/getting-started/quickstarts/flutter',
|
||||
icon: '/docs/img/icons/flutter-icon',
|
||||
hasLightIcon: false,
|
||||
feature: 'sdk:dart',
|
||||
description:
|
||||
'Learn how to create a Supabase project, add some sample data to your database, and query the data from a Flutter app.',
|
||||
},
|
||||
{
|
||||
title: 'iOS SwiftUI',
|
||||
href: '/guides/getting-started/quickstarts/ios-swiftui',
|
||||
icon: '/docs/img/icons/swift-icon',
|
||||
hasLightIcon: false,
|
||||
feature: 'sdk:swift',
|
||||
description:
|
||||
'Learn how to create a Supabase project, add some sample data to your database, and query the data from an iOS app.',
|
||||
},
|
||||
{
|
||||
title: 'Android Kotlin',
|
||||
href: '/guides/getting-started/quickstarts/kotlin',
|
||||
icon: '/docs/img/icons/kotlin-icon',
|
||||
hasLightIcon: false,
|
||||
feature: 'sdk:kotlin',
|
||||
description:
|
||||
'Learn how to create a Supabase project, add some sample data to your database, and query the data from an Android Kotlin app.',
|
||||
},
|
||||
{
|
||||
title: 'SvelteKit',
|
||||
href: '/guides/getting-started/quickstarts/sveltekit',
|
||||
icon: '/docs/img/icons/svelte-icon',
|
||||
hasLightIcon: false,
|
||||
description:
|
||||
'Learn how to create a Supabase project, add some sample data to your database, and query the data from a SvelteKit app.',
|
||||
},
|
||||
{
|
||||
title: 'SolidJS',
|
||||
href: '/guides/getting-started/quickstarts/solidjs',
|
||||
icon: '/docs/img/icons/solidjs-icon',
|
||||
hasLightIcon: false,
|
||||
description:
|
||||
'Learn how to create a Supabase project, add some sample data to your database, and query the data from a SolidJS app.',
|
||||
},
|
||||
{
|
||||
title: 'Vue',
|
||||
href: '/guides/getting-started/quickstarts/vue',
|
||||
icon: '/docs/img/icons/vuejs-icon',
|
||||
hasLightIcon: false,
|
||||
description:
|
||||
'Learn how to create a Supabase project, add some sample data to your database, and query the data from a Vue app.',
|
||||
},
|
||||
{
|
||||
title: 'TanStack Start',
|
||||
href: '/guides/getting-started/quickstarts/tanstack',
|
||||
icon: '/docs/img/icons/tanstack-icon',
|
||||
hasLightIcon: true,
|
||||
description:
|
||||
'Learn how to create a Supabase project, add some sample data to your database, and query the data from a TanStack Start app.',
|
||||
},
|
||||
{
|
||||
title: 'Refine',
|
||||
href: '/guides/getting-started/quickstarts/refine',
|
||||
icon: '/docs/img/icons/refine-icon',
|
||||
hasLightIcon: false,
|
||||
description:
|
||||
'Learn how to create a Supabase project, add some sample data to your database, and query the data from a Refine app.',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export const gettingStartedWebAppDemos: ContentListingGroup = {
|
||||
id: 'getting-started-web-app-demos',
|
||||
heading: 'Web app demos',
|
||||
headingLevel: 'h3',
|
||||
type: 'grid',
|
||||
items: [
|
||||
{
|
||||
title: 'Next.js',
|
||||
href: '/guides/getting-started/tutorials/with-nextjs',
|
||||
icon: '/docs/img/icons/nextjs-icon',
|
||||
hasLightIcon: true,
|
||||
description:
|
||||
'Learn how to build a user management app with Next.js and Supabase Database, Auth, and Storage functionality.',
|
||||
},
|
||||
{
|
||||
title: 'React',
|
||||
href: '/guides/getting-started/tutorials/with-react',
|
||||
icon: '/docs/img/icons/react-icon',
|
||||
hasLightIcon: false,
|
||||
description:
|
||||
'Learn how to build a user management app with React and Supabase Database, Auth, and Storage functionality.',
|
||||
},
|
||||
{
|
||||
title: 'Vue 3',
|
||||
href: '/guides/getting-started/tutorials/with-vue-3',
|
||||
icon: '/docs/img/icons/vuejs-icon',
|
||||
hasLightIcon: false,
|
||||
description:
|
||||
'Learn how to build a user management app with Vue 3 and Supabase Database, Auth, and Storage functionality.',
|
||||
},
|
||||
{
|
||||
title: 'Nuxt 3',
|
||||
href: '/guides/getting-started/tutorials/with-nuxt-3',
|
||||
icon: '/docs/img/icons/nuxt-icon',
|
||||
hasLightIcon: false,
|
||||
description:
|
||||
'Learn how to build a user management app with Nuxt 3 and Supabase Database, Auth, and Storage functionality.',
|
||||
},
|
||||
{
|
||||
title: 'Angular',
|
||||
href: '/guides/getting-started/tutorials/with-angular',
|
||||
icon: '/docs/img/icons/angular-icon',
|
||||
hasLightIcon: false,
|
||||
description:
|
||||
'Learn how to build a user management app with Angular and Supabase Database, Auth, and Storage functionality.',
|
||||
},
|
||||
{
|
||||
title: 'RedwoodJS',
|
||||
href: '/guides/getting-started/tutorials/with-redwoodjs',
|
||||
icon: '/docs/img/icons/redwood-icon',
|
||||
hasLightIcon: false,
|
||||
description:
|
||||
'Learn how to build a user management app with RedwoodJS and Supabase Database, Auth, and Storage functionality.',
|
||||
},
|
||||
{
|
||||
title: 'Svelte',
|
||||
href: '/guides/getting-started/tutorials/with-svelte',
|
||||
icon: '/docs/img/icons/svelte-icon',
|
||||
hasLightIcon: false,
|
||||
description:
|
||||
'Learn how to build a user management app with Svelte and Supabase Database, Auth, and Storage functionality.',
|
||||
},
|
||||
{
|
||||
title: 'SvelteKit',
|
||||
href: '/guides/getting-started/tutorials/with-sveltekit',
|
||||
icon: '/docs/img/icons/svelte-icon',
|
||||
hasLightIcon: false,
|
||||
description:
|
||||
'Learn how to build a user management app with SvelteKit and Supabase Database, Auth, and Storage functionality.',
|
||||
},
|
||||
{
|
||||
title: 'Refine',
|
||||
href: '/guides/getting-started/tutorials/with-refine',
|
||||
icon: '/docs/img/icons/refine-icon',
|
||||
hasLightIcon: false,
|
||||
description:
|
||||
'Learn how to build a user management app with Refine and Supabase Database, Auth, and Storage functionality.',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export const gettingStartedMobileTutorials: ContentListingGroup = {
|
||||
id: 'getting-started-mobile-tutorials',
|
||||
heading: 'Mobile tutorials',
|
||||
headingLevel: 'h3',
|
||||
type: 'grid',
|
||||
items: [
|
||||
{
|
||||
title: 'Flutter',
|
||||
href: '/guides/getting-started/tutorials/with-flutter',
|
||||
icon: '/docs/img/icons/flutter-icon',
|
||||
hasLightIcon: false,
|
||||
feature: 'sdk:dart',
|
||||
description:
|
||||
'Learn how to build a user management app with Flutter and Supabase Database, Auth, and Storage functionality.',
|
||||
},
|
||||
{
|
||||
title: 'Expo React Native',
|
||||
href: '/guides/getting-started/tutorials/with-expo-react-native',
|
||||
icon: '/docs/img/icons/expo-icon',
|
||||
hasLightIcon: true,
|
||||
description:
|
||||
'Learn how to build a user management app with Expo React Native and Supabase Database, Auth, and Storage functionality.',
|
||||
},
|
||||
{
|
||||
title: 'Expo React Native Social Auth',
|
||||
href: '/guides/auth/quickstarts/with-expo-react-native-social-auth',
|
||||
icon: '/docs/img/icons/expo-icon',
|
||||
hasLightIcon: true,
|
||||
description:
|
||||
'Learn how to implement social authentication in an app with Expo React Native and Supabase Database and Auth functionality.',
|
||||
},
|
||||
{
|
||||
title: 'Android Kotlin',
|
||||
href: '/guides/getting-started/tutorials/with-kotlin',
|
||||
icon: '/docs/img/icons/kotlin-icon',
|
||||
hasLightIcon: false,
|
||||
feature: 'sdk:kotlin',
|
||||
description:
|
||||
'Learn how to build a product management app with Android and Supabase Database, Auth, and Storage functionality.',
|
||||
},
|
||||
{
|
||||
title: 'iOS Swift',
|
||||
href: '/guides/getting-started/tutorials/with-swift',
|
||||
icon: '/docs/img/icons/swift-icon',
|
||||
hasLightIcon: false,
|
||||
feature: 'sdk:swift',
|
||||
description:
|
||||
'Learn how to build a user management app with iOS and Supabase Database, Auth, and Storage functionality.',
|
||||
},
|
||||
{
|
||||
title: 'Ionic React',
|
||||
href: '/guides/getting-started/tutorials/with-ionic-react',
|
||||
icon: '/docs/img/icons/ionic-icon',
|
||||
hasLightIcon: false,
|
||||
description:
|
||||
'Learn how to build a user management app with Ionic React and Supabase Database, Auth, and Storage functionality.',
|
||||
},
|
||||
{
|
||||
title: 'Ionic Vue',
|
||||
href: '/guides/getting-started/tutorials/with-ionic-vue',
|
||||
icon: '/docs/img/icons/ionic-icon',
|
||||
hasLightIcon: false,
|
||||
description:
|
||||
'Learn how to build a user management app with Ionic Vue and Supabase Database, Auth, and Storage functionality.',
|
||||
},
|
||||
{
|
||||
title: 'Ionic Angular',
|
||||
href: '/guides/getting-started/tutorials/with-ionic-angular',
|
||||
icon: '/docs/img/icons/ionic-icon',
|
||||
hasLightIcon: false,
|
||||
description:
|
||||
'Learn how to build a user management app with Ionic Angular and Supabase Database, Auth, and Storage functionality.',
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -11,8 +11,16 @@ import {
|
||||
functionsExamplesWebhooksPayments,
|
||||
functionsGetStarted,
|
||||
} from './functions.data'
|
||||
import {
|
||||
gettingStartedFrameworkQuickstarts,
|
||||
gettingStartedMobileTutorials,
|
||||
gettingStartedOverview,
|
||||
gettingStartedUseCases,
|
||||
gettingStartedWebAppDemos,
|
||||
} from './getting-started.data'
|
||||
import { logDrainsDestinations } from './log-drains.data'
|
||||
import { realtimeExamples, realtimeGetStarted, realtimeResources } from './realtime.data'
|
||||
import { resourcesMigrate, resourcesOverview, resourcesPostgres } from './resources.data'
|
||||
import {
|
||||
selfHostingCommunity,
|
||||
selfHostingGetHelp,
|
||||
@@ -37,10 +45,18 @@ const ALL_GROUPS: readonly ContentListingGroup[] = [
|
||||
functionsExamplesAiMedia,
|
||||
functionsExamplesMessaging,
|
||||
functionsExamplesOperations,
|
||||
gettingStartedOverview,
|
||||
gettingStartedUseCases,
|
||||
gettingStartedFrameworkQuickstarts,
|
||||
gettingStartedWebAppDemos,
|
||||
gettingStartedMobileTutorials,
|
||||
logDrainsDestinations,
|
||||
realtimeGetStarted,
|
||||
realtimeExamples,
|
||||
realtimeResources,
|
||||
resourcesOverview,
|
||||
resourcesMigrate,
|
||||
resourcesPostgres,
|
||||
selfHostingGetStarted,
|
||||
selfHostingCommunity,
|
||||
selfHostingResolveIssues,
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
import type { ContentListingGroup } from '~/lib/content-listings.schema'
|
||||
|
||||
export const resourcesOverview: ContentListingGroup = {
|
||||
id: 'resources-overview',
|
||||
type: 'grid',
|
||||
items: [
|
||||
{
|
||||
title: 'Examples',
|
||||
href: '/guides/getting-started',
|
||||
description: 'Official GitHub examples, curated content from the community, and more.',
|
||||
},
|
||||
{
|
||||
title: 'Glossary',
|
||||
href: '/guides/resources/glossary',
|
||||
description: 'Definitions for terminology and acronyms used in the Supabase documentation.',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export const resourcesMigrate: ContentListingGroup = {
|
||||
id: 'resources-migrate',
|
||||
heading: 'Migrate to Supabase',
|
||||
headingLevel: 'h3',
|
||||
type: 'grid',
|
||||
items: [
|
||||
{
|
||||
title: 'Auth0',
|
||||
href: '/guides/platform/migrating-to-supabase/auth0',
|
||||
icon: '/docs/img/icons/auth0-icon',
|
||||
hasLightIcon: true,
|
||||
description: 'Move your auth users from Auth0 to a Supabase project.',
|
||||
},
|
||||
{
|
||||
title: 'Firebase Auth',
|
||||
href: '/guides/platform/migrating-to-supabase/firebase-auth',
|
||||
icon: '/docs/img/icons/firebase-icon',
|
||||
hasLightIcon: false,
|
||||
description: 'Move your auth users from a Firebase project to a Supabase project.',
|
||||
},
|
||||
{
|
||||
title: 'Firestore Data',
|
||||
href: '/guides/platform/migrating-to-supabase/firestore-data',
|
||||
icon: '/docs/img/icons/firebase-icon',
|
||||
hasLightIcon: false,
|
||||
description: 'Migrate the contents of a Firestore collection to a single Postgres table.',
|
||||
},
|
||||
{
|
||||
title: 'Firebase Storage',
|
||||
href: '/guides/platform/migrating-to-supabase/firebase-storage',
|
||||
icon: '/docs/img/icons/firebase-icon',
|
||||
hasLightIcon: false,
|
||||
description: 'Convert your Firebase Storage files to Supabase Storage.',
|
||||
},
|
||||
{
|
||||
title: 'Heroku',
|
||||
href: '/guides/platform/migrating-to-supabase/heroku',
|
||||
icon: '/docs/img/icons/heroku-icon',
|
||||
hasLightIcon: false,
|
||||
description: 'Migrate your Heroku Postgres database to Supabase.',
|
||||
},
|
||||
{
|
||||
title: 'Render',
|
||||
href: '/guides/platform/migrating-to-supabase/render',
|
||||
icon: '/docs/img/icons/render-icon',
|
||||
hasLightIcon: false,
|
||||
description: 'Migrate your Render Postgres database to Supabase.',
|
||||
},
|
||||
{
|
||||
title: 'Amazon RDS',
|
||||
href: '/guides/platform/migrating-to-supabase/amazon-rds',
|
||||
icon: '/docs/img/icons/aws-rds-icon',
|
||||
hasLightIcon: false,
|
||||
description: 'Migrate your Amazon RDS database to Supabase.',
|
||||
},
|
||||
{
|
||||
title: 'Postgres',
|
||||
href: '/guides/platform/migrating-to-supabase/postgres',
|
||||
icon: '/docs/img/icons/postgres-icon',
|
||||
hasLightIcon: false,
|
||||
description: 'Migrate your Postgres database to Supabase.',
|
||||
},
|
||||
{
|
||||
title: 'MySQL',
|
||||
href: '/guides/platform/migrating-to-supabase/mysql',
|
||||
icon: '/docs/img/icons/mysql-icon',
|
||||
hasLightIcon: false,
|
||||
description: 'Migrate your MySQL database to Supabase.',
|
||||
},
|
||||
{
|
||||
title: 'Microsoft SQL Server',
|
||||
href: '/guides/platform/migrating-to-supabase/mssql',
|
||||
icon: '/docs/img/icons/mssql-icon',
|
||||
hasLightIcon: false,
|
||||
description: 'Migrate your Microsoft SQL Server database to Supabase.',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export const resourcesPostgres: ContentListingGroup = {
|
||||
id: 'resources-postgres',
|
||||
heading: 'Postgres resources',
|
||||
headingLevel: 'h3',
|
||||
type: 'grid',
|
||||
items: [
|
||||
{
|
||||
title: 'Managing Indexes',
|
||||
href: '/guides/database/postgres/indexes',
|
||||
description: 'Improve query performance using various index types in Postgres.',
|
||||
},
|
||||
{
|
||||
title: 'Cascade Deletes',
|
||||
href: '/guides/database/postgres/cascade-deletes',
|
||||
description: 'Understand the types of foreign key constraint deletes.',
|
||||
},
|
||||
{
|
||||
title: 'Drop all tables in schema',
|
||||
href: '/guides/database/postgres/dropping-all-tables-in-schema',
|
||||
description: 'Delete all tables in a given schema.',
|
||||
},
|
||||
{
|
||||
title: 'Select first row per group',
|
||||
href: '/guides/database/postgres/first-row-in-group',
|
||||
description: 'Retrieve the first row in each distinct group.',
|
||||
},
|
||||
{
|
||||
title: 'Print Postgres version',
|
||||
href: '/guides/database/postgres/which-version-of-postgres',
|
||||
description: 'Find out which version of Postgres you are running.',
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
import { withDocsBasePath } from '~/internals/internal-links'
|
||||
import type { ContentListingGroup } from '~/lib/content-listings.schema'
|
||||
import { getContentListingById, isExternalContentListingHref } from '~/lib/content-listings.utils'
|
||||
import {
|
||||
filterContentListingItems,
|
||||
getContentListingById,
|
||||
isExternalContentListingHref,
|
||||
} from '~/lib/content-listings.utils'
|
||||
|
||||
import { getInternalLinkBaseUrl } from '../internal-links'
|
||||
|
||||
@@ -14,6 +18,9 @@ export function serializeContentListingGroupToMarkdown(
|
||||
group: ContentListingGroup,
|
||||
linkBaseUrl: string
|
||||
): string {
|
||||
const items = filterContentListingItems(group.items)
|
||||
if (!items.length) return ''
|
||||
|
||||
const lines: string[] = []
|
||||
if (group.heading) {
|
||||
const level = group.headingLevel ?? 'h2'
|
||||
@@ -26,7 +33,7 @@ export function serializeContentListingGroupToMarkdown(
|
||||
lines.push('')
|
||||
}
|
||||
|
||||
for (const item of group.items) {
|
||||
for (const item of items) {
|
||||
const href = isExternalContentListingHref(item.href)
|
||||
? item.href
|
||||
: `${linkBaseUrl}${withDocsBasePath(item.href)}`
|
||||
|
||||
@@ -144,6 +144,74 @@ describe('serializeContentListingGroupToMarkdown', () => {
|
||||
expect(markdown).not.toMatch(/^#+\s/m)
|
||||
expect(markdown).toContain('**[Connect]')
|
||||
})
|
||||
|
||||
it('omits feature-gated items when those features are disabled', () => {
|
||||
const previous = process.env.ENABLED_FEATURES_OVERRIDE_DISABLE_ALL
|
||||
process.env.ENABLED_FEATURES_OVERRIDE_DISABLE_ALL = 'true'
|
||||
|
||||
try {
|
||||
const markdown = serializeContentListingGroupToMarkdown(
|
||||
{
|
||||
id: 'frameworks',
|
||||
heading: 'Frameworks',
|
||||
items: [
|
||||
{
|
||||
title: 'React',
|
||||
href: '/guides/getting-started/quickstarts/reactjs',
|
||||
description: 'Web framework.',
|
||||
},
|
||||
{
|
||||
title: 'Flutter',
|
||||
href: '/guides/getting-started/quickstarts/flutter',
|
||||
description: 'Mobile framework.',
|
||||
feature: 'sdk:dart',
|
||||
},
|
||||
],
|
||||
},
|
||||
''
|
||||
)
|
||||
|
||||
expect(markdown).toContain('**[React]')
|
||||
expect(markdown).not.toContain('Flutter')
|
||||
} finally {
|
||||
if (previous === undefined) {
|
||||
delete process.env.ENABLED_FEATURES_OVERRIDE_DISABLE_ALL
|
||||
} else {
|
||||
process.env.ENABLED_FEATURES_OVERRIDE_DISABLE_ALL = previous
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
it('returns empty string when every item is feature-gated off', () => {
|
||||
const previous = process.env.ENABLED_FEATURES_OVERRIDE_DISABLE_ALL
|
||||
process.env.ENABLED_FEATURES_OVERRIDE_DISABLE_ALL = 'true'
|
||||
|
||||
try {
|
||||
const markdown = serializeContentListingGroupToMarkdown(
|
||||
{
|
||||
id: 'sdk-only',
|
||||
heading: 'SDKs',
|
||||
items: [
|
||||
{
|
||||
title: 'Flutter',
|
||||
href: '/guides/getting-started/quickstarts/flutter',
|
||||
description: 'Mobile framework.',
|
||||
feature: 'sdk:dart',
|
||||
},
|
||||
],
|
||||
},
|
||||
''
|
||||
)
|
||||
|
||||
expect(markdown).toBe('')
|
||||
} finally {
|
||||
if (previous === undefined) {
|
||||
delete process.env.ENABLED_FEATURES_OVERRIDE_DISABLE_ALL
|
||||
} else {
|
||||
process.env.ENABLED_FEATURES_OVERRIDE_DISABLE_ALL = previous
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('ContentListings markdown handler', () => {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { CONTENT_LISTINGS } from '~/data/content-listings'
|
||||
import { isFeatureEnabled, type Feature } from 'common/enabled-features'
|
||||
|
||||
import type { ContentListingGroup } from './content-listings.schema'
|
||||
import type { ContentListingGroup, ContentListingItem } from './content-listings.schema'
|
||||
|
||||
/** Label for telemetry — prefers heading, falls back to id. */
|
||||
export function getContentListingGroupLabel(group: ContentListingGroup): string {
|
||||
@@ -14,3 +15,8 @@ export function isExternalContentListingHref(href: string): boolean {
|
||||
export function getContentListingById(id: string): ContentListingGroup | undefined {
|
||||
return CONTENT_LISTINGS[id]
|
||||
}
|
||||
|
||||
/** Omits items whose `feature` flag is disabled. Shared by UI and markdown export. */
|
||||
export function filterContentListingItems(items: ContentListingItem[]): ContentListingItem[] {
|
||||
return items.filter((item) => !item.feature || isFeatureEnabled(item.feature as Feature))
|
||||
}
|
||||
@@ -29,6 +29,11 @@ export const contentListingItemSchema = z.object({
|
||||
badge: z.string().min(1).optional(),
|
||||
/** Grid cards only. Defaults to inline (next to the title), matching existing usage. */
|
||||
badgePosition: z.enum(['inline', 'below']).optional(),
|
||||
/**
|
||||
* When set, the item is omitted unless `isFeatureEnabled(feature)` is true.
|
||||
* Use for SDK- or product-gated links (e.g. `sdk:dart`) inside a shared listing.
|
||||
*/
|
||||
feature: z.string().min(1).optional(),
|
||||
})
|
||||
|
||||
export const contentListingGroupTypeSchema = z.enum(['list', 'grid'])
|
||||
|
||||
Reference in new issue
Block a user