Create your own
Lesson illustration

Nested and Layout Routes

Hello! Welcome to the sixth lesson in our course on mastering TanStack Start and Router.

In the previous lesson, we explored typed navigation, covering how to use the <Link> component and the useNavigate hook to move between routes in a type-safe manner. You learned how to pass path and search parameters correctly, preventing a common source of bugs.

Lesson 6: Nested and Layout Routes

Today's Goal:

This lesson directly addresses the learning outcome: Implement nested routes and layout routes for shared UI. We will build on your knowledge of creating and navigating routes to organize them into hierarchical structures with persistent layouts, such as sidebars, headers, and footers. This is a foundational pattern for building any non-trivial web application.

As a lead developer, you're familiar with the need for reusable UI components. Layout routes extend this principle to the routing level, allowing you to define a shell that wraps around a group of related pages.

What we will cover:

  1. Nested Routes: How to create parent-child relationships between routes using file-system conventions.
  2. The <Outlet /> Component: The key mechanism for rendering child routes within a parent's UI.
  3. Layout Routes: Using routes to define shared UI that wraps multiple child routes.
  4. Pathless Layout Routes: A powerful technique for grouping routes under a shared layout without affecting the URL structure.

1. Nested Routes and the <Outlet />

Nested routes allow you to create UIs where sections of the screen correspond to different levels of the URL. For example, in a URL like /dashboard/settings, a persistent "dashboard" sidebar might be rendered by the /dashboard route, while the "settings" form is rendered by the /settings child route.

TanStack Router uses the file system to define this hierarchy. A route inside a folder becomes a child of the route defined by that folder.

The magic that connects the parent and child is the <Outlet /> component. A parent route component must render an <Outlet /> to specify where the child route's component should be displayed.

Let's watch a practical demonstration of creating a nested route.

Complete TanStack Router Tutorial - Build Type-Safe React Apps with File-Based Routing

This segment from the 'Complete TanStack Router Tutorial' by Code Genix clearly demonstrates how to create a nested route and, crucially, shows what happens when you forget the <Outlet /> and how adding it makes everything work.

First, watch the flat routing to see how a nested 'Contact Us' page is structured using file-based routing. Then, watch the Outlet demo to see the essential role of the <Outlet /> component in rendering the nested content.

As you saw, without <Outlet />, the router knows the child route is active, but it has nowhere to render its content.

The official documentation provides a concise explanation of the <Outlet /> component's role.

Outlets | TanStack Router React Docs

Please read this short page from the TanStack Router documentation. It formally defines the Outlet component and shows its use in a root route, which is the most common layout pattern.

In the Outlets guide, find the section 'The Outlet Component'. Read the Outlet behavior. Note the tip: if a route's component is left undefined, it renders an <Outlet /> by default. This is a useful convention for routes that only exist to group children.


2. Layout Routes: Sharing UI

A "Layout Route" is simply a parent route whose primary purpose is to provide a shared UI structure (the "layout") for its child routes. This is exactly what we saw in the previous example: the parent route component contained the common UI, and the <Outlet /> rendered the variable child content.

TanStack Router offers two main strategies for creating layout routes, depending on whether you want the layout to add a segment to the URL path.

A. Standard Layout Routes

These routes add a path segment to the URL and wrap all child routes. You can create them in two ways:

  1. Directory-based: Create a folder (e.g., app/) and place a route.tsx file inside it. This file defines the layout for all other routes in the app/ folder.
  2. Flat-file (dot notation): Create a file named app.tsx. This becomes the layout for any routes that start with app., like app.dashboard.tsx and app.settings.tsx.

The documentation provides clear examples of both structures.

Routing Concepts | TanStack Router React Docs

This section of the official docs explains Layout Routes with clear file structure diagrams and code examples. It's the best resource for understanding the core concept.

Read the 'Layout Routes' section. Pay attention to the two file structures presented (flat vs. directory) and the table showing which components are rendered for different URLs. This clarifies the parent-child rendering relationship.

For a more complex, real-world example of directory-based nesting, this video segment is excellent.

Complete TanStack Router Tutorial - Build Type-Safe React Apps with File-Based Routing

This clip from the 'Complete TanStack Router Tutorial' builds a deeply nested structure for product categories. It's a great example of how to organize a complex feature using folders and route.tsx files.

Watch the nested layout. Observe how folders with dynamic parameters ($categoryId) and route.tsx files are combined to create a clean, hierarchical, and powerful routing structure.

B. Pathless Layout Routes

Sometimes, you want to group routes under a shared layout for organizational purposes or to apply shared logic (like authentication checks) without adding a segment to the URL. For example, you might want / and /about to share a main site header and footer, but you don't want their URLs to be /_layout/ and /_layout/about.

