TanStack Devtools (React)

A React component that mounts TanStack's extensible, plugin-based devtools panel inside your app.

Library
npm
v0.10.13
507 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
80 /100 Excellent
Development Activity 88
Maintenance 92
Community 64
Maturity 36
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
78 /100 Good
Architecture 78
Code Quality 68
Innovation 74
Learning Curve 90

@tanstack/react-devtools is the React adapter for TanStack Devtools, a framework-agnostic debugging toolkit for inspecting and monitoring application state in real time. It wraps the framework-agnostic devtools engine in a single <TanStackDevtools> component, handling mounting, unmounting, and plugin rendering through React portals so state changes on the core panel translate directly into React re-renders.

Rather than shipping one fixed panel, the package exposes a plugins array: any devtools UI - TanStack Query, TanStack Router, or a hand-built internal panel - registers with an id, name, and render function and appears as a tab inside the same floating shell. This lets teams combine several libraries’ devtools into one consistent panel instead of stacking separate floating widgets, and lets consumers ship their own plugins for application-specific state.

What You Get

  • A single <TanStackDevtools> component that mounts the devtools shell on render and tears it down on unmount
  • A plugins array API for registering any number of devtools panels, first-party TanStack ones or custom, as tabs in one shell
  • Automatic React portal wiring between the core-rendered shell and React-rendered plugin content
  • Support for a customTrigger component to replace the default floating launcher button
  • Configurable eventBusConfig for how the devtools core communicates with connected plugin clients
  • TypeScript types for plugin definitions, configuration, and theming out of the box

Common Use Cases

  • Combining TanStack Query Devtools and TanStack Router Devtools into a single panel instead of two floating widgets
  • Building a custom internal devtools plugin to inspect application-specific state alongside library devtools
  • Swapping the default floating trigger button for an app-branded toggle via customTrigger
  • Debugging real-time state changes during local development without shipping the panel in production builds

Under The Hood

Architecture

The package itself is a thin adapter (src/devtools.tsx, under 300 lines) exporting one TanStackDevtools component. On first render it lazily constructs a TanStackDevtoolsCore instance inside a useState initializer, wires a hidden ref div, and calls devtools.mount()/devtools.unmount() from a useEffect keyed on that instance. Plugins passed via props are wrapped so their name/render callbacks receive an HTMLElement plus theme/open-state props from the core, and the results are pushed into React state (pluginContainers/PluginComponents, titleContainers/TitleComponents, triggerContainer/TriggerComponent). A separate useEffect re-runs devtools.setConfig({ plugins }) whenever the plugin list changes, propagating updates without remounting the whole shell.

Tech Stack

Built with TypeScript against React 19 (peer range >=16.8), bundled via vite build using the shared @tanstack/vite-config preset for ESM-only output, and tested with Vitest plus @testing-library/react under jsdom. Linting layers @eslint-react/eslint-plugin, eslint-plugin-react-hooks, and eslint-plugin-react-compiler on top of a shared root ESLint config. The panel engine it wraps, @tanstack/devtools, is itself implemented in SolidJS with goober for styling and @neodrag plus solid-primitives for drag/keyboard/resize interactions. The whole monorepo is orchestrated with Nx, pnpm workspaces, Changesets for releases, and size-limit for bundle-size CI gates.

Code Quality

A single but deliberate test file (tests/devtools.test.tsx) mocks TanStackDevtoolsCore entirely - with an inline comment explaining that mounting the real Solid-rendered core in jsdom is too heavy - and drives the adapter’s own wiring: constructing the core once, calling mount/unmount, and portaling a plugin’s React element into a core-provided container. Types are used throughout (discriminated unions for PluginRender/TriggerRender, exported TanStackDevtoolsReactPlugin/TanStackDevtoolsReactInit), and ESLint enforces react-hooks/rules-of-hooks, exhaustive-deps, and React Compiler compatibility as hard errors. publint --strict checks package.json/exports correctness in CI. There’s no broader integration or e2e suite scoped specifically to this adapter beyond that one unit test.

API Design The public surface is intentionally small: one <TanStackDevtools> component takes a plugins array plus optional config/eventBusConfig, so wiring in TanStack Query or Router devtools is just importing their exported panel component and dropping it into a plugin’s render field - no provider wrapping or manual mount calls required. Plugin authors write ordinary React, or a render callback receiving the mount element and theme/open-state props, rather than learning a devtools-specific rendering API, and richly-commented exported types double as inline documentation in editor tooltips. The main friction point is the implicit coupling to the core’s callback contract (render(el, props), name as string or function) which isn’t self-evident without also reading the core package’s types.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers