Skip to main content

What is the Dashboard?

The Dashboard is the protected, logged-in area of your app where users see their data, settings, and manage their account. Think of it like the “inside” of your application after someone signs in. Visual structure:
  • Left side: Collapsible sidebar with navigation menus
  • Top bar: Notifications, theme toggle, and user profile menu
  • Main area: Your dashboard pages (overview, settings, data tables, charts)
When a signed-out user tries to visit /dashboard, they’re automatically redirected to /sign-in. When a signed-in user tries to visit /sign-in, they’re redirected back to /dashboard.

How the Dashboard Works

The dashboard uses a layout wrapper pattern. Here’s what happens:

1. Layout wraps everything

File: sabo/src/app/(dashboard)/dashboard/layout.tsx This file creates the “shell” that appears on every dashboard page:
export default function DashboardLayout({ children }: { children: ReactNode }) {
  return (
    <AuthProvider>              {/* 1. Provides user authentication context */}
      <SidebarProvider>         {/* 2. Controls sidebar open/close state */}
        <AppSidebar />          {/* 3. The left sidebar with navigation */}
        <SidebarInset>          {/* 4. Container for main content area */}
          <div className="flex flex-1 flex-col">
            {children}          {/* 5. Your actual page content goes here */}
          </div>
        </SidebarInset>
      </SidebarProvider>
    </AuthProvider>
  );
}
{children} is where Next.js inserts your actual page content (like page.tsx, settings/general/page.tsx, etc.)

2. Pages use the layout automatically

Every page under /dashboard/* automatically gets wrapped by this layout. Example: sabo/src/app/(dashboard)/dashboard/page.tsx (the main dashboard page at /dashboard)
export default function DashboardPage() {
  return (
    <>
      <DashboardHeader breadcrumb={...} actions={...} />  {/* Top bar */}
      <div className="flex flex-col gap-4 py-4">
        <SectionCards />           {/* Metric cards (Revenue, Users, etc.) */}
        <ChartAreaInteractive />   {/* Charts and graphs */}
        <DataTable data={data} />  {/* Data tables */}
      </div>
    </>
  );
}
When you visit /dashboard, you see:
  • Sidebar (from layout) on the left
  • DashboardHeader (top bar with breadcrumb, notifications, user menu)
  • Your page content (cards, charts, tables)

3. Settings pages work the same way

File: sabo/src/app/(dashboard)/dashboard/settings/general/page.tsx
export default function GeneralSettingsPage() {
  return (
    <>
      <DashboardHeader breadcrumb="Settings > General" />
      <div className="p-4">
        {/* Settings form */}
      </div>
    </>
  );
}
When you visit /dashboard/settings/general:
  • Same sidebar and layout (from layout.tsx)
  • Different page content (the settings form)
  • Sidebar automatically highlights “Settings > General” as active

Key Components Explained

AppSidebar (Left Navigation)

Location: sabo/src/components/dashboard/app-sidebar.tsx What it contains:
  • Team Switcher (top) - Switch between teams/workspaces
  • Main Navigation - Primary menu items with collapsible sub-items
  • Projects List - Quick access to projects
  • Secondary Links - Support, Feedback
  • User Menu (bottom) - Profile and sign out
How to customize: Edit the arrays in app-sidebar.tsx:
const navMain = [
  {
    title: "Settings",
    url: "/dashboard/settings",
    icon: Settings2,
    isActive: pathname.startsWith("/dashboard/settings"),
    items: [
      { title: "General", url: "/dashboard/settings/general" },
      { title: "Account", url: "/dashboard/settings/account" },
    ],
  },
];

Sidebar Documentation

Learn how to customize the sidebar navigation and structure.

DashboardHeader (Top Bar)

Location: Exported from layout.tsx What it contains:
  • SidebarTrigger - Button to toggle sidebar (especially on mobile)
  • Breadcrumb - Shows current location (e.g., “Overview” or “Settings > Account”)
  • NotificationsDropdown - Bell icon with notification count
  • ModeToggle - Light/dark theme switcher
  • HeaderUserMenu - Avatar dropdown with profile links and sign out
How to use in your pages:
import { DashboardHeader } from "./layout";

<DashboardHeader 
  breadcrumb={<Breadcrumb>...</Breadcrumb>}
  actions={<Button>Custom Action</Button>}  // Optional extra buttons
/>

Settings Pages