This is achieved with Pathless Layout Routes. You create them by prefixing the file or folder name with an underscore (_).

Routing Concepts | TanStack Router React Docs

The documentation on Pathless Layout Routes explains this concept perfectly. It contrasts them with standard layout routes and clarifies their specific use case.

Read the 'Pathless Layout Routes' section. The key takeaway is the underscore prefix (_) and the fact that these routes do not add to the URL path. This is a powerful pattern for top-level site structure and applying middleware-like logic.


3. Practical Application: Building a Dashboard Layout

Let's synthesize these concepts into a practical example. We'll create an application with a main site layout and a nested dashboard section, which has its own specific layout.

Desired URL Structure & Layouts:

  • / and /about: Share a main layout with a header and footer.
  • /dashboard: Shows a dashboard-specific layout with a sidebar and renders the dashboard's index page.
  • /dashboard/profile: Shares the dashboard sidebar but renders the user's profile page.

File Structure:

This structure uses both a pathless layout for the main site and a standard layout for the dashboard section.

src/routes/
├── __root.tsx              # Root of the entire app
├── _main/                  # Pathless layout folder
│   ├── route.tsx           # Defines the main layout (Header/Footer)
│   ├── index.tsx           # Renders at `/`
│   └── about.tsx           # Renders at `/about`
└── dashboard/              # Standard layout folder
    ├── route.tsx           # Defines the dashboard layout (Sidebar)
    ├── index.tsx           # Renders at `/dashboard`
    └── profile.tsx         # Renders at `/dashboard/profile`

Code Implementation:

1. src/routes/_main/route.tsx (Pathless Main Layout)
This layout wraps the home (/) and about (/about) pages. Because the folder is named _main, it does not add /main to the URL.

import { createFileRoute, Link, Outlet } from '@tanstack/react-router';

export const Route = createFileRoute('/_main')({
  component: MainLayout,
});

function MainLayout() {
  return (
    <div>
      <header style={{ padding: '1rem', borderBottom: '1px solid #ccc' }}>
        <nav style={{ display: 'flex', gap: '1rem' }}>
          <Link to="/">Home</Link>
          <Link to="/about">About</Link>
          <Link to="/dashboard">Dashboard</Link>
        </nav>
      </header>
      <main style={{ padding: '1rem' }}>
        {/* Child routes (index.tsx, about.tsx) render here */}
        <Outlet />
      </main>
      <footer style={{ padding: '1rem', borderTop: '1px solid #ccc', marginTop: '2rem' }}>
        My App Footer
      </footer>
    </div>
  );
}

2. src/routes/dashboard/route.tsx (Standard Dashboard Layout)
This layout wraps all pages within the /dashboard section. It adds the /dashboard segment to the URL.

import { createFileRoute, Link, Outlet } from '@tanstack/react-router';

export const Route = createFileRoute('/dashboard')({
  component: DashboardLayout,
});

function DashboardLayout() {
  return (
    <div style={{ display: 'flex' }}>
      <aside style={{ width: '200px', padding: '1rem', borderRight: '1px solid #ccc' }}>
        <h3>Dashboard</h3>
        <nav style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>
          <Link to="/dashboard" activeProps={{ style: { fontWeight: 'bold' } }}>
            Overview
          </Link>
          <Link to="/dashboard/profile" activeProps={{ style: { fontWeight: 'bold' } }}>
            Profile
          </Link>
        </nav>
      </aside>
      <main style={{ flex: 1, padding: '1rem' }}>
        {/* Child dashboard routes (index.tsx, profile.tsx) render here */}
        <Outlet />
      </main>
    </div>
  );
}

The other files (index.tsx, about.tsx, profile.tsx) would just contain the specific content for their respective pages. This structure cleanly separates shared layouts from page-specific content.


Conclusion

Today you've learned how to structure a scalable React application using TanStack Router's powerful nesting and layout features. This file-based approach provides an intuitive way to manage complex UIs.

Key Takeaways:

  • Nested Routes are created by organizing files into folders, mirroring the URL structure.
  • The <Outlet /> component is essential; it's the placeholder where a parent route renders its active child route.
  • Layout Routes are parent routes that define a shared UI shell for their children.
  • Standard Layouts (e.g., dashboard/route.tsx) add a URL segment and are ideal for feature-specific sections of an app.
  • Pathless Layouts (e.g., _main/route.tsx) group routes under a common UI without affecting the URL, perfect for the main application shell.

Next Lesson Preview:

Now that we have a firm grasp of routing and UI structure, we'll shift our focus to data and execution context. In the next lesson, we will "Analyze TanStack Start's mechanism for distinguishing server-only ('use server') and client-side code execution." This is a critical concept for understanding how to write code that runs in the correct environment in an SSR application.

Can't find a good explanation? Sign up and we'll make it for you

Sign up