-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
[WIP] feat: add start devtools #5247
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughAdds a Start Devtools core, Solid and React adapters, workspace overrides, Vite/devtools integration in an example app, new event-client and event emission, plus package manifests, ESLint/TS/Vite configs, styling tokens/hooks, minimal components, tests, and environment-gated NoOp exports. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Dev as Developer (browser)
participant App as Example App
participant Vite as Vite (dev plugin)
participant Host as TanStackDevtools Host
participant ReactP as React Adapter
participant SolidP as Solid Adapter
participant StartCore as @tanstack/start-devtools
participant EventClient as startEventClient
Note over Vite,App: Build-time
Vite->>App: inject devtools runtime (devtools plugin)
Note over App,Host: Runtime (dev)
App->>Host: mount TanStackDevtools with plugins [React Query, Router, Start]
Host->>ReactP: initialize React panel (if registered)
Host->>SolidP: initialize Solid panel (if registered)
ReactP->>StartCore: construct / lazy-load core
SolidP->>StartCore: construct / lazy-load core
StartCore-->>ReactP: provide panel component
StartCore-->>SolidP: provide panel component
Host-->>Dev: render devtools UI panels
Note over EventClient,StartCore: runtime events
App->>EventClient: start-server emits "request-received"
EventClient-->>StartCore: forwards events to devtools UI
StartCore-->>Host: updates panel state
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
🧹 Nitpick comments (12)
packages/react-start-devtools/tests/index.test.ts (1)
1-7
: Replace placeholder test with actual implementation.This is a minimal placeholder test that doesn't validate any functionality. Consider adding tests for the React devtools components and hooks once the implementation is complete.
Based on the search results, here are some common patterns for testing TanStack-related packages:// More comprehensive test examples for devtools components import { describe, expect, it, vi } from 'vitest' import { render, screen } from '@testing-library/react' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' describe('React Start Devtools', () => { it('should render devtools panel in development', () => { const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false }, mutations: { retry: false }, }, }) // Test devtools component rendering // Add actual component tests here expect(true).toBe(true) }) it('should not render in production', () => { const originalEnv = process.env.NODE_ENV process.env.NODE_ENV = 'production' // Test production behavior // Add actual production test here process.env.NODE_ENV = originalEnv expect(true).toBe(true) }) })packages/start-devtools/package.json (1)
57-68
: Consider making solid-js a peer dependency to avoid duplicate framework copies.Framework libraries are typically peers. This prevents multiple Solid versions in consuming apps. Keep it as devDependency too for local builds.
Apply:
"dependencies": { "@tanstack/devtools-ui": "^0.3.4", "@tanstack/devtools-utils": "^0.0.3", "@tanstack/solid-store": "^0.7.5", "clsx": "^2.1.1", "dayjs": "^1.11.18", - "goober": "^2.1.16", - "solid-js": "^1.9.9" + "goober": "^2.1.16" }, + "peerDependencies": { + "solid-js": "^1.9.9" + }, "devDependencies": { - "vite-plugin-solid": "^2.11.8" + "vite-plugin-solid": "^2.11.8", + "solid-js": "^1.9.9" }packages/solid-start-devtools/package.json (2)
58-60
: Consider upgrading @tanstack/devtools-utils.Pinned to ^0.0.3 while latest published is higher; evaluate compatibility and update if safe.
Based on learnings
40-43
: Add publishConfig for public scoped publish.Prevents accidental “restricted” scope on publish.
Apply this diff:
"files": [ "dist/", "src" ], + "publishConfig": { + "access": "public" + },packages/react-start-devtools/package.json (3)
55-59
: Don’t list @types/ as peerDependencies.*Types should be dev-time, not required of consumers. Move them to devDependencies or mark as optional via peerDependenciesMeta.
Apply this diff:
"peerDependencies": { - "@types/react": ">=16.8", - "@types/react-dom": ">=16.8", "react": ">=16.8", "react-dom": ">=16.8" }, @@ "devDependencies": { + "@types/react": ">=16.8", + "@types/react-dom": ">=16.8", "@eslint-react/eslint-plugin": "^1.53.1", "@vitejs/plugin-react": "^5.0.2", "eslint-plugin-react-compiler": "19.1.0-rc.2", "eslint-plugin-react-hooks": "^5.2.0" }If you prefer to keep them as peers, add:
+ "peerDependenciesMeta": { + "@types/react": { "optional": true }, + "@types/react-dom": { "optional": true } + },
60-63
: Consider upgrading @tanstack/devtools-utils.Currently ^0.0.3; evaluate bump to the latest stable to reduce drift.
Based on learnings
40-43
: Add publishConfig for public scoped publish.Ensures npm publish uses public scope by default.
Apply this diff:
"files": [ "dist/", "src" ], + "publishConfig": { + "access": "public" + },examples/react/start-basic-react-query/vite.config.ts (1)
7-18
: Gate devtools plugin to dev mode.Avoids including dev-only plugin during production builds.
Apply this diff:
-export default defineConfig({ - server: { - port: 3000, - }, - plugins: [ - devtools(), - tsConfigPaths({ - projects: ['./tsconfig.json'], - }), - tanstackStart(), - viteReact(), - ], -}) +export default defineConfig(({ command }) => ({ + server: { + port: 3000, + }, + plugins: [ + ...(command === 'serve' ? [devtools()] : []), + tsConfigPaths({ + projects: ['./tsconfig.json'], + }), + tanstackStart(), + viteReact(), + ], +}))If the plugin already no-ops in build, feel free to skip this change.
packages/start-devtools/src/production.ts (1)
1-6
: Avoid forcing client-only semantics in core production entryUnless
./core
actually renders UI, the'use client'
directive here can unnecessarily force client boundaries for consumers. Prefer keeping this directive in framework-specific UI entries (React/Solid) and leave the core re-export neutral.Apply this diff if the core is UI-agnostic:
-'use client' - export { StartDevtoolsCore } from './core' export type { StartDevtoolsInit } from './core'To confirm intent, please verify whether
./core
uses browser-only APIs or JSX.packages/solid-start-devtools/src/plugin.tsx (1)
1-6
: Optional: inline export and drop .tsx (no JSX used)Minor ergonomics:
- No JSX here;
.ts
is sufficient.- You can inline the destructured exports to reduce boilerplate.
Apply this refactor:
-import { createSolidPlugin } from '@tanstack/devtools-utils/solid' -import { StartDevtoolsPanel } from './SolidStartDevtools' - -const [startDevtoolsPlugin, startDevtoolsNoOpPlugin] = createSolidPlugin("TanStack Start", StartDevtoolsPanel) - -export { startDevtoolsPlugin, startDevtoolsNoOpPlugin } +import { createSolidPlugin } from '@tanstack/devtools-utils/solid' +import { StartDevtoolsPanel } from './SolidStartDevtools' + +export const [startDevtoolsPlugin, startDevtoolsNoOpPlugin] = createSolidPlugin( + 'TanStack Start', + StartDevtoolsPanel, +)Also consider renaming the file to
plugin.ts
.packages/react-start-devtools/src/index.ts (1)
1-17
: Shift env gating to package.json for better tree-shaking
Remove the runtimeprocess.env.NODE_ENV
checks in src/index.ts and instead use conditional exports in packages/react-start-devtools/package.json to point"."
atdist/esm/index.js
in development and atdist/esm/production.js
in production so unused code is dropped.packages/start-devtools/src/index.ts (1)
1-11
: Prefer package.json conditional exports over runtime gating
Theprocess.env.NODE_ENV
check in yoursrc/index.ts
can pull both implementations into production bundles. Instead, map.
directly to your dev/prod builds inpackage.json
:"exports": { ".": { "development": "./dist/esm/index.js", "production": "./dist/esm/production.js", "default": "./dist/esm/index.js" } }This lets bundlers pick the correct entry at build time and tree-shake away the unused code.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (40)
examples/react/start-basic-react-query/package.json
(2 hunks)examples/react/start-basic-react-query/src/routes/__root.tsx
(2 hunks)examples/react/start-basic-react-query/vite.config.ts
(1 hunks)package.json
(3 hunks)packages/react-start-devtools/eslint.config.js
(1 hunks)packages/react-start-devtools/package.json
(1 hunks)packages/react-start-devtools/src/ReactStartDevtools.tsx
(1 hunks)packages/react-start-devtools/src/index.ts
(1 hunks)packages/react-start-devtools/src/plugin.tsx
(1 hunks)packages/react-start-devtools/src/production.ts
(1 hunks)packages/react-start-devtools/tests/index.test.ts
(1 hunks)packages/react-start-devtools/tests/test-setup.ts
(1 hunks)packages/react-start-devtools/tsconfig.docs.json
(1 hunks)packages/react-start-devtools/tsconfig.json
(1 hunks)packages/react-start-devtools/vite.config.ts
(1 hunks)packages/solid-start-devtools/eslint.config.js
(1 hunks)packages/solid-start-devtools/package.json
(1 hunks)packages/solid-start-devtools/src/SolidStartDevtools.tsx
(1 hunks)packages/solid-start-devtools/src/index.ts
(1 hunks)packages/solid-start-devtools/src/plugin.tsx
(1 hunks)packages/solid-start-devtools/src/production.ts
(1 hunks)packages/solid-start-devtools/tests/index.test.ts
(1 hunks)packages/solid-start-devtools/tests/test-setup.ts
(1 hunks)packages/solid-start-devtools/tsconfig.docs.json
(1 hunks)packages/solid-start-devtools/tsconfig.json
(1 hunks)packages/solid-start-devtools/vite.config.ts
(1 hunks)packages/start-devtools/CHANGELOG.md
(1 hunks)packages/start-devtools/eslint.config.js
(1 hunks)packages/start-devtools/package.json
(1 hunks)packages/start-devtools/src/StartDevtools.tsx
(1 hunks)packages/start-devtools/src/core.tsx
(1 hunks)packages/start-devtools/src/index.ts
(1 hunks)packages/start-devtools/src/production.ts
(1 hunks)packages/start-devtools/src/styles/tokens.ts
(1 hunks)packages/start-devtools/src/styles/use-styles.ts
(1 hunks)packages/start-devtools/tests/index.test.ts
(1 hunks)packages/start-devtools/tests/test-setup.ts
(1 hunks)packages/start-devtools/tsconfig.docs.json
(1 hunks)packages/start-devtools/tsconfig.json
(1 hunks)packages/start-devtools/vite.config.ts
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
packages/{*-start,start-*}/**
📄 CodeRabbit inference engine (AGENTS.md)
Name and place Start framework packages under packages/-start/ or packages/start-/
Files:
packages/start-devtools/tsconfig.docs.json
packages/start-devtools/src/production.ts
packages/start-devtools/eslint.config.js
packages/start-devtools/tests/test-setup.ts
packages/start-devtools/CHANGELOG.md
packages/start-devtools/tests/index.test.ts
packages/start-devtools/vite.config.ts
packages/start-devtools/src/styles/tokens.ts
packages/start-devtools/src/core.tsx
packages/start-devtools/src/StartDevtools.tsx
packages/start-devtools/tsconfig.json
packages/start-devtools/package.json
packages/start-devtools/src/styles/use-styles.ts
packages/start-devtools/src/index.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript in strict mode with extensive type safety across the codebase
Files:
packages/solid-start-devtools/src/production.ts
packages/start-devtools/src/production.ts
packages/react-start-devtools/src/production.ts
packages/start-devtools/tests/test-setup.ts
packages/solid-start-devtools/src/plugin.tsx
examples/react/start-basic-react-query/vite.config.ts
packages/start-devtools/tests/index.test.ts
packages/react-start-devtools/src/ReactStartDevtools.tsx
packages/start-devtools/vite.config.ts
packages/start-devtools/src/styles/tokens.ts
packages/start-devtools/src/core.tsx
packages/solid-start-devtools/src/index.ts
packages/react-start-devtools/src/index.ts
packages/start-devtools/src/StartDevtools.tsx
packages/react-start-devtools/src/plugin.tsx
packages/solid-start-devtools/src/SolidStartDevtools.tsx
packages/solid-start-devtools/tests/index.test.ts
examples/react/start-basic-react-query/src/routes/__root.tsx
packages/solid-start-devtools/tests/test-setup.ts
packages/react-start-devtools/vite.config.ts
packages/react-start-devtools/tests/index.test.ts
packages/start-devtools/src/styles/use-styles.ts
packages/start-devtools/src/index.ts
packages/solid-start-devtools/vite.config.ts
packages/react-start-devtools/tests/test-setup.ts
examples/{react,solid}/**
📄 CodeRabbit inference engine (AGENTS.md)
Keep example applications under examples/react/ and examples/solid/
Files:
examples/react/start-basic-react-query/vite.config.ts
examples/react/start-basic-react-query/src/routes/__root.tsx
examples/react/start-basic-react-query/package.json
**/package.json
📄 CodeRabbit inference engine (AGENTS.md)
Use workspace:* protocol for internal dependencies in package.json files
Files:
packages/react-start-devtools/package.json
packages/start-devtools/package.json
packages/solid-start-devtools/package.json
examples/react/start-basic-react-query/package.json
package.json
**/src/routes/**
📄 CodeRabbit inference engine (AGENTS.md)
Place file-based routes under src/routes/ directories
Files:
examples/react/start-basic-react-query/src/routes/__root.tsx
🧠 Learnings (3)
📚 Learning: 2025-09-23T17:36:12.598Z
Learnt from: CR
PR: TanStack/router#0
File: AGENTS.md:0-0
Timestamp: 2025-09-23T17:36:12.598Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript in strict mode with extensive type safety across the codebase
Applied to files:
packages/solid-start-devtools/tsconfig.json
packages/solid-start-devtools/tsconfig.docs.json
packages/react-start-devtools/tsconfig.json
packages/start-devtools/tsconfig.json
📚 Learning: 2025-09-23T17:36:12.598Z
Learnt from: CR
PR: TanStack/router#0
File: AGENTS.md:0-0
Timestamp: 2025-09-23T17:36:12.598Z
Learning: Applies to packages/{react-router,solid-router}/** : Implement React and Solid bindings/components only in packages/react-router/ and packages/solid-router/
Applied to files:
examples/react/start-basic-react-query/src/routes/__root.tsx
📚 Learning: 2025-09-23T17:36:12.598Z
Learnt from: CR
PR: TanStack/router#0
File: AGENTS.md:0-0
Timestamp: 2025-09-23T17:36:12.598Z
Learning: Applies to **/package.json : Use workspace:* protocol for internal dependencies in package.json files
Applied to files:
package.json
🧬 Code graph analysis (13)
packages/solid-start-devtools/src/plugin.tsx (3)
packages/solid-start-devtools/src/index.ts (2)
startDevtoolsPlugin
(10-13)StartDevtoolsPanel
(5-8)packages/solid-start-devtools/src/production.ts (2)
startDevtoolsPlugin
(6-6)StartDevtoolsPanel
(2-2)packages/solid-start-devtools/src/SolidStartDevtools.tsx (1)
StartDevtoolsPanel
(10-10)
packages/react-start-devtools/src/ReactStartDevtools.tsx (4)
packages/react-start-devtools/src/index.ts (2)
StartDevtoolsReactInit
(16-16)StartDevtoolsPanel
(6-9)packages/react-start-devtools/src/production.ts (2)
StartDevtoolsReactInit
(5-5)StartDevtoolsPanel
(3-3)packages/start-devtools/src/core.tsx (1)
StartDevtoolsCore
(11-11)packages/start-devtools/src/index.ts (1)
StartDevtoolsCore
(5-8)
packages/start-devtools/vite.config.ts (1)
scripts/set-ts-version.js (1)
packageJson
(33-33)
packages/start-devtools/src/core.tsx (3)
examples/react/start-workos/src/authkit/ssr/utils.ts (1)
lazy
(8-18)packages/start-devtools/src/index.ts (2)
StartDevtoolsInit
(10-10)StartDevtoolsCore
(5-8)packages/start-devtools/src/production.ts (2)
StartDevtoolsInit
(5-5)StartDevtoolsCore
(3-3)
packages/solid-start-devtools/src/index.ts (1)
packages/react-start-devtools/src/index.ts (2)
StartDevtoolsPanel
(6-9)startDevtoolsPlugin
(11-14)
packages/react-start-devtools/src/index.ts (4)
packages/react-start-devtools/src/ReactStartDevtools.tsx (1)
StartDevtoolsPanel
(10-10)packages/react-start-devtools/src/production.ts (2)
StartDevtoolsPanel
(3-3)startDevtoolsPlugin
(7-7)packages/solid-start-devtools/src/index.ts (2)
StartDevtoolsPanel
(5-8)startDevtoolsPlugin
(10-13)packages/react-start-devtools/src/plugin.tsx (1)
startDevtoolsPlugin
(6-6)
packages/react-start-devtools/src/plugin.tsx (2)
packages/react-start-devtools/src/index.ts (2)
startDevtoolsPlugin
(11-14)StartDevtoolsPanel
(6-9)packages/react-start-devtools/src/production.ts (2)
startDevtoolsPlugin
(7-7)StartDevtoolsPanel
(3-3)
packages/solid-start-devtools/src/SolidStartDevtools.tsx (4)
packages/solid-start-devtools/src/index.ts (2)
StartDevtoolsPanel
(5-8)StartDevtoolsSolidInit
(15-15)packages/solid-start-devtools/src/production.ts (2)
StartDevtoolsPanel
(2-2)StartDevtoolsSolidInit
(4-4)packages/start-devtools/src/core.tsx (1)
StartDevtoolsCore
(11-11)packages/start-devtools/src/index.ts (1)
StartDevtoolsCore
(5-8)
examples/react/start-basic-react-query/src/routes/__root.tsx (3)
packages/react-router-devtools/src/TanStackRouterDevtoolsPanel.tsx (1)
TanStackRouterDevtoolsPanel
(37-87)packages/react-start-devtools/src/index.ts (1)
StartDevtoolsPanel
(6-9)packages/react-start-devtools/src/production.ts (1)
StartDevtoolsPanel
(3-3)
packages/react-start-devtools/vite.config.ts (1)
scripts/set-ts-version.js (1)
packageJson
(33-33)
packages/start-devtools/src/styles/use-styles.ts (1)
packages/start-devtools/src/styles/tokens.ts (1)
tokens
(1-305)
packages/start-devtools/src/index.ts (2)
packages/start-devtools/src/core.tsx (1)
StartDevtoolsCore
(11-11)packages/start-devtools/src/production.ts (1)
StartDevtoolsCore
(3-3)
packages/solid-start-devtools/vite.config.ts (1)
scripts/set-ts-version.js (1)
packageJson
(33-33)
🪛 Biome (2.1.2)
packages/start-devtools/src/core.tsx
[error] 7-7: An empty interface is equivalent to {}.
Safe fix: Use a type alias instead.
(lint/suspicious/noEmptyInterface)
🔇 Additional comments (29)
packages/start-devtools/CHANGELOG.md (1)
1-2
: LGTM! Minimal changelog header setup.The changelog follows standard convention with package scoping and is ready for future release entries.
packages/react-start-devtools/tests/test-setup.ts (1)
1-1
: LGTM! Standard Vitest test setup with jest-dom matchers.This enables additional DOM matchers for improved test assertions in the React devtools package.
packages/start-devtools/tests/test-setup.ts (1)
1-1
: LGTM! Standard Vitest test setup with jest-dom matchers.This enables additional DOM matchers for improved test assertions in the core devtools package.
packages/solid-start-devtools/tsconfig.docs.json (1)
1-4
: LGTM! Docs-specific TypeScript configuration follows standard pattern.The configuration properly extends the base tsconfig and constrains the documentation build to only include tests and source directories, which is consistent with similar configs in other packages.
packages/react-start-devtools/tsconfig.json (1)
1-7
: LGTM! React-specific TypeScript configuration follows standards.The configuration properly extends the root tsconfig, includes all necessary paths, and correctly sets JSX compilation to "react" for React components. This aligns with TypeScript strict mode requirements.
packages/solid-start-devtools/tsconfig.json (1)
1-8
: LGTM! SolidJS-specific TypeScript configuration is correctly configured.The configuration properly extends the root tsconfig, includes all necessary paths, and correctly sets JSX to "preserve" with "solid-js" as the import source, which is the standard approach for SolidJS projects. This aligns with TypeScript strict mode requirements.
packages/react-start-devtools/tsconfig.docs.json (1)
1-4
: LGTM! Docs-specific TypeScript configuration follows standard pattern.The configuration properly extends the base tsconfig and constrains the documentation build to only include tests and source directories, which is consistent with similar configs in other packages.
packages/solid-start-devtools/tests/test-setup.ts (1)
1-1
: LGTM: jest-dom matchers enabled for Vitest.Good addition. Aligns with jsdom environment in Vite config.
packages/solid-start-devtools/tests/index.test.ts (1)
1-7
: LGTM: baseline Vitest suite added.Foundational test in place; fine for initial scaffolding.
packages/solid-start-devtools/vite.config.ts (2)
6-16
: LGTM: Vite + Vitest config looks correct.Solid plugin, jsdom env, and setup file are wired properly; entries delegated to tanstackViteConfig.
4-4
: JSON imports are supported via tsconfig
resolveJsonModule
is set totrue
intsconfig.json
, so importingpackage.json
in the Vite config will work without further changes.packages/react-start-devtools/vite.config.ts (2)
6-16
: LGTM: Vite + Vitest config for React.React plugin plus jsdom and setup are set; tanstackViteConfig entries look good.
4-4
: JSON import handling confirmed:resolveJsonModule
is enabled in tsconfig.json and Vite supports JSON imports by default.packages/solid-start-devtools/src/SolidStartDevtools.tsx (1)
6-10
: LGTM: Solid panel wiring to StartDevtoolsCore.Panel/NoOp tuple and exported Init type look good and align with index/production fallbacks.
packages/start-devtools/tsconfig.docs.json (1)
1-4
: LGTM.Docs-specific tsconfig neatly scoped to src and tests.
packages/start-devtools/src/StartDevtools.tsx (1)
3-9
: Ensure JSX runtime matches tsconfig.With current tsconfig (solid-js), this TSX may mis-type. After fixing tsconfig to react-jsx, this file is fine; otherwise add
import React from 'react'
.packages/start-devtools/tests/index.test.ts (1)
1-7
: LGTM.Minimal sanity test establishes test harness.
packages/start-devtools/eslint.config.js (1)
3-10
: LGTM.Extends root config cleanly; override placeholder ready for local rules.
packages/start-devtools/tsconfig.json (1)
5-7
: Keep Solid JSX config
This package’s TSX imports fromsolid-js
, so"jsx": "preserve"
and"jsxImportSource": "solid-js"
are correct.Likely an incorrect or invalid review comment.
packages/react-start-devtools/src/plugin.tsx (1)
1-6
: React plugin wiring aligns with createReactPlugin expectationsTuple destructuring and re-export follow the utils contract; looks good.
packages/solid-start-devtools/src/index.ts (1)
2-15
: Solid entrypoint mirrors the React facade correctlyConditional exports cleanly swap between real and no-op implementations; no issues spotted.
packages/start-devtools/vite.config.ts (1)
1-25
: Vite config composition is consistent with the other packagesBase Vitest setup merged with
tanstackViteConfig
matches the house pattern; all good.packages/react-start-devtools/src/ReactStartDevtools.tsx (1)
2-10
: React panel wiring looks goodPanel factory and exported types line up with the shared core.
packages/start-devtools/src/styles/use-styles.ts (1)
1-364
: Theme-aware styles hook is thoroughReactive theme handling plus token usage is solid; no concerns here.
packages/start-devtools/src/styles/tokens.ts (1)
1-305
: Token palette definition is complete and ready for reuseStructured palette and sizing constants look consistent.
packages/react-start-devtools/eslint.config.js (1)
1-32
: ESLint config follows the repo’s flat-config conventionsPlugin wiring and rule overrides align with the rest of the workspace.
packages/solid-start-devtools/src/production.ts (1)
1-7
: LGTM – concise production surfaceRe-exports look correct for Solid’s production entry. No client directive is appropriate here.
packages/solid-start-devtools/eslint.config.js (1)
1-11
: LGTM – extends root ESLint with scoped overridesConfig correctly inherits root and allows local tweaks.
packages/react-start-devtools/src/production.ts (1)
1-8
: LGTM – production re-exports for ReactClient directive is appropriate for the React UI entry. Surface matches the index/types.
export interface StartDevtoolsInit { } | ||
|
||
const [StartDevtoolsCore, StartDevtoolsCoreNoOp] = constructCoreClass(Component) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Replace empty interface with a type alias to satisfy lint
Biome flags the empty interface
as an error. Switching to a type alias keeps the surface the same while letting the lint pass.
-export interface StartDevtoolsInit { }
+export type StartDevtoolsInit = Record<string, never>
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
export interface StartDevtoolsInit { } | |
const [StartDevtoolsCore, StartDevtoolsCoreNoOp] = constructCoreClass(Component) | |
export type StartDevtoolsInit = Record<string, never> | |
const [StartDevtoolsCore, StartDevtoolsCoreNoOp] = constructCoreClass(Component) |
🧰 Tools
🪛 Biome (2.1.2)
[error] 7-7: An empty interface is equivalent to {}.
Safe fix: Use a type alias instead.
(lint/suspicious/noEmptyInterface)
🤖 Prompt for AI Agents
In packages/start-devtools/src/core.tsx around lines 7 to 9, the empty exported
interface StartDevtoolsInit should be replaced with an exported type alias to
satisfy the linter; change the declaration from an empty interface to a type
alias with the same empty object shape and keep the rest of the file (including
the ConstructCoreClass call and exports) unchanged.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
…into feat/devtools
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (4)
package.json
(3 hunks)packages/react-start-devtools/package.json
(1 hunks)packages/solid-start-devtools/package.json
(1 hunks)packages/start-devtools/package.json
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/react-start-devtools/package.json
- package.json
🧰 Additional context used
📓 Path-based instructions (2)
**/package.json
📄 CodeRabbit inference engine (AGENTS.md)
Use workspace:* protocol for internal dependencies in package.json files
Files:
packages/solid-start-devtools/package.json
packages/start-devtools/package.json
packages/{*-start,start-*}/**
📄 CodeRabbit inference engine (AGENTS.md)
Name and place Start framework packages under packages/-start/ or packages/start-/
Files:
packages/start-devtools/package.json
"@tanstack/devtools-utils": "^0.0.3", | ||
"@tanstack/start-devtools": "workspace:*" | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Use workspace protocol for internal utils dependency.
@tanstack/devtools-utils
is an in-repo package, so it needs the workspace:*
specifier to keep local builds in sync and honor the monorepo policy.
- "@tanstack/devtools-utils": "^0.0.3",
+ "@tanstack/devtools-utils": "workspace:*",
As per coding guidelines
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
"@tanstack/devtools-utils": "^0.0.3", | |
"@tanstack/start-devtools": "workspace:*" | |
}, | |
"@tanstack/devtools-utils": "workspace:*", | |
"@tanstack/start-devtools": "workspace:*" | |
}, |
🤖 Prompt for AI Agents
In packages/solid-start-devtools/package.json around lines 58 to 60, the
dependency "@tanstack/devtools-utils" is pinned to a version string instead of
using the workspace protocol; change its specifier to "workspace:*" (same as
"@tanstack/start-devtools") so the local in-repo package is referenced via
workspace and local builds remain in sync with monorepo policy.
"dependencies": { | ||
"@tanstack/devtools-ui": "^0.3.4", | ||
"@tanstack/devtools-utils": "^0.0.3", | ||
"@tanstack/solid-store": "^0.7.5", | ||
"clsx": "^2.1.1", | ||
"dayjs": "^1.11.18", | ||
"goober": "^2.1.16", | ||
"solid-js": "^1.9.9" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Switch internal TanStack deps to workspace:*
.
Per repo guidelines, internal packages should be linked via workspace:*
. Leaving the caret ranges will resolve against the registry instead of local workspaces, breaking monorepo dev workflows and risking version skew during publishing. Please flip the internal TanStack dependencies to workspace links.
- "@tanstack/devtools-ui": "^0.3.4",
- "@tanstack/devtools-utils": "^0.0.3",
- "@tanstack/solid-store": "^0.7.5",
+ "@tanstack/devtools-ui": "workspace:*",
+ "@tanstack/devtools-utils": "workspace:*",
+ "@tanstack/solid-store": "workspace:*",
As per coding guidelines
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
"dependencies": { | |
"@tanstack/devtools-ui": "^0.3.4", | |
"@tanstack/devtools-utils": "^0.0.3", | |
"@tanstack/solid-store": "^0.7.5", | |
"clsx": "^2.1.1", | |
"dayjs": "^1.11.18", | |
"goober": "^2.1.16", | |
"solid-js": "^1.9.9" | |
"dependencies": { | |
"@tanstack/devtools-ui": "workspace:*", | |
"@tanstack/devtools-utils": "workspace:*", | |
"@tanstack/solid-store": "workspace:*", | |
"clsx": "^2.1.1", | |
"dayjs": "^1.11.18", | |
"goober": "^2.1.16", | |
"solid-js": "^1.9.9" |
🤖 Prompt for AI Agents
In packages/start-devtools/package.json around lines 57 to 64, the internal
TanStack dependencies are using caret ranges which will resolve from the
registry instead of local workspaces; change the internal @tanstack packages
(@tanstack/devtools-ui, @tanstack/devtools-utils, @tanstack/solid-store) to use
"workspace:*" as their version specifier so they resolve to local workspace
packages during monorepo development and publishing; keep external deps (clsx,
dayjs, goober, solid-js) unchanged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (7)
examples/react/start-basic-react-query/src/routes/__root.tsx (1)
141-157
: Gate DevTools (and server bus) to dev only to avoid prod bloat/network attempts.Render the DevTools only in development and guard the server bus connection. This prevents unnecessary code in production bundles and avoids stray connections.
Apply this diff:
- <TanStackDevtools eventBusConfig={{ - connectToServerBus: true - }} plugins={[ + {import.meta.env.DEV && ( + <TanStackDevtools + eventBusConfig={{ connectToServerBus: import.meta.env.DEV }} + plugins={[ { name: 'React Query', render: () => <ReactQueryDevtoolsPanel /> }, { name: 'React Router', render: () => <TanStackRouterDevtoolsPanel /> }, { name: "TanStack Start", render: () => <StartDevtoolsPanel /> } - ]} /> + ]} + /> + )}packages/start-server-core/src/createStartHandler.ts (1)
405-406
: Type hole increateHandlers
identity.Consider a generic signature to preserve handler types instead of
any
, e.g.,createHandlers<T>(d: T): T
.packages/start-server-core/src/event-client.ts (2)
13-20
: Expose types for consumers.Exporting the class (and map) improves DX for typed consumers.
-class StartEventClient extends EventClient<StartEventMap> { +export class StartEventClient extends EventClient<StartEventMap> {Optionally:
-interface StartEventMap { +export interface StartEventMap {
22-24
: Export the singleton directly.Slightly cleaner and tree-shakeable:
-const startEventClient = new StartEventClient() - -export { startEventClient } +export const startEventClient = new StartEventClient()packages/start-devtools/src/StartDevtools.tsx (3)
44-45
: Render plain header data to JsonTree.
Headers
isn’t JSON-serializable; show a plain object.- <JsonTree value={req.headers} /> + <JsonTree value={Object.fromEntries(req.headers.entries())} />
24-27
: Optional: cap list length to avoid unbounded growth.Consider keeping only the last N (e.g., 200) requests for long dev sessions.
16-19
: Nit: stray spaces in color hex.Remove trailing spaces to avoid accidental diffs.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (9)
examples/react/start-basic-react-query/src/routes/__root.tsx
(2 hunks)packages/start-devtools/package.json
(1 hunks)packages/start-devtools/src/StartDevtools.tsx
(1 hunks)packages/start-plugin-core/src/start-compiler-plugin/plugin.ts
(2 hunks)packages/start-server-core/package.json
(3 hunks)packages/start-server-core/src/createStartHandler.ts
(3 hunks)packages/start-server-core/src/event-client.ts
(1 hunks)packages/start-server-core/src/index.tsx
(1 hunks)packages/start-server-core/vite.config.ts
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- packages/start-server-core/src/index.tsx
🧰 Additional context used
📓 Path-based instructions (5)
**/package.json
📄 CodeRabbit inference engine (AGENTS.md)
Use workspace:* protocol for internal dependencies in package.json files
Files:
packages/start-server-core/package.json
packages/start-devtools/package.json
packages/{*-start,start-*}/**
📄 CodeRabbit inference engine (AGENTS.md)
Name and place Start framework packages under packages/-start/ or packages/start-/
Files:
packages/start-server-core/package.json
packages/start-server-core/src/createStartHandler.ts
packages/start-devtools/src/StartDevtools.tsx
packages/start-plugin-core/src/start-compiler-plugin/plugin.ts
packages/start-server-core/vite.config.ts
packages/start-server-core/src/event-client.ts
packages/start-devtools/package.json
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript in strict mode with extensive type safety across the codebase
Files:
packages/start-server-core/src/createStartHandler.ts
packages/start-devtools/src/StartDevtools.tsx
packages/start-plugin-core/src/start-compiler-plugin/plugin.ts
examples/react/start-basic-react-query/src/routes/__root.tsx
packages/start-server-core/vite.config.ts
packages/start-server-core/src/event-client.ts
**/src/routes/**
📄 CodeRabbit inference engine (AGENTS.md)
Place file-based routes under src/routes/ directories
Files:
examples/react/start-basic-react-query/src/routes/__root.tsx
examples/{react,solid}/**
📄 CodeRabbit inference engine (AGENTS.md)
Keep example applications under examples/react/ and examples/solid/
Files:
examples/react/start-basic-react-query/src/routes/__root.tsx
🧠 Learnings (1)
📚 Learning: 2025-09-23T17:36:12.598Z
Learnt from: CR
PR: TanStack/router#0
File: AGENTS.md:0-0
Timestamp: 2025-09-23T17:36:12.598Z
Learning: Applies to **/package.json : Use workspace:* protocol for internal dependencies in package.json files
Applied to files:
packages/start-devtools/package.json
🧬 Code graph analysis (3)
packages/start-server-core/src/createStartHandler.ts (1)
packages/start-server-core/src/event-client.ts (1)
startEventClient
(24-24)
packages/start-devtools/src/StartDevtools.tsx (1)
packages/start-server-core/src/event-client.ts (1)
startEventClient
(24-24)
examples/react/start-basic-react-query/src/routes/__root.tsx (2)
packages/react-router-devtools/src/TanStackRouterDevtoolsPanel.tsx (1)
TanStackRouterDevtoolsPanel
(37-87)packages/react-start-devtools/src/index.ts (1)
StartDevtoolsPanel
(6-9)
🔇 Additional comments (10)
packages/start-devtools/package.json (1)
57-65
: Switch internal TanStack deps toworkspace:*
.Per repo guidance, these local packages must resolve via the workspace protocol; keeping caret ranges pulls them from the registry and breaks monorepo linking. Please flip them to
workspace:*
.- "@tanstack/devtools-ui": "^0.3.5", - "@tanstack/devtools-utils": "^0.0.3", - "@tanstack/solid-store": "^0.7.5", + "@tanstack/devtools-ui": "workspace:*", + "@tanstack/devtools-utils": "workspace:*", + "@tanstack/solid-store": "workspace:*",As per coding guidelines.
examples/react/start-basic-react-query/src/routes/__root.tsx (2)
9-13
: Correct devtools panel imports; resolves prior mis‑wiring.React Query and Router panel imports look correct and align with the unified devtools panel usage.
144-151
: React Query plugin now renders the correct panel.The “React Query” entry now maps to ReactQueryDevtoolsPanel (and Router to TanStackRouterDevtoolsPanel) — fixes the previously reported duplication.
packages/start-server-core/vite.config.ts (1)
21-21
: Confirmentry
supports string[].Looks good logically. Please verify
tanstackViteConfig
accepts an array forentry
and outputsdist/esm/event-client.{js,d.ts}
to match the new export.packages/start-server-core/package.json (2)
50-55
: Export subpath LGTM; ensure artifacts are emitted.The new
./event-client
export is correct. Ensure the build emitsdist/esm/event-client.js
andevent-client.d.ts
soattw
/publint
pass.
67-67
: External dependency – keep semver
No internal package named@tanstack/devtools-event-client
was found in this monorepo; retain the existing semver range.packages/start-server-core/src/createStartHandler.ts (2)
22-22
: Import is fine.No issues with the new import.
112-112
: Minor style change acknowledged.No behavioral change here.
packages/start-server-core/src/event-client.ts (1)
3-11
: Event keys are namespaced; keep consistent across emitters/consumers.This map looks good. Ensure all
emit
/on
calls use"start:request-received"
(see other comments).packages/start-devtools/src/StartDevtools.tsx (1)
10-10
: Duplicate: event name mismatch noted elsewhere.See createStartHandler comment; both emitter and listener must use the same namespaced key.
startEventClient.on("request-received", (e) => { | ||
setRequests((r) => [...r, e.payload]) | ||
}) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix subscription leak and align event name.
Unsubscribe on unmount and listen to the namespaced key.
- createEffect(() => {
- startEventClient.on("request-received", (e) => {
- setRequests((r) => [...r, e.payload])
- })
- })
+ createEffect(() => {
+ const off = startEventClient.on('start:request-received', (e) => {
+ setRequests((r) => [...r, e.payload])
+ })
+ onCleanup(() => off?.())
+ })
Also add onCleanup import:
-import { For, createEffect, createSignal, } from "solid-js"
+import { For, createEffect, createSignal, onCleanup } from "solid-js"
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
startEventClient.on("request-received", (e) => { | |
setRequests((r) => [...r, e.payload]) | |
}) | |
}) | |
// packages/start-devtools/src/StartDevtools.tsx | |
import { For, createEffect, createSignal, onCleanup } from "solid-js" | |
// … other imports and code … | |
createEffect(() => { | |
- startEventClient.on("request-received", (e) => { | |
- setRequests((r) => [...r, e.payload]) | |
- }) | |
const off = startEventClient.on('start:request-received', (e) => { | |
setRequests((r) => [...r, e.payload]) | |
}) | |
onCleanup(() => off?.()) | |
}) |
🤖 Prompt for AI Agents
In packages/start-devtools/src/StartDevtools.tsx around lines 9 to 12, the event
handler is registered but never unsubscribed and uses the non-namespaced event
name; update the listener to subscribe to the namespaced key (e.g.
"request-received:devtools") instead of "request-received", capture the
unsubscribe/cleanup function returned by startEventClient.on, call that
unsubscribe in a Solid onCleanup callback, and add an import for onCleanup from
'solid-js' at the top of the file.
const expectedLocation = packageName + '/package.json' | ||
try { | ||
const pkgRoot = path.dirname(require.resolve(expectedLocation)) | ||
return pkgRoot | ||
// eslint-disable-next-line unused-imports/no-unused-vars | ||
} catch (_error) { | ||
const pkgRoot = path.dirname(expectedLocation) | ||
return pkgRoot | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not swallow resolution failures; we now return an unusable package root.
When require.resolve(packageName + '/package.json')
fails, the new fallback path.dirname(expectedLocation)
just gives back the bare specifier (e.g. @tanstack/start-client-core
). resolveRuntimeFiles
then produces entries such as @tanstack/start-client-core/dist/esm/index.js
, which are not the absolute module IDs Vite hands to this plugin. As soon as a package hides package.json
behind exports
, the exclude filter stops matching, so we start transforming those runtime files again and break the build. Please restore an absolute root discovery step—e.g. resolve the package’s entry file and walk up the filesystem until you hit a real package.json
, or rethrow the original error so the caller can fail fast.
You can fix it along these lines:
+import { existsSync } from 'node:fs'
+
function resolvePackage(packageName: string): string {
const expectedLocation = packageName + '/package.json'
try {
const pkgRoot = path.dirname(require.resolve(expectedLocation))
return pkgRoot
// eslint-disable-next-line unused-imports/no-unused-vars
} catch (_error) {
- const pkgRoot = path.dirname(expectedLocation)
- return pkgRoot
+ let entryPath: string
+ try {
+ entryPath = require.resolve(packageName)
+ } catch {
+ throw _error
+ }
+
+ let dir = path.dirname(entryPath)
+ while (true) {
+ if (existsSync(path.join(dir, 'package.json'))) {
+ return dir
+ }
+ const parent = path.dirname(dir)
+ if (parent === dir) {
+ break
+ }
+ dir = parent
+ }
+ throw _error
}
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const expectedLocation = packageName + '/package.json' | |
try { | |
const pkgRoot = path.dirname(require.resolve(expectedLocation)) | |
return pkgRoot | |
// eslint-disable-next-line unused-imports/no-unused-vars | |
} catch (_error) { | |
const pkgRoot = path.dirname(expectedLocation) | |
return pkgRoot | |
} | |
// at the top of the file (alongside your other imports) | |
import { existsSync } from 'node:fs' | |
function resolvePackage(packageName: string): string { | |
const expectedLocation = packageName + '/package.json' | |
try { | |
const pkgRoot = path.dirname(require.resolve(expectedLocation)) | |
return pkgRoot | |
// eslint-disable-next-line unused-imports/no-unused-vars | |
} catch (_error) { | |
let entryPath: string | |
try { | |
entryPath = require.resolve(packageName) | |
} catch { | |
throw _error | |
} | |
let dir = path.dirname(entryPath) | |
while (true) { | |
if (existsSync(path.join(dir, 'package.json'))) { | |
return dir | |
} | |
const parent = path.dirname(dir) | |
if (parent === dir) { | |
break | |
} | |
dir = parent | |
} | |
throw _error | |
} | |
} |
🤖 Prompt for AI Agents
In packages/start-plugin-core/src/start-compiler-plugin/plugin.ts around lines
35 to 43, the catch block swallows require.resolve failures and returns a
non-absolute fallback (path.dirname(expectedLocation)), producing unusable
package roots; instead, either rethrow the original error so the caller fails
fast, or perform a real resolution: resolve the package’s entry
(require.resolve(packageName) or require.resolve(packageName + '/'), then walk
up directories from that resolved path looking for a real package.json
(fs.existsSync) and return that directory; implement one of these two approaches
and remove the current bare-specifier fallback.
startEventClient.emit("request-received", { | ||
headers: request.headers, | ||
url: request.url.split("--")[0]!, | ||
method: request.method | ||
|
||
}) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Event name mismatch breaks listeners.
emit("request-received", ...)
does not match StartEventMap’s "start:request-received"
key and the UI is listening to "request-received"
. Align all three to the namespaced event key to avoid silent no-ops. Also avoid ad-hoc URL splitting.
Apply:
- startEventClient.emit("request-received", {
+ startEventClient.emit('start:request-received', {
headers: request.headers,
- url: request.url.split("--")[0]!,
+ url: request.url,
method: request.method
-
})
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
startEventClient.emit("request-received", { | |
headers: request.headers, | |
url: request.url.split("--")[0]!, | |
method: request.method | |
}) | |
startEventClient.emit('start:request-received', { | |
headers: request.headers, | |
url: request.url, | |
method: request.method | |
}) |
🤖 Prompt for AI Agents
In packages/start-server-core/src/createStartHandler.ts around lines 98 to 104,
change the emitted event name from "request-received" to the namespaced key
"start:request-received" (and update any UI/listener code and StartEventMap
entries to use that same namespaced key) so listeners are not silently skipped;
also replace the ad-hoc request.url.split("--")[0]! with a robust parse (e.g.
construct a URL with a safe base and use url.pathname + url.search or otherwise
extract the normalized path without using split) to avoid brittle string
manipulation and potential runtime errors.
@@ -0,0 +1,70 @@ | |||
{ | |||
"name": "@tanstack/start-devtools", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding this here, but doesn't need to be acted upon until merging.
To match the router devtools core package (and there other repo-packages in general), could we name this start-devtools-core
?
Summary by CodeRabbit
New Features
Chores
Tests
Documentation