Capítulo 7 de 57

Chapter 7: Manual Installation

Core Idea

Manual setup requires installing @tanstack/react-router (plus optionally @tanstack/react-router-devtools and, for file-based routing, @tanstack/router-plugin), then wiring a root route, at least one child route, and a main.tsx entry that creates the router, registers it via module declaration, and renders RouterProvider, either through file-based routing or a single-file code-based configuration.

Key Concepts

  • File-based setup files: src/routes/__root.tsx (root layout, note the double underscore), src/routes/index.tsx, src/routes/about.tsx, and src/main.tsx are the minimum files needed.
  • Vite plugin ordering: tanstackRouter({ target: 'react', autoCodeSplitting: true }) from @tanstack/router-plugin/vite must be passed to Vite's plugins array before @vitejs/plugin-react.
  • Generated route tree location: Regardless of which bundler/CLI drives generation, the output lands at src/routeTree.gen.ts and is imported into main.tsx as routeTree.
  • createRootRoute: Defines the root layout component (rendering <Outlet /> for children); used identically in both file-based and code-based setups.
  • createRouter + module declaration: const router = createRouter({ routeTree }) followed by declare module '@tanstack/react-router' { interface Register { router: typeof router } } in main.tsx is the standard boilerplate for type-safe registration.
  • Code-based single-file alternative: createRoute({ getParentRoute: () => rootRoute, path: '/', component: ... }) plus rootRoute.addChildren([indexRoute, aboutRoute]) builds the route tree manually; docs recommend splitting routes into separate files as the app grows even though a single file works for demos.
  • Root <div> id: When using file-based routing generated output, the root HTML element should be <div id="root"></div> (code-based example in the docs instead targets id="app").

Code Examples

// src/main.tsx
import { StrictMode } from 'react'
import ReactDOM from 'react-dom/client'
import { RouterProvider, createRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'

const router = createRouter({ routeTree })

declare module '@tanstack/react-router' {
  interface Register {
    router: typeof router
  }
}

const rootElement = document.getElementById('root')!
if (!rootElement.innerHTML) {
  const root = ReactDOM.createRoot(rootElement)
  root.render(
    <StrictMode>
      <RouterProvider router={router} />
    </StrictMode>,
  )
}
  • What it demonstrates: The canonical entry point boilerplate: import the generated route tree, create the router, register it for type inference, and mount RouterProvider.

Key Takeaways

  1. Manual installation always ends with the same three steps regardless of file-based or code-based routing: build a routeTree, call createRouter({ routeTree }), then declare the Register module interface before rendering RouterProvider.
  2. When using Vite, the tanstackRouter plugin must precede @vitejs/plugin-react in the plugins array, ordering matters.
  3. Code-based routing in a single file is fine for demos/small apps, but the docs explicitly recommend splitting routes into separate files for organization and performance as the app grows.

Connects To

  • Ch 2: Quick Start's manual-install path is expanded in full detail here.
  • Ch 3: Devtools shows how TanStackRouterDevtools slots into the same __root.tsx file built here.
  • Ch 8: With Vite goes deeper into the Vite plugin configuration referenced in this chapter.
  • Ch 4: Decisions on DX explains why getParentRoute and module declaration are structured this way.