Personal Account Navigation in Next.js Supabase
Configure the personal account sidebar navigation, layout style, and menu structure in the Next.js Supabase SaaS Kit.
The personal account navigation at apps/web/config/personal-account-navigation.config.tsx defines the sidebar menu for personal workspaces. Add your own routes here to extend the dashboard navigation.
Where to Add Routes
This is the file you'll edit most often when building your product. Add dashboard pages, settings sections, and feature-specific navigation items here.
Layout Options
| Variable | Options | Default | Description |
|---|---|---|---|
NEXT_PUBLIC_USER_NAVIGATION_STYLE | sidebar, header | sidebar | Navigation layout style |
NEXT_PUBLIC_HOME_SIDEBAR_COLLAPSED | true, false | false | Start with collapsed sidebar |
NEXT_PUBLIC_SIDEBAR_COLLAPSIBLE_STYLE | offcanvas, icon, none | icon | How sidebar collapses |
Sidebar Style (Default)
NEXT_PUBLIC_USER_NAVIGATION_STYLE=sidebarShows a vertical sidebar on the left with expandable sections.
Header Style
NEXT_PUBLIC_USER_NAVIGATION_STYLE=headerShows navigation in a horizontal header bar.
Collapse Behavior
Control how the sidebar behaves when collapsed:
# Icon mode: Shows icons only when collapsedNEXT_PUBLIC_SIDEBAR_COLLAPSIBLE_STYLE=icon# Offcanvas mode: Slides in/out as an overlayNEXT_PUBLIC_SIDEBAR_COLLAPSIBLE_STYLE=offcanvas# None: Sidebar cannot be collapsedNEXT_PUBLIC_SIDEBAR_COLLAPSIBLE_STYLE=noneDefault Configuration
The kit ships with these routes:
import { CreditCard, Home, User } from 'lucide-react';import { z } from 'zod';import { NavigationConfigSchema } from '@kit/ui/navigation-schema';import featureFlagsConfig from '~/config/feature-flags.config';import pathsConfig from '~/config/paths.config';const iconClasses = 'w-4';const routes = [ { label: 'common:routes.application', children: [ { label: 'common:routes.home', path: pathsConfig.app.home, Icon: <Home className={iconClasses} />, end: true, }, ], }, { label: 'common:routes.settings', children: [ { label: 'common:routes.profile', path: pathsConfig.app.personalAccountSettings, Icon: <User className={iconClasses} />, }, featureFlagsConfig.enablePersonalAccountBilling ? { label: 'common:routes.billing', path: pathsConfig.app.personalAccountBilling, Icon: <CreditCard className={iconClasses} />, } : undefined, ].filter((route) => !!route), },] satisfies z.infer<typeof NavigationConfigSchema>['routes'];export const personalAccountNavigationConfig = NavigationConfigSchema.parse({ routes, style: process.env.NEXT_PUBLIC_USER_NAVIGATION_STYLE, sidebarCollapsed: process.env.NEXT_PUBLIC_HOME_SIDEBAR_COLLAPSED, sidebarCollapsedStyle: process.env.NEXT_PUBLIC_SIDEBAR_COLLAPSIBLE_STYLE,});Adding Custom Routes
Simple Route
Add a route to an existing section:
const routes = [ { label: 'common:routes.application', children: [ { label: 'common:routes.home', path: pathsConfig.app.home, Icon: <Home className={iconClasses} />, end: true, }, { label: 'Projects', path: '/home/projects', Icon: <Folder className={iconClasses} />, }, ], }, // ... rest of routes];New Section
Add a new collapsible section:
const routes = [ // ... existing sections { label: 'Your Store', children: [ { label: 'Products', path: '/home/products', Icon: <Package className={iconClasses} />, }, { label: 'Orders', path: '/home/orders', Icon: <ShoppingCart className={iconClasses} />, }, { label: 'Analytics', path: '/home/analytics', Icon: <BarChart className={iconClasses} />, }, ], },];Nested Routes
Create sub-menus within a section:
const routes = [ { label: 'Dashboard', children: [ { label: 'Overview', path: '/home', Icon: <LayoutDashboard className={iconClasses} />, end: true, }, { label: 'Projects', path: '/home/projects', Icon: <Folder className={iconClasses} />, children: [ { label: 'Active', path: '/home/projects/active', Icon: <Play className={iconClasses} />, }, { label: 'Archived', path: '/home/projects/archived', Icon: <Archive className={iconClasses} />, }, ], }, ], },];Conditional Routes
Show routes based on feature flags or user state:
const routes = [ { label: 'common:routes.settings', children: [ { label: 'common:routes.profile', path: pathsConfig.app.personalAccountSettings, Icon: <User className={iconClasses} />, }, // Only show billing if enabled featureFlagsConfig.enablePersonalAccountBilling ? { label: 'common:routes.billing', path: pathsConfig.app.personalAccountBilling, Icon: <CreditCard className={iconClasses} />, } : undefined, ].filter((route) => !!route), },];Route Properties
| Property | Type | Required | Description |
|---|---|---|---|
label | string | Yes | Display text (supports i18n keys) |
path | string | Yes | Route path |
Icon | ReactNode | No | Lucide icon component |
end | boolean | No | Exact path matching (for index routes) |
children | Route[] | No | Nested routes for sub-menus |
Internationalization
Route labels support i18n keys:
{ label: 'common:routes.dashboard', // Uses translation path: '/home', Icon: <Home className={iconClasses} />,}Translation files are in apps/web/public/locales/[locale]/common.json:
{ "routes": { "dashboard": "Dashboard", "settings": "Settings", "profile": "Profile" }}For quick prototyping, use plain strings:
{ label: 'My Projects', // Plain string path: '/home/projects', Icon: <Folder className={iconClasses} />,}Best Practices
- Use
pathsConfig: Import paths from the configuration instead of hardcoding strings. - Group logically: Put related routes in the same section.
- Use feature flags: Conditionally show routes based on billing plans or user permissions.
- Consistent icons: Use icons from
lucide-reactfor visual consistency.
Common Pitfalls
- Missing
endproperty: The home route needsend: trueto prevent it from matching all paths starting with/home. - Forgetting to filter undefined: When using conditional routes, always filter out
undefinedvalues with.filter((route) => !!route). - Wrong icon size: Use
w-4class for icons to match the navigation style.
Related Topics
- Team Account Navigation - Configure team navigation
- Paths Configuration - Centralized path management
- Adding Pages - Create new dashboard pages