Paths Configuration in the Next.js Supabase SaaS Kit
Configure route paths for authentication, personal accounts, and team accounts in the Next.js Supabase SaaS Kit. Centralized path management for consistent navigation.
The paths configuration at apps/web/config/paths.config.ts centralizes all route definitions. Instead of scattering magic strings throughout your codebase, reference paths from this single configuration file.
Why Centralize Paths
Centralizing paths prevents typos, makes refactoring easier, and ensures consistency across navigation, redirects, and links throughout your application.
Default Paths
Authentication Paths
| Path Key | Default Value | Description |
|---|---|---|
auth.signIn | /auth/sign-in | Sign in page |
auth.signUp | /auth/sign-up | Sign up page |
auth.verifyMfa | /auth/verify | MFA verification |
auth.callback | /auth/callback | OAuth callback handler |
auth.passwordReset | /auth/password-reset | Password reset request |
auth.passwordUpdate | /update-password | Password update completion |
Personal Account Paths
| Path Key | Default Value | Description |
|---|---|---|
app.home | /home | Personal dashboard |
app.personalAccountSettings | /home/settings | Profile settings |
app.personalAccountBilling | /home/billing | Billing management |
app.personalAccountBillingReturn | /home/billing/return | Billing portal return |
Team Account Paths
| Path Key | Default Value | Description |
|---|---|---|
app.accountHome | /home/[account] | Team dashboard |
app.accountSettings | /home/[account]/settings | Team settings |
app.accountBilling | /home/[account]/billing | Team billing |
app.accountMembers | /home/[account]/members | Team members |
app.accountBillingReturn | /home/[account]/billing/return | Team billing return |
app.joinTeam | /join | Team invitation acceptance |
Configuration File
import { z } from 'zod';const PathsSchema = z.object({ auth: z.object({ signIn: z.string().min(1), signUp: z.string().min(1), verifyMfa: z.string().min(1), callback: z.string().min(1), passwordReset: z.string().min(1), passwordUpdate: z.string().min(1), }), app: z.object({ home: z.string().min(1), personalAccountSettings: z.string().min(1), personalAccountBilling: z.string().min(1), personalAccountBillingReturn: z.string().min(1), accountHome: z.string().min(1), accountSettings: z.string().min(1), accountBilling: z.string().min(1), accountMembers: z.string().min(1), accountBillingReturn: z.string().min(1), joinTeam: z.string().min(1), }),});const pathsConfig = PathsSchema.parse({ auth: { signIn: '/auth/sign-in', signUp: '/auth/sign-up', verifyMfa: '/auth/verify', callback: '/auth/callback', passwordReset: '/auth/password-reset', passwordUpdate: '/update-password', }, app: { home: '/home', personalAccountSettings: '/home/settings', personalAccountBilling: '/home/billing', personalAccountBillingReturn: '/home/billing/return', accountHome: '/home/[account]', accountSettings: `/home/[account]/settings`, accountBilling: `/home/[account]/billing`, accountMembers: `/home/[account]/members`, accountBillingReturn: `/home/[account]/billing/return`, joinTeam: '/join', },});export default pathsConfig;Using Paths in Code
In Server Components and Actions
import pathsConfig from '~/config/paths.config';import { redirect } from 'next/navigation';// Redirect to sign inredirect(pathsConfig.auth.signIn);// Redirect to team dashboardconst teamSlug = 'acme-corp';redirect(pathsConfig.app.accountHome.replace('[account]', teamSlug));In Client Components
import pathsConfig from '~/config/paths.config';import Link from 'next/link';function Navigation() { return ( <nav> <Link href={pathsConfig.app.home}>Dashboard</Link> <Link href={pathsConfig.app.personalAccountSettings}>Settings</Link> </nav> );}Dynamic Team Paths
Team account paths contain [account] as a placeholder. Replace it with the actual team slug:
import pathsConfig from '~/config/paths.config';function getTeamPaths(teamSlug: string) { return { dashboard: pathsConfig.app.accountHome.replace('[account]', teamSlug), settings: pathsConfig.app.accountSettings.replace('[account]', teamSlug), billing: pathsConfig.app.accountBilling.replace('[account]', teamSlug), members: pathsConfig.app.accountMembers.replace('[account]', teamSlug), };}// Usageconst paths = getTeamPaths('acme-corp');// paths.dashboard = '/home/acme-corp'// paths.settings = '/home/acme-corp/settings'Adding Custom Paths
Extend the schema when adding new routes to your application:
const PathsSchema = z.object({ auth: z.object({ // ... existing auth paths }), app: z.object({ // ... existing app paths // Add your custom paths projects: z.string().min(1), projectDetail: z.string().min(1), }),});const pathsConfig = PathsSchema.parse({ auth: { // ... existing values }, app: { // ... existing values projects: '/home/[account]/projects', projectDetail: '/home/[account]/projects/[projectId]', },});Then use the new paths:
const projectsPath = pathsConfig.app.projects .replace('[account]', teamSlug);const projectDetailPath = pathsConfig.app.projectDetail .replace('[account]', teamSlug) .replace('[projectId]', projectId);Path Conventions
Follow these conventions when adding paths:
- Use lowercase with hyphens:
/home/my-projectsnot/home/myProjects - Use brackets for dynamic segments:
[account],[projectId] - Keep paths shallow: Avoid deeply nested routes when possible
- Group related paths: Put team-related paths under
app.account*
Common Pitfalls
- Forgetting to replace dynamic segments: Always replace
[account]with the actual slug before using team paths in redirects or links. - Hardcoding paths: Don't use string literals like
'/home/settings'. Always import frompathsConfigfor consistency. - Missing trailing slash consistency: The kit doesn't use trailing slashes. Keep this consistent in your custom paths.
Related Topics
- Navigation Configuration - Configure sidebar navigation
- App Router Structure - Understand the route organization