Files
supabase/apps/ui-library/components/side-navigation.tsx
Saxon FletcherandClaude Opus 5 b1d2efd99e feat(library): add starter app guides (#50368)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Feature, docs.

Part 2 of 6 in a stack that splits the library redesign into reviewable
pieces.

## What is the current behavior?

The library documents individual blocks. Nothing answers "I have no
project yet" — a reader who wants a working app has to assemble one from
block guides and figure out the scaffolding themselves.

## What is the new behavior?

Four starter guides under `/docs/starters`, each starting from an empty
directory and ending with a running app on Supabase:

- **Next.js starter** — composes the library's own password-based auth
block.
- **SaaS starter** — the community subscription-payments template, with
Stripe setup.
- **AI chat app** — the community Vercel AI SDK template.
- **Flutter starter** — the user-management example, with profiles and
avatar uploads.

They reuse the existing doc route, so the sidebar, command menu,
Markdown export and `llms.txt` pick them up with no new plumbing. The
framework selector already renders nothing for pages that declare no
framework variants, so a starter page shows none.

## Additional context

The starter pages are added here in the current site's page layout; the
last PR in the stack converts them to the new one along with every other
guide.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Added a Starter Apps section to the side navigation and command menu.
- Added links for Next.js, SaaS, AI Chat, and Flutter starter projects,
marked as new.

- **Documentation**
  - Added setup and deployment guides for the Next.js and SaaS starters.
- Added an AI Chat App guide covering configuration, local verification,
and deployment.
- Added a Flutter starter guide covering authentication, profiles,
avatars, deep links, and hosted setup.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 10:38:49 +10:00

135 lines
4.7 KiB
TypeScript

import Link from 'next/link'
import { CommandMenu } from './command-menu'
import { ThemeSwitcherDropdown } from './theme-switcher-dropdown'
import NavigationItem from '@/components/side-navigation-item'
import {
componentPages,
gettingStarted,
mcpBlocks,
oauthBlocks,
platformBlocks,
starterApps,
} from '@/config/docs'
function SideNavigation() {
return (
<nav className="flex flex-col h-full min-w-[220px]">
<div className="p-6">
<div className="flex items-start justify-between mb-4">
<Link href="/">
<svg
xmlns="http://www.w3.org/2000/svg"
width="109"
height="113"
viewBox="0 0 109 113"
fill="none"
className="w-6 h-6"
>
<path
d="M63.7076 110.284C60.8481 113.885 55.0502 111.912 54.9813 107.314L53.9738 40.0625L99.1935 40.0625C107.384 40.0625 111.952 49.5226 106.859 55.9372L63.7076 110.284Z"
fill="url(#paint0_linear)"
/>
<path
d="M63.7076 110.284C60.8481 113.885 55.0502 111.912 54.9813 107.314L53.9738 40.0625L99.1935 40.0625C107.384 40.0625 111.952 49.5226 106.859 55.9372L63.7076 110.284Z"
fill="url(#paint1_linear)"
fillOpacity="0.2"
/>
<path
d="M45.317 2.07103C48.1765 -1.53037 53.9745 0.442937 54.0434 5.041L54.4849 72.2922H9.83113C1.64038 72.2922 -2.92775 62.8321 2.1655 56.4175L45.317 2.07103Z"
fill="#3ECF8E"
/>
<defs>
<linearGradient
id="paint0_linear"
x1="53.9738"
y1="54.9738"
x2="94.1635"
y2="71.8293"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#249361" />
<stop offset="1" stopColor="#3ECF8E" />
</linearGradient>
<linearGradient
id="paint1_linear"
x1="36.1558"
y1="30.5779"
x2="54.4844"
y2="65.0804"
gradientUnits="userSpaceOnUse"
>
<stop />
<stop offset="1" stopOpacity="0" />
</linearGradient>
</defs>
</svg>
</Link>
<ThemeSwitcherDropdown />
</div>
<Link href="/" className="mb-4 block">
<h1>Supabase Library</h1>
</Link>
{/* <TopNavigationSearch /> */}
<CommandMenu />
</div>
<div className="pb-6 space-y-0.5">
<div className="font-mono uppercase text-xs text-foreground-lighter/75 mb-2 px-6 tracking-widest">
{gettingStarted.title}
</div>
{gettingStarted.items.map((item, i) => (
<NavigationItem item={item} key={`${item.href}-${i}`} />
))}
</div>
<div className="pb-6 space-y-0.5">
<div className="font-mono uppercase text-xs text-foreground-lighter/75 mb-2 px-6 tracking-widest">
{starterApps.title}
</div>
{starterApps.items.map((item, i) => (
<NavigationItem item={item} key={`${item.href}-${i}`} />
))}
</div>
<div className="pb-6">
<div className="font-mono uppercase text-xs text-foreground-lighter/75 mb-2 px-6 tracking-widest">
UI Blocks
</div>
<div className="space-y-0.5">
{/* Render items based on component definitions */}
{componentPages.items.map((component, i) => (
<NavigationItem
item={component}
key={`${component.href?.toString() || component.title}-${i}`}
/>
))}
</div>
</div>
<div className="pb-6">
<div className="font-mono uppercase text-xs text-foreground-lighter/75 mb-2 px-6 tracking-widest">
{oauthBlocks.title}
</div>
{oauthBlocks.items.map((item, i) => (
<NavigationItem item={item} key={`${item.href}-${i}`} />
))}
</div>
<div className="pb-6">
<div className="font-mono uppercase text-xs text-foreground-lighter/75 mb-2 px-6 tracking-widest">
{mcpBlocks.title}
</div>
{mcpBlocks.items.map((item, i) => (
<NavigationItem item={item} key={`${item.href}-${i}`} />
))}
</div>
<div className="pb-6">
<div className="font-mono uppercase text-xs text-foreground-lighter/75 mb-2 px-6 tracking-widest">
{platformBlocks.title}
</div>
{platformBlocks.items.map((item, i) => (
<NavigationItem item={item} key={`${item.href}-${i}`} />
))}
</div>
</nav>
)
}
export default SideNavigation