Documentation
Documentation
Introduction

Getting Started

Getting StartedInstallationQuick StartProject Structure

Architecture

Architecture OverviewTech StacktRPC MiddlewareDesign Principles

Patterns

Code Patterns & ConventionsFeature ModulesError HandlingType Safety

Database

DatabaseSchema DefinitionDatabase OperationsMigrationsCaching

API

tRPCProceduresRouterstRPC Proxy Setup
APIsOpenAPIREST Endpoints

Auth & Access

AuthenticationConfigurationOAuth ProvidersRolesSession Management
AuthorizationUser RolesPermissions

Routing & i18n

RoutingDeclarative RoutingNavigation
InternationalizationTranslationsLocale Routing

Components & UI

ComponentsButtonsFormsNavigationDialogs
StylesTailwind CSSThemingTypography

Storage

StorageConfigurationUsageBuckets

Configuration

ConfigurationEnvironment VariablesFeature Flags

Templates

Template GuidesCreate New FeatureCreate New PageCreate Database TableCreate tRPC RouterAdd Translations

Development

DevelopmentCommandsAI AgentsBest Practices

Routing

Type-safe routing with declarative routes

Overview

This project uses Declarative Routing for type-safe navigation. Routes are automatically generated from page.info.ts files, providing full TypeScript support for navigation.

Routing Structure

Routes are defined in src/routes/ and auto-generated from page.info.ts files:

src/routes/
├── index.ts          # Auto-generated route exports (DO NOT EDIT)
├── makeRoute.tsx     # Route builder utilities
├── routing.ts        # Navigation menus & authorization config
├── hooks.ts          # Route-related hooks
└── utils.ts          # Route utilities

Basic Usage

As a Link

import { PageHome, PageDashboard } from "@/routes";

<PageHome.Link>Go to Home</PageHome.Link>
<PageDashboard.Link>Go to Dashboard</PageDashboard.Link>

Get URL String

const url = PageHome();
const dashboardUrl = PageDashboard();

With Parameters

import { PageUserId } from "@/routes";

// Link with params
<PageUserId.Link id={user.id}>View Profile</PageUserId.Link>

// Or using ParamsLink
<PageUserId.ParamsLink params={{ id: user.id }}>
  View Profile
</PageUserId.ParamsLink>

// Get URL string
const url = PageUserId({ id: user.id });

With Search Params

import { PageSearch } from "@/routes";

<PageSearch.Link search={{ q: "hello", page: 1 }}>
  Search Results
</PageSearch.Link>

const url = PageSearch({}, { q: "hello", page: 1 });

Creating a Page

For complete step-by-step instructions, see the New Page Template.

Quick Example

Create page.info.ts alongside your page.tsx:

// src/app/[locale]/(site)/about/page.info.ts
import { z } from "zod";

export const Route = {
  name: "PageAbout" as const,
  params: z.object({}),
};

The route is automatically available:

import { PageAbout } from "@/routes";

<PageAbout.Link>About Us</PageAbout.Link>

Protected Routes

Routes requiring authentication are defined in src/routes/routing.ts:

PagesRequiringAuth: () => [
  PageSettingsProfile,
  PageDashboard,
  PageAdmin,
],

Routes blocked for authenticated users:

PagesBlockedForAuth: () => [
  PageLogin,
  PageRegister,
  PageForgotPassword,
],

Navigation Configuration

Configure navigation menus in src/routes/routing.ts:

Header Navigation

Header: (role?: UserRole | null) => [
  { route: PageHome },
  { route: PageAbout },
  { route: PagePricing, group: "product" },
],

Dashboard Sidebar

Dashboard: (pathname: string): SidebarMenuGroup[] => [
  {
    groupLabel: "",
    menus: [
      {
        ...routeMenu(PageDashboard, { activePathname: pathname }),
        submenus: [],
      },
    ],
  },
  {
    groupLabel: "content",
    menus: [
      {
        ...routeMenu(PageDashboardProjects, { activePathname: pathname }),
        submenus: [],
      },
    ],
  },
],

Route Icons

Icons are configured in src/routes/config/icons.ts:

import { PageHome, PageDashboard } from "@/routes";

export const Icons: () => Record<string, IconKey> = () => ({
  [PageHome.routeName]: "home",
  [PageDashboard.routeName]: "dashboard",
});

When creating a new page, add an entry to icons.ts to assign an icon.

Route Translations

Page names for navigation are defined in menu.json:

// src/messages/dictionaries/en/menu.json
{
  "links": {
    "PageHome": "Home",
    "PageDashboard": "Dashboard",
    "PageAbout": "About Us"
  }
}

The key must match the name from page.info.ts.

Best Practices

1. Use Typed Routes

// ✅ Good
<PageDashboard.Link>Dashboard</PageDashboard.Link>

// ❌ Bad
<Link href="/dashboard">Dashboard</Link>

2. Add Icons for New Routes

Update icons.ts when creating pages.

3. Update Navigation Configs

Add user-facing pages to navigation menus.

4. Use ParamsLink for Complex Params

<PageUserId.ParamsLink params={{ id: user.id }}>
  View
</PageUserId.ParamsLink>

Next Steps

Declarative Routing

Navigation

New Page Template

On this page

Overview
Routing Structure
Basic Usage
As a Link
Get URL String
With Parameters
With Search Params
Creating a Page
Quick Example
Protected Routes
Navigation Configuration
Header Navigation
Dashboard Sidebar
Route Icons
Route Translations
Best Practices
1. Use Typed Routes
2. Add Icons for New Routes
3. Update Navigation Configs
4. Use ParamsLink for Complex Params
Next Steps