Skip to main content

Introduction

The Auction Platform uses TanStack Router for type-safe, file-based routing. Routes are organized with layout routes that provide consistent UI patterns across the application.

Route Structure

Routes are defined in the src/routes/ directory using a file-based convention:
routes/
├── __root.tsx                    # Root layout
├── _with-navbar.tsx              # Layout with navbar
│   └── index.tsx                 # Home page (/)
├── _with-sidebar.tsx             # Layout with sidebar
│   └── dashboard.tsx             # Dashboard page (/dashboard)
└── _without-navbar.tsx           # Layout without navigation
    ├── login.tsx                 # Login page (/login)
    ├── signup.tsx                # Signup page (/signup)
    └── onboarding.tsx            # Onboarding page (/onboarding)

Root Route

The root route defines the base layout and 404 handling:
import { Outlet, createRootRoute } from '@tanstack/react-router'
import * as React from 'react'
import NotFound from '../shared/ui/not found/NotFound'

export const Route = createRootRoute({
  component: RootComponent,
  notFoundComponent() {
    return <NotFound />
  },
})

function RootComponent() {
  return (
    <React.Fragment>
      <Outlet />
    </React.Fragment>
  )
}
The <Outlet /> component renders the matched child route. The root route also defines a custom 404 page.

Layout Routes

With Navbar Layout

The _with-navbar layout adds a navigation bar to public pages:
import { createFileRoute, Outlet } from '@tanstack/react-router'
import NavBar from '../widgets/Navbar/Navbar'

export const Route = createFileRoute('/_with-navbar')({
  component: RouteComponent,
})

function RouteComponent() {
  return (
    <div>
      <NavBar />
      <Outlet />
    </div>
  )
}
Routes using this layout:
  • / - Home page

With Sidebar Layout

The _with-sidebar layout provides a dashboard-style interface:
import { createFileRoute, Outlet } from '@tanstack/react-router';
import Sidebar from '../widgets/Sidebar/Sidebar';

export const Route = createFileRoute('/_with-sidebar')({
  component: RouteComponent,
})

function RouteComponent() {
  return (
    <div
      style={{
        height: "100vh",
        display: "flex",
      }}
    >
      <Sidebar />

      <main
        style={{
          flex: 1,
          padding: "24px",
          overflow: "auto",
        }}
      >
        <Outlet />
      </main>
    </div>
  );
}
Routes using this layout:
  • /dashboard - Main dashboard

Without Navbar Layout

The _without-navbar layout is used for authentication pages:
import { createFileRoute, Outlet } from '@tanstack/react-router'

export const Route = createFileRoute('/_without-navbar')({
  component: RouteComponent,
})

function RouteComponent() {
  return <div><Outlet /></div>
}
Routes using this layout:
  • /login - Login page
  • /signup - Signup page
  • /onboarding - Onboarding page

Route Examples

Home Page

import Home from '@/pages/home/Home'
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/_with-navbar/')({
  component: Home,
})

Dashboard Page

import DashboardMainPannel from '@/features/dashboard/Components/DashboardMainPannel'
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/_with-sidebar/dashboard')({
  component: RouteComponent,
})

function RouteComponent() {
  return <div><DashboardMainPannel /></div>
}

Login Page with Guards

The login route includes authentication guards using beforeLoad:
import { useAuthStore } from '@app/store/auth/auth.store';
import AuthLayout from '@features/auth/components/AuthLayout';
import { createFileRoute, redirect } from '@tanstack/react-router';

export const Route = createFileRoute('/_without-navbar/login')({
  beforeLoad: async () => {
    const { isAuthenticated, isOnboarded } = useAuthStore.getState();

    // Allow access if not authenticated
    if (!isAuthenticated) {
      return;
    }
    
    // Redirect to onboarding if authenticated but not onboarded
    if (!isOnboarded) {
      throw redirect({ to: "/onboarding" });
    }
    
    // Redirect to dashboard if fully authenticated
    throw redirect({ to: "/dashboard" });
  },
  component: () => <AuthLayout type="login" />,
})
Route guards check authentication state before rendering the component, ensuring users are redirected appropriately.

Route Guards Pattern

TanStack Router’s beforeLoad hook enables route protection:
1

Check Authentication State

Access the Zustand auth store to check isAuthenticated and isOnboarded.
2

Apply Business Logic

Determine if the user should access the route or be redirected.
3

Redirect if Needed

Use throw redirect() to navigate to a different route.
4

Allow Access

Return nothing or undefined to allow the route to render.

Path Aliases

The application uses TypeScript path aliases for cleaner imports:
{
  "compilerOptions": {
    "paths": {
      "@/*": ["./src/*"],
      "@app/*": ["./src/app/*"],
      "@features/*": ["./src/features/*"],
      "@shared/*": ["./src/shared/*"],
      "@widgets/*": ["./src/widgets/*"]
    }
  }
}
Example usage:
import { useAuthStore } from '@app/store/auth/auth.store';
import AuthLayout from '@features/auth/components/AuthLayout';
import Home from '@/pages/home/Home';

Type Safety

TanStack Router generates type definitions automatically:
  • routeTree.gen.ts - Auto-generated route tree with full type safety
  • Type-safe route parameters and search params
  • Compile-time route validation
Don’t manually edit routeTree.gen.ts - it’s automatically generated by TanStack Router.

Programmatic Navigation

import { useNavigate } from '@tanstack/react-router';

function MyComponent() {
  const navigate = useNavigate();
  
  const goToDashboard = () => {
    navigate({ to: '/dashboard' });
  };
  
  return <button onClick={goToDashboard}>Go to Dashboard</button>;
}
import { Link } from '@tanstack/react-router';

function Navigation() {
  return (
    <nav>
      <Link to="/">Home</Link>
      <Link to="/dashboard">Dashboard</Link>
      <Link to="/login">Login</Link>
    </nav>
  );
}

Best Practices

Group routes with similar layouts using layout routes to reduce duplication.
Use beforeLoad to protect routes and handle authentication/authorization.
Take advantage of TanStack Router’s type-safe navigation and parameters.
Import using path aliases (@app, @features, etc.) for cleaner code.

Architecture Overview

Learn about the overall architecture

State Management

Understand Zustand stores used in route guards

TanStack Router Docs

Official TanStack Router documentation

Build docs developers (and LLMs) love