Sabo uses Next.js 16 App Router with route groups for clean organization. This guide explains every major folder and file, helping you understand where to find and modify code.
High-Level Overview
Application Routes (src/app/)
Next.js App Router uses folders for routes. Sabo organizes routes with route groups (folders wrapped in parentheses) that don’t affect the URL structure:
Route Groups Explained
Route groups like
(auth) organize files without adding /auth to the URL. For example, (auth)/sign-in/page.tsx becomes /sign-in, not /auth/sign-in.Authentication Routes ((auth)/)
Purpose: User authentication flows (sign-up, sign-in, password reset)
actions.ts- Server actions called by auth forms (handles Supabase API calls)- Each
page.tsx- React Server Component rendering the auth UI /confirmpages - Post-submission confirmation screens
Dashboard Routes ((dashboard)/)
Purpose: Protected application area (requires authentication)
layout.tsx- Sidebar layout wrapping all dashboard pages (usesSidebarProviderfrom shadcn/ui)page.tsx- Dashboard homepage with sample cards, chart, and data tablesettings/*- User settings pages connected touser_profilesanduser_subscriptionstables
All routes under
(dashboard)/ are protected by middleware. Unauthenticated users are redirected to /sign-in.Marketing Routes ((marketing)/)
Purpose: Public marketing pages for your SaaS
page.tsx(root) - Homepage with hero, features, pricing, testimonials, FAQ, CTApricing/page.tsx- Full pricing page with plan comparisoncontact/page.tsx- Contact form (submits to/api/contact)
The marketing layout (
layout.tsx) includes the site header and footer, applied to all marketing pages.Legal Routes ((legal)/)
Purpose: Legal documents rendered from MDX
- Pages fetch content from
src/content/legal/*.mdx - MDX files use frontmatter for metadata (title, lastUpdated)
Blog Routes (blog/)
Purpose: MDX-based blog system
- Blog posts in
src/content/blog/*.mdx - Frontmatter: title, description, date, author, thumbnail, tags
- Dynamic route
[slug]matches MDX filename
Changelog Routes (changelog/)
Purpose: Version release notes
- Changelog entries in
src/content/changelog/*.mdx - Frontmatter: version, title, description, date
- Entries sorted by date (newest first)
API Routes (api/)
Purpose: Backend API endpoints
contact/route.ts- Contact form submission handlercheckout_sessions/route.ts- Creates Stripe Checkout sessioncustomer_portal/route.ts- Generates Stripe Customer Portal URLwebhooks/stripe/route.ts- Handles Stripe webhook events (subscription lifecycle, invoices)
API routes export HTTP method handlers:
export async function POST(request: Request) { ... }Auth Callback (auth/)
Purpose: Supabase authentication callback handler
- OAuth redirects (Google, GitHub, Apple)
- Email verification links
- Magic link authentication
- Password reset confirmations
Root Files
layout.tsx- Wraps all pages, includes<html>,<body>, and global providers (theme, auth, PostHog)globals.css- Tailwind directives, CSS variables for theming, custom utilitiessitemap.ts- Generates dynamic sitemap including blog/changelog posts
Components (src/components/)
React components organized by feature:
UI Components (ui/)
50+ Components from shadcn/ui and Magic UI:
- Base Components
- Form Components
- Overlays
- Data Display
- Magic UI (Animated)
- Button, Badge, Card, Separator, Skeleton
- Avatar, Tabs, Toggle, Progress, Spinner, KBD
Auth Components (auth/)
auth-context.tsx- ProvidesuseAuth()hook for accessing user stateoauth-buttons.tsx- Reusable OAuth buttons called from sign-in/sign-up pages
Dashboard Components (dashboard/)
app-sidebar.tsx- Composes allnav-*components into the full sidebardata-table.tsx- Includes sorting, filtering, column visibility, and drag-drop
Marketing Components (marketing/)
- Edit text and copy directly in each component
- Modify pricing plans in
src/lib/payments/plans.ts
These components are composed together in
(marketing)/page.tsx to create the homepage.Shared Components (shared/)
header.tsx- Desktop navigation with linksmobile-nav.tsx- Drawer navigation for mobile viewportsfooter.tsx- Includes links, social icons, and status badge
Libraries (src/lib/)
Utility functions, clients, and integrations:
Supabase Library (lib/supabase/)
client.ts - Browser Client
client.ts - Browser Client
Creates a Supabase client for use in Client Components:
server.ts - Server Clients
server.ts - Server Clients
Exports two functions:
createClient()- Cookie-based client for Server Components, Server ActionscreateServiceClient()- Service role client (admin access, bypasses RLS)
middleware.ts - Auth Middleware
middleware.ts - Auth Middleware
Exports
updateSession() which:- Refreshes the user’s Supabase session
- Redirects unauthenticated users from protected routes
- Redirects authenticated users away from auth pages
src/proxy.ts (top-level middleware).types.ts - Database Types
types.ts - Database Types
TypeScript interfaces mirroring database schema:
UserProfile- user_profiles tableUserSubscription- user_subscriptions tablePaymentHistory- payment_history table
Payments Library (lib/payments/)
stripe.ts - Stripe Client
stripe.ts - Stripe Client
Exports a configured Stripe instance:
plans.ts - Plan Configuration
plans.ts - Plan Configuration
Centralized plan definitions plus helper utilities:Used by pricing page, Stripe API routes, and webhook handlers.
index.ts - Module Exports
index.ts - Module Exports
Centralized exports so other modules can import
stripe, plans, and helper functions from "@/lib/payments".Content (src/content/)
MDX files for blog, changelog, and legal pages:
- Blog Post
- Changelog
- Legal
Hooks (src/hooks/)
Custom React hooks:
Database (supabase/)
Supabase database configuration:
user_profilestable (profile data, preferences)user_subscriptionstable (Stripe subscription sync)payment_historytable (payment records)stripe_productstable (product catalog)- RLS policies for all tables
profile-imagesstorage bucket
Run this migration in your Supabase Dashboard (SQL Editor) or via Supabase CLI (
supabase db push).Tests (tests/e2e/)
Playwright end-to-end tests:
Static Assets (public/)
Images, logos, and Open Graph images:
Files in
public/ are served at the root path. Reference as /logo.png in your code.Configuration Files
File Naming Conventions
Sabo follows Next.js and React best practices:| Type | Convention | Example |
|---|---|---|
| Routes | page.tsx | (dashboard)/dashboard/page.tsx |
| Layouts | layout.tsx | (marketing)/layout.tsx |
| API Routes | route.ts | api/contact/route.ts |
| Components | kebab-case.tsx | contact-form.tsx |
| Hooks | use-*.ts | use-mobile.ts |
| Utilities | kebab-case.ts | utils.ts |
| MDX Content | kebab-case.mdx | getting-started.mdx |
Key Architectural Decisions
Why route groups?
Why route groups?
Route groups (
(auth), (dashboard), etc.) organize code without affecting URLs. This keeps the file structure clean while maintaining short, user-friendly paths like /sign-in instead of /auth/sign-in.Why separate client and server Supabase clients?
Why separate client and server Supabase clients?
Next.js Server Components and Client Components require different Supabase clients:
- Server client (
server.ts) uses cookies for SSR - Browser client (
client.ts) works in Client Components
Why centralize plans in lib/payments/plans.ts?
Why centralize plans in lib/payments/plans.ts?
Defining plans in one place makes it easy to:
- Update pricing without touching multiple files
- Add/remove plans
- Sync plan data between UI, API, and webhooks
- Type-check plan references
Why use Server Actions for auth?
Why use Server Actions for auth?
Server Actions (
actions.ts) provide a secure way to call Supabase APIs from Client Components without exposing API logic to the browser. They’re called like regular functions but execute server-side.