Devtools
Purpose and Scope
TanStack Router devtools are the first debugging surface to add when a Router application starts to involve nested routes, data loading, redirects, search parameters, or route tree generation. The Router docs describe them as dedicated devtools that visualize the inner workings of TanStack Router and can save hours when debugging navigation behavior. In practice, the component gives developers a live place to inspect router state instead of guessing from rendered UI alone. This page explains the supported installation path, where the component should be mounted, how it finds a router instance, and which import to choose for development or production usage.
Sources: docs/router/devtools.md
The devtools integration is intentionally packaged separately from the main framework router package. That separation matters for application authors because it keeps the core routing dependency focused on runtime navigation while letting teams opt into debugging UI when they need it. The Router documentation shows framework-specific devtools packages for React and Solid, matching the framework-specific router packages used by those applications. The documented examples use the same conceptual flow in both frameworks: install the adapter package, import the framework component, then render it near the router so it can observe the active router instance.
Sources: docs/router/devtools.md
Relevant Source Files
- docs/router/devtools.md - Official Router devtools guide for installing framework devtools packages, importing development and production variants, rendering the component in the root route, manually passing the router instance, and using floating mode.
Framework Packages and Imports
The documented packages are framework adapters rather than a single universal component. React applications install the React Router devtools package, and Solid applications install the Solid Router devtools package. After installation, each framework imports a component with the same public name from its framework package. That naming symmetry is useful when moving between examples, because the React and Solid snippets differ mainly by package name and by the router framework package used in the surrounding route component. The devtools package is therefore selected by framework, while the integration pattern remains consistent across the documented adapters.
Sources: docs/router/devtools.md
npm install @tanstack/react-router-devtools
# or
npm install @tanstack/solid-router-devtoolsimport { TanStackRouterDevtools } from '@tanstack/react-router-devtools'import { TanStackRouterDevtools } from '@tanstack/solid-router-devtools'The standard import is optimized for normal development usage. The docs state that when the component is imported as TanStackRouterDevtools it will not be shown in production. That is an important operational detail: teams can place the component in shared application code without accidentally displaying it to end users after a production build. If production troubleshooting requires the same UI in an environment where the runtime reports production mode, the docs provide a separate import named TanStackRouterDevtoolsInProd. That production variant has the same options, but its name makes the deployment decision explicit in code review.
Sources: docs/router/devtools.md
import { TanStackRouterDevtoolsInProd } from '@tanstack/react-router-devtools'import { TanStackRouterDevtoolsInProd } from '@tanstack/solid-router-devtools'Mounting in the Route Tree
The easiest documented setup is to render the devtools in the root route. In a file-based Router app, that commonly means the root route component renders the application outlet and the devtools side by side. The docs explain that rendering inside the root route, or inside any route under the provider, automatically connects the devtools to the router instance. This is the default recommendation because the component can use its position inside the router context instead of requiring the application to thread a router value through a separate part of the component tree.
Sources: docs/router/devtools.md
import { createRootRoute, Outlet } from '@tanstack/react-router'
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'
export const Route = createRootRoute({
component: () => (
<>
<Outlet />
<TanStackRouterDevtools />
</>
),
})This root-route placement also fits how Router applications are usually composed. The outlet renders whichever child route matches the current location, while the devtools remain mounted across route changes. That makes the tool useful during transitions because it is not destroyed when the user navigates from one child route to another. For debugging layout routes, pending UI, route errors, or nested child matching, keeping the devtools at the root gives a stable inspection point while the rest of the route tree changes underneath it.
Sources: docs/router/devtools.md
Manual Router Instance Wiring
The devtools do not have to be rendered inside RouterProvider. The docs document a router prop that accepts the same router instance passed to the RouterProvider component. This mode is useful when an application shell, portal, layout system, or debugging overlay lives outside the provider subtree. Instead of relying on context lookup, the application passes the router object directly. The important constraint is that both RouterProvider and TanStackRouterDevtools receive the same instance; otherwise the devtools would not be observing the router that actually drives the visible application.
Sources: docs/router/devtools.md
function App() {
return (
<>
<RouterProvider router={router} />
<TanStackRouterDevtools router={router} />
</>
)
}Manual wiring is also the safer pattern when you want the devtools near the top of a custom app shell but not inside a route component. For example, a shell may render providers, global modals, analytics, and a router provider as siblings. Passing the router prop keeps the devtools location independent from the routing context while preserving the same debugging behavior. The docs emphasize that this makes it possible to place the devtools anywhere on the page, not only inside the provider, which is especially helpful for app architectures that centralize overlays outside normal route rendering.
Sources: docs/router/devtools.md
Floating Mode and Runtime Behavior
Floating mode is the documented default style for putting the devtools in an application without dedicating permanent layout space to them. The docs describe it as a fixed floating element with a corner toggle that can show and hide the panel. The toggle state is stored in localStorage and remembered across reloads, so developers do not need to reopen or reclose the panel every time the page refreshes. The guide recommends placing the component as high in the app as possible, because a root-level placement makes the floating overlay behave more predictably across navigation and layout changes.
Sources: docs/router/devtools.md
function App() {
return (
<>
<RouterProvider router={router} />
<TanStackRouterDevtools initialIsOpen={false} />
</>
)
}The initialIsOpen option shown in the docs is a practical default for teams that want the devtools available but unobtrusive. With the panel initially closed, the application can keep the debugging affordance on screen while avoiding a large inspection surface during normal development flows. Because the toggle state is persisted, developers can still keep the panel open during an active debugging session. That behavior is especially useful when reproducing navigation issues that require reloads, because the devtools can remain in the last chosen state while the application returns to the problematic route.
Sources: docs/router/devtools.md
Debugging Workflow and Panel Use
Use the devtools when the visible page does not explain what the router is doing. Start by mounting the component at the root route, reproduce the navigation, and then compare the active route hierarchy with the UI you expected to render. If a route is missing, inspect the route tree and matching assumptions before changing loader or component code. If route state changes but the UI does not, focus on outlets, layouts, or component boundaries. If the devtools cannot see the router, move it inside the provider or pass the router prop explicitly.
Sources: docs/router/devtools.md
The broader TanStack Devtools ecosystem also supports a multi-panel shell where Router debugging can sit beside other TanStack panels. That workflow is useful in applications that combine TanStack Router with data or form tools, because route transitions and data activity often interact. The standalone Router docs on this page focus on the dedicated Router devtools component, while the shared Devtools documentation describes composing named panels in a single client UI. For most Router-only debugging, start with TanStackRouterDevtools. For cross-library inspection, consider the shared TanStack Devtools shell and add the Router panel alongside the other panels your app uses.
Next Steps
After adding the devtools, use them together with the route-tree and data-loading guides rather than treating them as an isolated widget. If a route does not render, read the route tree, layouts, and outlets material next. If navigation reaches the route but data is stale or pending, move to the data loading and preloading pages. If a generated route is absent or typed links do not match expected paths, continue with file-based routing and route generation. The devtools give the runtime view; the related guides explain how to fix the source route definitions that created that runtime behavior.
Sources: docs/router/devtools.md