Location: sabo/src/app/(dashboard)/dashboard/settings/* Four built-in settings pages:
PageURLWhat it does
General/dashboard/settings/generalProfile info, display name, bio
Account/dashboard/settings/accountEmail, password, delete account
Billing/dashboard/settings/billingSubscription plan, payment history
Notifications/dashboard/settings/notificationsEmail/push notification toggles
These pages connect to Supabase tables:
  • UserProfile table - stores profile data
  • UserSubscription table - stores Stripe subscription info
  • PaymentHistory table - stores invoice records

Settings Documentation

Learn how settings pages connect to Supabase and how to customize them.

File Structure Map

sabo/src/app/(dashboard)/dashboard/
├── layout.tsx              ← Wrapper for all dashboard pages
├── page.tsx                ← Main dashboard page (/dashboard)
└── settings/
    ├── general/page.tsx    ← Profile settings
    ├── account/page.tsx    ← Email/password
    ├── billing/page.tsx    ← Subscription
    └── notifications/      ← Email toggles
        └── page.tsx

sabo/src/components/dashboard/
├── app-sidebar.tsx         ← Left navigation sidebar
├── nav-main.tsx            ← Main navigation items
├── nav-secondary.tsx       ← Secondary links (Support, etc.)
├── nav-user.tsx            ← User dropdown in sidebar footer
├── nav-projects.tsx        ← Projects list
├── team-switcher.tsx       ← Team/workspace switcher
├── header-user-menu.tsx    ← Top-right user avatar menu
├── notifications-dropdown.tsx  ← Bell icon notifications
├── section-cards.tsx       ← Metric cards (Revenue, Users)
├── data-table.tsx          ← Data tables with sorting/filtering
└── chart-area-interactive.tsx  ← Charts and graphs

How Pages Connect Together

Example: Clicking “Settings” in Sidebar

  1. User clicks “Settings” in the left sidebar
  2. Sidebar code (app-sidebar.tsx) has this item:
    { title: "Settings", url: "/dashboard/settings/general", icon: Settings2 }
    
  3. Next.js routes to /dashboard/settings/general
  4. Layout wrapper (layout.tsx) stays the same (sidebar still visible)
  5. New page content loads (settings/general/page.tsx)
  6. Sidebar highlights “Settings” as active (via isActive prop)

Example: User Profile Menu

  1. User clicks avatar in top-right corner
  2. HeaderUserMenu (header-user-menu.tsx) opens dropdown
  3. Dropdown shows:
    • Account → links to /dashboard/settings/account
    • Billing → links to /dashboard/settings/billing
    • Notifications → links to /dashboard/settings/notifications
    • Log out → calls supabase.auth.signOut() and redirects to /
The user menu items are just regular links. When clicked, they navigate to the settings pages using Next.js routing.

Protected Routes (How Sign-in/Sign-out Works)

The dashboard is protected by middleware that checks if you’re signed in. Location: sabo/src/lib/supabase/middleware.ts Key arrays:
const protectedRoutes = ['/dashboard'];  // Requires sign-in
const authRoutes = ['/sign-in', '/sign-up'];  // Redirects if already signed in
How it works:
1

User visits /dashboard

Middleware checks: Is user signed in?
  • Yes → Show dashboard
  • No → Redirect to /sign-in
2

User signs in successfully

Auth callback redirects to /dashboard
3

Signed-in user visits /sign-in

Middleware checks: User already signed in?
  • Yes → Redirect to /dashboard (they don’t need sign-in page)
  • No → Show sign-in page

Routing & Middleware

Full guide on how middleware protects routes and customizing auth guards.

How to Customize the Dashboard

1. Add a new page

Create a new file: sabo/src/app/(dashboard)/dashboard/analytics/page.tsx
import { DashboardHeader } from "../layout";

export default function AnalyticsPage() {
  return (
    <>
      <DashboardHeader breadcrumb="Analytics" />
      <div className="p-4">
        <h1>Analytics Dashboard</h1>
        {/* Your analytics content */}
      </div>
    </>
  );
}
URL: /dashboard/analytics

2. Add it to sidebar navigation

Edit app-sidebar.tsx:
const navMain = [
  {
    title: "Analytics",      // ← Add this item
    url: "/dashboard/analytics",
    icon: BarChart,
    isActive: pathname === "/dashboard/analytics",
  },
  // ... other items
];
Now “Analytics” appears in the left sidebar and links to your new page.

3. Change what’s on the main dashboard page

Edit sabo/src/app/(dashboard)/dashboard/page.tsx: Replace <SectionCards /> with your own components, or remove charts, or add new sections. This is your main dashboard page - customize it however you want.

Common Patterns

Settings are split into General (profile), Account (auth), Billing (payments), and Notifications (preferences). This is a common UX pattern that makes settings easy to find.
The Team Switcher at the top of the sidebar lets users switch context (e.g., between different workspaces or teams). When they switch, you’d typically update the data shown across all dashboard pages.
The main dashboard page shows metric cards at the top, charts in the middle, and data tables at the bottom. This follows the “overview → trends → details” pattern.

Troubleshooting

Problem: The middleware thinks you’re not signed in.Check:
  • Open sabo/src/lib/supabase/middleware.ts
  • Look at the protectedRoutes array
  • Make sure /dashboard is listed: const protectedRoutes = ['/dashboard']
  • Verify your session cookies are being sent (check browser DevTools → Application → Cookies)
Fix: If the route isn’t in protectedRoutes, add it.
Problem: The middleware isn’t redirecting authenticated users away from auth pages.Check:
  • Open sabo/src/lib/supabase/middleware.ts
  • Look at the authRoutes array
  • Make sure it includes: const authRoutes = ['/sign-in', '/sign-up']
Fix: If /sign-in isn’t in authRoutes, add it. The middleware will then redirect signed-in users to /dashboard when they try to access these pages.
Problem: The Supabase tables don’t exist or aren’t connected.Check:
  • Do you have a user_profiles table in Supabase?
  • Are the column names correct? (e.g., full_name, email_notifications)
  • Check the browser console for Supabase errors
Fix: Create the required tables in Supabase (see Settings Documentation for schema details).
Problem: Both the layout and page content have overflow: auto.Fix:
  • Remove fixed heights from the layout columns
  • Let the content flow naturally
  • Only add overflow-x-auto to specific components that need horizontal scroll (like wide tables)