-
Notifications
You must be signed in to change notification settings - Fork 813
Tanstack Devtools in web #1049
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
Tanstack Devtools in web #1049
Conversation
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughAdds a feature flag store for Layout persisted in localStorage, introduces hooks to read flags, updates ProgressCircle to use a flag for upload progress, integrates TanStack React Query Devtools and a custom CapDevtools panel in development, and updates TanStack-related dependencies in apps/web. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Dev as Developer (Dev)
participant UI as CapDevtools (UI)
participant FF as featureFlags Store
participant LS as localStorage
participant PC as ProgressCircle
rect rgb(245,248,255)
note over UI,FF: Feature flag toggle flow (new)
Dev->>UI: Toggle "enableUploadProgress"
UI-->>FF: update(flag=true/false)
FF-->>LS: Persist JSON under "featureFlags"
end
rect rgb(245,255,245)
note over PC,FF: Flag consumption
PC->>FF: useFeatureFlag("enableUploadProgress")
FF-->>PC: current boolean value
PC->>PC: Enable/disable upload progress query
end
sequenceDiagram
autonumber
participant App as React App
participant Prov as ReactQueryProvider
participant DevT as Devtools (TanStack/Cap)
participant ENV as NODE_ENV
App->>Prov: Mount provider
Prov->>ENV: Check if development
alt development
Prov-->>DevT: Render Devtools UI (React Query + CapDevtools)
else production
Prov-->>Prov: Skip Devtools
end
Prov-->>App: Render children
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
Pre-merge checks and finishing touches✅ Passed checks (3 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: 1
🧹 Nitpick comments (6)
apps/web/package.json (1)
61-64
: Avoid shipping DevTools in production bundles.These deps are dev-only. Either move them to
devDependencies
or dynamically import them in code so they're excluded from prod bundles. The code currently imports them at module scope in a client provider, which risks bundling in prod.Do you prefer moving to
devDependencies
, or keeping independencies
but loading vianext/dynamic
withssr: false
? The latter keeps the runtime path clean in dev while ensuring no prod bundle impact.apps/web/app/Layout/providers.tsx (2)
66-70
: Gate is good; but devtools still get bundled. Dynamically import to keep prod bundles lean.Even behind
NODE_ENV === "development"
, static imports can end up in prod bundles. Usenext/dynamic
withssr: false
and remove top-level DevTools imports.Apply these diffs:
-import { TanStackDevtools } from "@tanstack/react-devtools"; -import { - QueryClient, - QueryClientProvider, - useQueryClient, -} from "@tanstack/react-query"; -import { ReactQueryDevtoolsPanel } from "@tanstack/react-query-devtools"; +import dynamic from "next/dynamic"; +import { + QueryClient, + QueryClientProvider, + useQueryClient, +} from "@tanstack/react-query";And update the Devtools component:
export function Devtools() { const client = useQueryClient(); return ( - <TanStackDevtools + {(() => { + const TanStackDevtools = dynamic( + () => import("@tanstack/react-devtools").then((m) => m.TanStackDevtools), + { ssr: false }, + ); + const ReactQueryDevtoolsPanel = dynamic( + () => + import("@tanstack/react-query-devtools").then( + (m) => m.ReactQueryDevtoolsPanel, + ), + { ssr: false }, + ); + return ( + <TanStackDevtools config={{ - // TODO: This doesn't seem to be working? position: "top-left", }} plugins={[ { name: "Cap", render: <CapDevtools />, }, { name: "Tanstack Query", - render: <ReactQueryDevtoolsPanel client={client} />, + render: <ReactQueryDevtoolsPanel client={client} />, }, ]} - /> + /> + ); + })()} ); }
85-88
: Remove inline TODO per repo guidelines (no inline comments).Apply this diff:
- config={{ - // TODO: This doesn't seem to be working? - position: "top-left", - }} + config={{ position: "top-left" }}apps/web/app/s/[videoId]/_components/ProgressCircle.tsx (1)
60-64
: Clamp computed progress to [0, 100] to avoid overshoot/NaN edge cases.When
uploaded > total
, the arc can exceed 100%. Clamp to keep SVG rendering stable.Apply this diff:
- : (query.data.uploaded / query.data.total) * 100, + : Math.max( + 0, + Math.min(100, (query.data.uploaded / query.data.total) * 100), + ),apps/web/app/Layout/features.ts (2)
23-30
: Guard localStorage side-effect for SSR.Mounting this effect during SSR will throw since
localStorage
isn’t defined. Wrap in a window check.Apply this diff:
-new Effect({ - fn: () => - localStorage.setItem( - featureFlagsLocalStorageKey, - JSON.stringify(featureFlags.state), - ), - deps: [featureFlags], -}).mount(); +if (typeof window !== "undefined") { + new Effect({ + fn: () => + localStorage.setItem( + featureFlagsLocalStorageKey, + JSON.stringify(featureFlags.state), + ), + deps: [featureFlags], + }).mount(); +}
9-15
: Type the localStorage helper to the flags shape.Avoids implicit
any
and improves call-site inference.Apply this diff:
-function safeJsonFromLocalStorage(key: string) { +function safeJsonFromLocalStorage( + key: string, +): Partial<FeatureFlags> { try { - return JSON.parse(localStorage.getItem(key) || "{}"); + return JSON.parse(localStorage.getItem(key) || "{}") as Partial<FeatureFlags>; } catch { - return {}; + return {}; } }
📜 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 (5)
apps/web/app/Layout/features.ts
(1 hunks)apps/web/app/Layout/providers.tsx
(2 hunks)apps/web/app/layout.tsx
(1 hunks)apps/web/app/s/[videoId]/_components/ProgressCircle.tsx
(2 hunks)apps/web/package.json
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/**/*.{ts,tsx}
: Use TanStack Query v5 for all client-side server state and data fetching in the web app
Web mutations should call Server Actions directly and perform targeted cache updates with setQueryData/setQueriesData rather than broad invalidations
Client code should use useEffectQuery/useEffectMutation and useRpcClient from apps/web/lib/EffectRuntime.ts; do not create ManagedRuntime inside components
Files:
apps/web/app/Layout/providers.tsx
apps/web/app/Layout/features.ts
apps/web/app/layout.tsx
apps/web/app/s/[videoId]/_components/ProgressCircle.tsx
apps/web/app/**/*.{tsx,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
Prefer Server Components for initial data in the Next.js App Router and pass initialData to client components
Files:
apps/web/app/Layout/providers.tsx
apps/web/app/Layout/features.ts
apps/web/app/layout.tsx
apps/web/app/s/[videoId]/_components/ProgressCircle.tsx
**/*.{ts,tsx,js,jsx,rs}
📄 CodeRabbit inference engine (CLAUDE.md)
Do not add inline, block, or docstring comments in any language; code must be self-explanatory
Files:
apps/web/app/Layout/providers.tsx
apps/web/app/Layout/features.ts
apps/web/app/layout.tsx
apps/web/app/s/[videoId]/_components/ProgressCircle.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use strict TypeScript and avoid any; leverage shared types from packages
**/*.{ts,tsx}
: Use a 2-space indent for TypeScript code.
Use Biome for formatting and linting TypeScript/JavaScript files by runningpnpm format
.
Files:
apps/web/app/Layout/providers.tsx
apps/web/app/Layout/features.ts
apps/web/app/layout.tsx
apps/web/app/s/[videoId]/_components/ProgressCircle.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}
: Use kebab-case for filenames for TypeScript/JavaScript modules (e.g.,user-menu.tsx
).
Use PascalCase for React/Solid components.
Files:
apps/web/app/Layout/providers.tsx
apps/web/app/Layout/features.ts
apps/web/app/layout.tsx
apps/web/app/s/[videoId]/_components/ProgressCircle.tsx
apps/web/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
On the client, always use
useEffectQuery
oruseEffectMutation
from@/lib/EffectRuntime
; never callEffectRuntime.run*
directly in components.
Files:
apps/web/app/Layout/providers.tsx
apps/web/app/Layout/features.ts
apps/web/app/layout.tsx
apps/web/app/s/[videoId]/_components/ProgressCircle.tsx
🧠 Learnings (3)
📚 Learning: 2025-09-22T14:17:47.380Z
Learnt from: CR
PR: CapSoftware/Cap#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-22T14:17:47.380Z
Learning: Applies to apps/web/**/*.{ts,tsx} : Use TanStack Query v5 for all client-side server state and data fetching in the web app
Applied to files:
apps/web/app/Layout/providers.tsx
apps/web/app/layout.tsx
apps/web/package.json
📚 Learning: 2025-09-22T14:17:47.380Z
Learnt from: CR
PR: CapSoftware/Cap#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-22T14:17:47.380Z
Learning: Applies to apps/desktop/**/*.{ts,tsx} : In the desktop app, use tanstack/solid-query for server state management
Applied to files:
apps/web/app/layout.tsx
📚 Learning: 2025-09-22T14:17:47.380Z
Learnt from: CR
PR: CapSoftware/Cap#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-22T14:17:47.380Z
Learning: Applies to apps/web/**/*.{ts,tsx} : Client code should use useEffectQuery/useEffectMutation and useRpcClient from apps/web/lib/EffectRuntime.ts; do not create ManagedRuntime inside components
Applied to files:
apps/web/app/s/[videoId]/_components/ProgressCircle.tsx
🧬 Code graph analysis (2)
apps/web/app/Layout/providers.tsx (1)
apps/web/app/Layout/features.ts (2)
useFeatureFlags
(36-38)featureFlags
(18-21)
apps/web/app/s/[videoId]/_components/ProgressCircle.tsx (1)
apps/web/app/Layout/features.ts (1)
useFeatureFlag
(32-34)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
- GitHub Check: Build Desktop (aarch64-apple-darwin, macos-latest)
- GitHub Check: Analyze (rust)
🔇 Additional comments (2)
apps/web/app/s/[videoId]/_components/ProgressCircle.tsx (1)
27-29
: LGTM: Feature flag gating is clean and localized.This switch simplifies rollout and aligns with the new flags store.
apps/web/app/Layout/providers.tsx (1)
96-97
: No change needed — prop isclient
.
ReactQueryDevtoolsPanel v5 expects the propclient
(notqueryClient
); keep the current code as-is.
This allows accessing React Query Devtools, toggling feature flags and more.
In the future will do a PR to add an easy utility for toggling Cap pro on a user as that will make testing different flows wayyyy easier.
Summary by CodeRabbit
New Features
Chores