
Skill
devtools-framework-adapters
create framework adapters for devtools
Description
Use devtools-utils factory functions to create per-framework plugin adapters. createReactPlugin/createSolidPlugin/createVuePlugin/createPreactPlugin, createReactPanel/createSolidPanel/createVuePanel/createPreactPanel. [Plugin, NoOpPlugin] tuple for tree-shaking. DevtoolsPanelProps (theme). Vue uses (name, component) not options object. Solid render must be function.
SKILL.md
Use @tanstack/devtools-utils factory functions to create per-framework devtools plugin adapters. Each framework has a subpath export (/react, /vue, /solid, /preact) with two factories:
createXPlugin-- wraps a component into a[Plugin, NoOpPlugin]tuple for tree-shaking.createXPanel-- wraps a class-based devtools core (mount/unmount) into a[Panel, NoOpPanel]component tuple.
Key Source Files
packages/devtools-utils/src/react/plugin.tsx-- createReactPluginpackages/devtools-utils/src/react/panel.tsx-- createReactPanel, DevtoolsPanelPropspackages/devtools-utils/src/vue/plugin.ts-- createVuePlugin (different API)packages/devtools-utils/src/vue/panel.ts-- createVuePanel, DevtoolsPanelProps (includes 'system' theme)packages/devtools-utils/src/solid/plugin.tsx-- createSolidPluginpackages/devtools-utils/src/solid/panel.tsx-- createSolidPanelpackages/devtools-utils/src/solid/class.ts-- constructCoreClass (Solid-specific)packages/devtools-utils/src/preact/plugin.tsx-- createPreactPluginpackages/devtools-utils/src/preact/panel.tsx-- createPreactPanel
Shared Pattern
All four frameworks follow the same two-factory pattern:
Plugin Factory
Every createXPlugin returns readonly [Plugin, NoOpPlugin]:
- Plugin -- returns a plugin object with metadata and a
renderfunction that renders your component. - NoOpPlugin -- returns a plugin object with the same metadata but renders an empty fragment.
Panel Factory
Every createXPanel returns readonly [Panel, NoOpPanel]:
- Panel -- a framework component that creates a
<div style="height:100%">, instantiates the core class, callscore.mount(el, theme)on mount, andcore.unmount()on cleanup. - NoOpPanel -- renders an empty fragment.
DevtoolsPanelProps
// React, Solid, Preact
interface DevtoolsPanelProps {
theme?: 'light' | 'dark'
}
// Vue (note: includes 'system')
interface DevtoolsPanelProps {
theme?: 'dark' | 'light' | 'system'
}
Import from the framework subpath:
import type { DevtoolsPanelProps } from '@tanstack/devtools-utils/react'
import type { DevtoolsPanelProps } from '@tanstack/devtools-utils/vue'
import type { DevtoolsPanelProps } from '@tanstack/devtools-utils/solid'
import type { DevtoolsPanelProps } from '@tanstack/devtools-utils/preact'
Primary Example (React)
import { createReactPlugin } from '@tanstack/devtools-utils/react'
function MyStorePanel({ theme }: { theme?: 'light' | 'dark' }) {
return <div className={theme}>My Store Devtools</div>
}
const [MyPlugin, NoOpPlugin] = createReactPlugin({
name: 'My Store',
id: 'my-store',
defaultOpen: false,
Component: MyStorePanel,
})
// Tree-shaking: use NoOp in production
const ActivePlugin =
process.env.NODE_ENV === 'development' ? MyPlugin : NoOpPlugin
With Class-Based Panel
import {
createReactPanel,
createReactPlugin,
} from '@tanstack/devtools-utils/react'
class MyDevtoolsCore {
mount(el: HTMLElement, theme: 'light' | 'dark') {
/* render into el */
}
unmount() {
/* cleanup */
}
}
const [MyPanel, NoOpPanel] = createReactPanel(MyDevtoolsCore)
const [MyPlugin, NoOpPlugin] = createReactPlugin({
name: 'My Store',
Component: MyPanel,
})
Framework API Differences
React & Preact -- Options Object
createReactPlugin({ name, id?, defaultOpen?, Component }) // => [Plugin, NoOpPlugin]
createPreactPlugin({ name, id?, defaultOpen?, Component }) // => [Plugin, NoOpPlugin]
ComponentreceivesDevtoolsPanelProps(withtheme).Plugin()returns{ name, id?, defaultOpen?, render(el, theme) }.- Preact is identical to React but uses Preact JSX types and
preact/hooks.
Vue -- Positional Arguments, NOT Options Object
createVuePlugin(name: string, component: DefineComponent) // => [Plugin, NoOpPlugin]
- Takes
(name, component)as separate arguments, NOT an options object. Plugin(props)returns{ name, component, props }-- it passes props through.NoOpPlugin(props)returns{ name, component: Fragment, props }.- Vue's
DevtoolsPanelProps.themealso accepts'system'.
Solid -- Same API as React, Different Internals
createSolidPlugin({ name, id?, defaultOpen?, Component }) // => [Plugin, NoOpPlugin]
- Same options-object API as React.
Componentmust be a Solid component function(props: DevtoolsPanelProps) => JSX.Element.- The render function internally returns
<Component theme={theme} />-- Solid handles reactivity. - Solid also exports
constructCoreClassfrom@tanstack/devtools-utils/solid/classfor building lazy-loaded devtools cores.
Common Mistakes
CRITICAL: Using React JSX Pattern in Vue Adapter
Vue uses positional (name, component) arguments, NOT an options object.
// WRONG -- will fail at compile time or produce garbage at runtime
const [MyPlugin, NoOpPlugin] = createVuePlugin({
name: 'My Plugin',
Component: MyPanel,
})
// CORRECT
const [MyPlugin, NoOpPlugin] = createVuePlugin('My Plugin', MyPanel)
Vue plugins also work differently at call time -- you pass props:
// WRONG -- calling Plugin() with no args (React pattern)
const plugin = MyPlugin()
// CORRECT -- Vue Plugin takes props
const plugin = MyPlugin({ theme: 'dark' })
CRITICAL: Solid Render Prop Not Wrapped in Function
When using Solid components, Component must be a function reference, not raw JSX.
// WRONG -- evaluates immediately, breaks Solid reactivity
createSolidPlugin({
name: 'My Store',
Component: <MyPanel />, // This is JSX.Element, not a component function
})
// CORRECT -- pass the component function itself
createSolidPlugin({
name: 'My Store',
Component: (props) => <MyPanel theme={props.theme} />,
})
// ALSO CORRECT -- pass the component reference directly
createSolidPlugin({
name: 'My Store',
Component: MyPanel,
})
HIGH: Ignoring NoOp Variant for Production
The factory returns [Plugin, NoOpPlugin]. Both must be destructured and used for proper tree-shaking.
// WRONG -- NoOp variant discarded, devtools code ships to production
const [MyPlugin] = createReactPlugin({ name: 'Store', Component: MyPanel })
// CORRECT -- conditionally use NoOp in production
const [MyPlugin, NoOpPlugin] = createReactPlugin({
name: 'Store',
Component: MyPanel,
})
const ActivePlugin =
process.env.NODE_ENV === 'development' ? MyPlugin : NoOpPlugin
MEDIUM: Not Passing Theme Prop to Panel Component
DevtoolsPanelProps includes theme. The devtools shell passes it so panels can match light/dark mode. If your component ignores it, the panel will not adapt to theme changes.
// WRONG -- theme is ignored
const Component = () => <div>My Panel</div>
// CORRECT -- use theme for styling
const Component = ({ theme }: DevtoolsPanelProps) => (
<div className={theme === 'dark' ? 'dark-mode' : 'light-mode'}>My Panel</div>
)
Design Tension
The core architecture is framework-agnostic, but each framework has different idioms:
- React/Preact use an options object with
Componentas a JSX function component. - Vue uses positional arguments with a
DefineComponentand passes props through. - Solid uses the same options API as React but with Solid's JSX and reactivity model.
Agents trained on React patterns will get Vue wrong. Always check the import path to determine which factory API to use.
Cross-References
- devtools-plugin-panel -- Build your panel component first, then wrap it with the appropriate framework adapter.
- devtools-production -- NoOp variants are the primary mechanism for stripping devtools from production bundles.
Reference Files
references/react.md-- Full React factory API and examplesreferences/vue.md-- Full Vue factory API and examples (different from React)references/solid.md-- Full Solid factory API and examplesreferences/preact.md-- Full Preact factory API and examples
More skills from the devtools repository
View all 9 skillsdevtools-app-setup
configure TanStack Devtools for applications
Jul 16DebuggingFrontendTanStackdevtools-bidirectional
implement bidirectional devtools communication
Jul 16DebuggingObservabilityTanStackdevtools-event-client
implement typed event clients for libraries
Jul 16API DevelopmentEngineeringTanStackdevtools-instrumentation
instrument library code for devtools
Jul 16DebuggingEngineeringObservabilityTanStackdevtools-marketplace
publish plugins to TanStack Devtools Marketplace
Jul 16npmTanStackdevtools-plugin-panel
build TanStack devtools panels
Jul 16FrontendObservabilityTanStackUI Components
More from TanStack
View publisheraggregation
perform data aggregation in TanStack Table
table
Jul 26Data AnalysisFrontendTanStackapi-not-found
diagnose TanStack Table API errors
table
Jul 26DebuggingFrontendTanStackcell-selection
select rectangular cell ranges in tables
table
Jul 26Data AnalysisTanStackUI Componentsclient-vs-server
manage TanStack Table data pipelines
table
Jul 26Data PipelineFrontendPerformanceTanStackcolumn-faceting
build faceted filter UIs
table
Jul 26Data VisualizationFrontendTanStackcolumn-filtering
implement column filtering in TanStack Table
table
Jul 26Data AnalysisFrontendTanStack