Routing

TanStack Start is built on top of TanStack Router, so all of the features of TanStack Router are available to you.

Note

We highly recommend reading the TanStack Router documentation to learn more about the features and capabilities of TanStack Router. What you learn here is more of a high-level overview of TanStack Router and how it works in Start.

The Router

The router.tsx file is the file that will dictate the behavior of TanStack Router used within Start. It's located in the src directory of your project.

src/
├── router.tsx
src/
├── router.tsx

Here, you can configure everything from the default preloading functionality to caching staleness.

// src/router.tsx
import { createRouter } from '@tanstack/solid-router'
import { routeTree } from './routeTree.gen'

// You must export a getRouter function that
// returns a new router instance each time
export function getRouter() {
  const router = createRouter({
    routeTree,
    scrollRestoration: true,
  })

  return router
}
// src/router.tsx
import { createRouter } from '@tanstack/solid-router'
import { routeTree } from './routeTree.gen'

// You must export a getRouter function that
// returns a new router instance each time
export function getRouter() {
  const router = createRouter({
    routeTree,
    scrollRestoration: true,
  })

  return router
}

File-Based Routing

Start uses TanStack Router's file-based routing approach to ensure proper code-splitting and advanced type-safety.

You can find your routes in the src/routes directory.

src/
├── routes <-- This is where you put your routes
│   ├── __root.tsx
│   ├── index.tsx
│   ├── about.tsx
│   ├── posts.tsx
│   ├── posts/$postId.tsx
src/
├── routes <-- This is where you put your routes
│   ├── __root.tsx
│   ├── index.tsx
│   ├── about.tsx
│   ├── posts.tsx
│   ├── posts/$postId.tsx

The Root Route

The root route is the top-most route in the entire tree and encapsulates all other routes as children. It's found in the src/routes/__root.tsx file and must be named __root.tsx.

src/
├── routes
│   ├── __root.tsx <-- The root route
src/
├── routes
│   ├── __root.tsx <-- The root route
  • It has no path and is always matched
  • Its component is always rendered
  • This is where you render your document shell, e.g. <html>, <body>, etc.
  • Because it is always rendered, it is the perfect place to construct your application shell and take care of any global logic
// src/routes/__root.tsx
import {
  Outlet,
  createRootRoute,
  HeadContent,
  Scripts,
} from '@tanstack/solid-router'
import type { SolidJSNode } from 'react'

export const Route = createRootRoute({
  head: () => ({
    meta: [
      {
        charSet: 'utf-8',
      },
      {
        name: 'viewport',
        content: 'width=device-width, initial-scale=1',
      },
      {
        title: 'TanStack Start Starter',
      },
    ],
  }),
  component: RootComponent,
})

function RootComponent() {
  return (
    <RootDocument>
      <Outlet />
    </RootDocument>
  )
}

function RootDocument({ children }: Readonly<{ children: SolidJSNode }>) {
  return (
    <html>
      <head>
        <HeadContent />
      </head>
      <body>
        {children}
        <Scripts />
      </body>
    </html>
  )
}
// src/routes/__root.tsx
import {
  Outlet,
  createRootRoute,
  HeadContent,
  Scripts,
} from '@tanstack/solid-router'
import type { SolidJSNode } from 'react'

export const Route = createRootRoute({
  head: () => ({
    meta: [
      {
        charSet: 'utf-8',
      },
      {
        name: 'viewport',
        content: 'width=device-width, initial-scale=1',
      },
      {
        title: 'TanStack Start Starter',
      },
    ],
  }),
  component: RootComponent,
})

function RootComponent() {
  return (
    <RootDocument>
      <Outlet />
    </RootDocument>
  )
}

function RootDocument({ children }: Readonly<{ children: SolidJSNode }>) {
  return (
    <html>
      <head>
        <HeadContent />
      </head>
      <body>
        {children}
        <Scripts />
      </body>
    </html>
  )
}

Notice the Scripts component at the bottom of the <body> tag. This is used to load all of the client-side JavaScript for the application and should always be included for proper functionality.

The HeadContent Component

The HeadContent component is used to render the head, title, meta, link, and head-related script tags of the document.

It should be rendered in the <head> tag of your root route's layout.

The Outlet Component

The Outlet component is used to render the next potentially matching child route. <Outlet /> doesn't take any props and can be rendered anywhere within a route's component tree. If there is no matching child route, <Outlet /> will render null.

The Scripts Component

The Scripts component is used to render the body scripts of the document.

It should be rendered in the <body> tag of your root route's layout.

Route Tree Generation

You may notice a routeTree.gen.ts file in your project.

src/
├── routeTree.gen.ts <-- The generated route tree file
src/
├── routeTree.gen.ts <-- The generated route tree file

This file is automatically generated when you run TanStack Start (via npm run dev or npm run start). This file contains the generated route tree and a handful of TS utilities that make TanStack Start's type-safety extremely fast and fully inferred.

You may gitignore this file, since it is a build artifact.

Nested Routing

TanStack Router uses nested routing to match the URL with the correct component tree to render.

For example, given the following routes:

routes/
├── __root.tsx <-- Renders the <Root> component
├── posts.tsx <-- Renders the <Posts> component
├── posts.$postId.tsx <-- Renders the <Post> component
routes/
├── __root.tsx <-- Renders the <Root> component
├── posts.tsx <-- Renders the <Posts> component
├── posts.$postId.tsx <-- Renders the <Post> component

And the URL: /posts/123

The component tree would look like this:

<Root>
  <Posts>
    <Post />
  </Posts>
</Root>
<Root>
  <Posts>
    <Post />
  </Posts>
</Root>

Types of Routes

There are a few different types of routes that you can create in your project.

  • Index Routes - Matched when the URL is exactly the same as the route's path
  • Dynamic/Wildcard/Splat Routes - Dynamically capture part or all of the URL path into a variable to use in your application

There are also a few different utility route types that you can use to group and organize your routes

  • Pathless Layout Routes (Apply layout or logic to a group of routes without nesting them in a path)
  • Non-Nested Routes (Un-nest a route from its parents and render its own component tree)
  • Grouped Routes (Group routes together in a directory simply for organization, without affecting the path hierarchy)

Route Tree Configuration

The route tree is configured in the src/routes directory.

Creating File Routes

To create a route, create a new file that corresponds to the path of the route you want to create. For example:

PathFilenameType
/index.tsxIndex Route
/aboutabout.tsxStatic Route
posts.tsx"Layout" Route
/posts/posts/index.tsxIndex Route
/posts/:postIdposts/$postId.tsxDynamic Route
/rest/*rest/$.tsxWildcard Route

Defining Routes

To define a route, use the createFileRoute function to export the route as the Route variable.

For example, to handle the /posts/:postId route, you would create a file named posts/$postId.tsx here:

src/
├── routes
│   ├── posts/$postId.tsx
src/
├── routes
│   ├── posts/$postId.tsx

Then, define the route like this:

// src/routes/posts/$postId.tsx
import { createFileRoute } from '@tanstack/solid-router'

export const Route = createFileRoute('/posts/$postId')({
  component: PostComponent,
})
// src/routes/posts/$postId.tsx
import { createFileRoute } from '@tanstack/solid-router'

export const Route = createFileRoute('/posts/$postId')({
  component: PostComponent,
})

Note

The path string passed to createFileRoute is automatically written and managed by the router for you via the TanStack Router Bundler Plugin or Router CLI. So, as you create new routes, move routes around or rename routes, the path will be updated for you automatically.

This is just the "start"

This has been just a high-level overview of how to configure routes using TanStack Router. For more detailed information, please refer to the TanStack Router documentation.

Subscribe to Bytes

Your weekly dose of JavaScript news. Delivered every Monday to over 100,000 devs, for free.

Bytes

No spam. Unsubscribe at any time.

Subscribe to Bytes

Your weekly dose of JavaScript news. Delivered every Monday to over 100,000 devs, for free.

Bytes

No spam. Unsubscribe at any time.