name: performance-review description: Review frontend code changes for performance anti-patterns and guideline compliance. Checks query hooks, stale times, bundle impact, rendering patterns, and Zustand selectors. user_invocable: true
Frontend Performance Review
Reference: frontend/docs/performance.md
When to Invoke
- Before submitting a PR that adds or modifies query hooks, page components, Zustand stores, or real-time features
- When the user asks for a "performance review" or "perf check"
- As part of the component-development workflow for new pages
Agent Instructions
When invoked, perform the following checks in order. Report PASS/FAIL/WARN for each. Group failures by severity: CRITICAL (must fix before merge), WARNING (should fix), INFO (consider).
Step 1: Identify Scope
Read the diff or the files specified by the user. If no files specified, use git diff --name-only to find changed frontend files. Identify which categories apply: query hooks, page routes, stores, real-time, bundle.
Step 2: Query Hook Checks
- Search for
useState+useEffect+api.within 20 lines of each other in changed files. If found: CRITICAL — should be a TanStack Query hook. - Check that new
useQuerycalls reference a key fromqueryKeys.ts, not an inline array. If inline: CRITICAL. - Check that new query hook files are named
use<Domain>Queries.tsand placed insrc/hooks/queries/. If misplaced: WARNING. - Check that
useMutationcalls includeonSuccesswithqueryClient.invalidateQueries(). If missing: WARNING. - Check for
skipTokenusage on conditional queries vs.enabled: false. Flagenabled: falsewithoutskipTokenas WARNING.
Step 3: Stale Time Audit
- For each new
useQuery, check ifstaleTimeis set explicitly or inherits the 30s default appropriately. - Cross-reference the data type: if the query fetches components, templates, or providers — flag missing
staleTime: Infinityas CRITICAL. - For execution queries, verify they use
executionQueryOptions.tsfactories rather than inline values. Flag inconsistency as WARNING. - For queries on terminal runs, verify
terminalStaleTime()is used rather than a hardcoded number.
Step 4: Bundle Impact
- For each new page added to
App.tsx: verify it usesReact.lazy(() => import(...)). Static imports are CRITICAL. - Verify new sidebar pages are added to
routePrefetchMapinsrc/lib/prefetch-routes.ts. Missing entry is WARNING. - If a new conditionally-visible component imports a library > 100KB (check for
@xterm,posthog-js,lucide-reactbarrel imports): flag as WARNING — consider deferred load pattern.
Step 5: Rendering Checks
- Search for
const [*, set*] = useStatefollowed byset*inside auseEffectthat references query data — CRITICAL (should useuseMemo). - Look for derived data calculations inline in JSX without
useMemoinvolving array operations (filter, sort, reduce) — WARNING. - Check for
React.memousage on new components intimeline/orworkflow/directories that re-render frequently — INFO if missing.
Step 6: Zustand Store Checks
- Search for
const store = use<X>Store()or destructuring fromuse<X>Store()without a selector — full store subscription. WARNING. - For new stores using
persist, verifypartializeis present. Missing is WARNING. - For new
persiststores, verify action functions are excluded frompartialize.
Step 7: Generate Report
Format the output as follows:
## Performance Review: [description of scope]
### Critical (must fix before merge)
- [file:line] Description of issue. See: performance.md § [section]
### Warnings (should fix)
- [file:line] Description of issue. See: performance.md § [section]
### Info (consider)
- [file:line] Description. See: performance.md § [section]
### Passed Checks
- [n] query hooks using TanStack Query correctly
- [n] page routes using React.lazy
- [n] Zustand selectors properly scoped
- staleTime: appropriate tiers applied
### Summary
[1-2 sentences on overall performance hygiene of the change]
Rules
- This is a review only — do NOT make code changes unless the user explicitly asks
- Always cite the file and line number for each finding
- Always reference
frontend/docs/performance.mdfor the relevant pattern section - If no frontend files are in the diff, report "No frontend changes detected" and exit