adding tanstack router to a vite app
I did not want to start a whole new project just to try a router. I had a Vite app sitting there doing nothing, so I bolted TanStack Router onto it. Turns out the whole thing is about 30 lines. Here is the smallest setup that actually works.
1. Install it
One package. npm install @tanstack/react-router. That is it for the code-based setup, which is what I recommend starting with because there are fewer moving parts.
2. Build the route tree
Make a src/router.tsx file. You define a root route, then hang routes off it with createRoute, then join them into a tree:
import {
createRootRoute,
createRoute,
createRouter,
} from '@tanstack/react-router'
const rootRoute = createRootRoute({
component: () => (
<div>
<h1>My app</h1>
</div>
),
})
const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/',
component: () => <p>Home page</p>,
})
const aboutRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/about',
component: () => <p>About page</p>,
})
const routeTree = rootRoute.addChildren([indexRoute, aboutRoute])
export const router = createRouter({ routeTree })}3. The step everyone forgets
Register the router with TypeScript, in the same file, below everything else. Without this, useParams returns unknown and you have thrown away the entire reason to use this router:
declare module '@tanstack/react-router' {
interface Register {
router: typeof router
}
}I forgot this the first time and spent 20 minutes wondering why my params had no types. (The docs do tell you. I did not read that far. We have all been there.)
4. Render it
In src/main.tsx, swap out your App component for the RouterProvider:
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { RouterProvider } from '@tanstack/react-router'
import { router } from './router'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<RouterProvider router={router} />
</StrictMode>,
)That is the whole integration. Run the dev server, visit /about, and it works.
Going file-based later
When the route tree gets big, the file-based setup is nicer. Install the plugin with npm install -D @tanstack/router-plugin, then add it to your Vite config. Order matters here, it must come before the React plugin:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { TanStackRouterVite } from '@tanstack/router-plugin/vite'
export default defineConfig({
plugins: [TanStackRouterVite(), react()],
})Then routes live in src/routes/: __root.tsx for the layout, index.tsx for /, posts.$postId.tsx for /posts/123. The plugin generates a routeTree.gen.ts file, which is why it all works. Add that file to your .gitignore, it is build output, not source.
So, what have I learnt?
- Start code-based. You can see every wire, and there is nothing hiding from you.
- The type registration step is not optional. It is the product.
- Plugin order in Vite configs will get you eventually. Now you know before it happens.
The devtools are worth installing too. One package, bottom-left corner, and you will wonder how you lived without the route inspector.