-
-
Notifications
You must be signed in to change notification settings - Fork 104
feat(examples): add AI-powered search example #114
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
082c6b8 to
e2283a1
Compare
|
View your CI Pipeline Execution ↗ for commit c176553
☁️ Nx Cloud last updated this comment at |
@tanstack/ai
@tanstack/ai-anthropic
@tanstack/ai-client
@tanstack/ai-devtools-core
@tanstack/ai-gemini
@tanstack/ai-grok
@tanstack/ai-ollama
@tanstack/ai-openai
@tanstack/ai-preact
@tanstack/ai-react
@tanstack/ai-react-ui
@tanstack/ai-solid
@tanstack/ai-solid-ui
@tanstack/ai-svelte
@tanstack/ai-vue
@tanstack/ai-vue-ui
@tanstack/preact-ai-devtools
@tanstack/react-ai-devtools
@tanstack/solid-ai-devtools
commit: |
|
We should hold on this example until we have a structured output generation function. |
0f0e7e5 to
200e184
Compare
200e184 to
720ebf6
Compare
📝 WalkthroughWalkthroughAdds a new TypeScript React example project (ts-react-search) with UI primitives, routing and generated route tree, API endpoints (including an AI-backed /api/search), domain data/collections for orders/disputes/settlements, client hooks (speech, search mutation), utilities, and project/tooling configs. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant Browser as Client (SearchForm)
participant API as /api/search (Server)
participant OpenAI as OpenAI
participant Router as TanStack Router
participant Page as Domain Page (Manager)
User->>Browser: type / choose prompt / speak
Browser->>API: POST /api/search { content }
API->>OpenAI: Chat completion request (SYSTEM_PROMPT + input)
OpenAI-->>API: Structured JSON response (domain + params)
API-->>Browser: Return structured result
Browser->>Router: navigate to /{domain}?params
Router->>Page: initialize page with validated search
Page->>Page: useLiveQuery -> collection filters
Page-->>User: render filtered table
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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: 19
🧹 Nitpick comments (17)
examples/ts-react-search/src/components/ui/README.md (1)
1-7: Clear and concise documentation.The README accurately describes the shadcn/ui setup and provides the correct installation command. Documentation is appropriate for an example project.
Optional enhancement: Consider listing which shadcn/ui components are already installed in this example (e.g., Button, Calendar, DatePicker, Label, Popover, Select, Table) to help developers understand what's available without needing to explore the directory. This would make the documentation even more discoverable.
examples/ts-react-search/public/manifest.json (1)
1-25: Icon files are present but empty.The manifest references
favicon.ico,logo192.png, andlogo512.png—these files exist in thepublic/directory. However, they are all 0-byte placeholder files. While this won't prevent the example from running, the PWA will fail to display icons correctly. For a complete example, populate these files with actual images or remove the references from the manifest.examples/ts-react-search/src/components/HeroSection/Search/QuickPrompts.tsx (2)
1-1: Remove unnecessary 'use client' directive.The
'use client'directive is specific to React Server Components (Next.js App Router). In a Vite-based application, this directive has no effect and may cause confusion.🔎 Proposed fix
-'use client' - const PROMPTS = [
21-23: Consider simplifying the click handler.The
makePromptClickHandlerwrapper can be replaced with an inline arrow function for cleaner code.🔎 Proposed refactor
function QuickPrompts({ onClick }: QuickPromptsProps) { - function makePromptClickHandler(value: string) { - return () => onClick(value) - } - return ( <div className="space-y-2"> <p className="text-center text-sm text-muted-foreground"> Quick prompts: </p> <ul className="flex flex-wrap justify-center gap-2"> {PROMPTS.map(({ prompt, locale }) => ( <li key={prompt}> <button className="text-sm px-2 py-1 rounded bg-slate-700 text-cyan-400 cursor-pointer hover:bg-slate-600 transition-[color,box-shadow,background-color] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50" type="button" - onClick={makePromptClickHandler(prompt)} + onClick={() => onClick(prompt)} > {locale} • {prompt} </button>examples/ts-react-search/src/utils/getBaseUrl.ts (1)
1-5: Consider requiring VITE_API_BASE_URL in production environments.The hardcoded fallback to
'http://localhost:3000'on Line 4 may cause issues in production deployments where the API server is not at localhost. Consider either requiring the environment variable or providing a more flexible configuration strategy.🔎 Proposed enhancement to validate environment configuration
function getBaseUrl() { if (typeof window !== 'undefined') return '' - return import.meta.env.VITE_API_BASE_URL || 'http://localhost:3000' + const baseUrl = import.meta.env.VITE_API_BASE_URL + if (!baseUrl && import.meta.env.MODE === 'production') { + throw new Error('VITE_API_BASE_URL must be set in production') + } + return baseUrl || 'http://localhost:3000' }examples/ts-react-search/src/router.tsx (1)
7-15: Consider singleton pattern to avoid multiple router instances.The
getRouter()function creates a new router instance on each call. If this function is called multiple times, it could lead to multiple router instances, which may cause unexpected behavior.🔎 Proposed singleton pattern implementation
+let routerInstance: ReturnType<typeof createRouter> | undefined + export const getRouter = () => { + if (routerInstance) return routerInstance + const router = createRouter({ routeTree, scrollRestoration: true, defaultPreloadStaleTime: 0, }) + routerInstance = router return router }examples/ts-react-search/src/components/HeroSection/Brand.tsx (1)
1-13: LGTM! Consider adding a return type annotation.The component implementation is clean and follows React best practices. The Tailwind 4 gradient syntax and animations are correctly applied.
🔎 Optional: Add explicit return type for better type safety
-function Brand() { +function Brand(): JSX.Element { return (examples/ts-react-search/src/routes/index.tsx (1)
5-7: Consider adding a comment explaining the null return.The
HomePagecomponent returnsnull, which is unusual but appears intentional given that the actual content is rendered via the__root.tsxlayout. A brief comment would help clarify this architectural decision for future maintainers.🔎 Suggested documentation
function HomePage() { + // Content is rendered in __root.tsx layout via HeroSection return null }examples/ts-react-search/src/features/orders/ordersCollection.ts (1)
11-16: Add error handling for fetch response.The fetch call doesn't check
response.okbefore parsing JSON. If the API returns an error status (4xx/5xx), this could lead to unexpected behavior or unhelpful error messages.🔎 Suggested improvement
queryFn: async () => { const response = await fetch(`${getBaseUrl()}/api/orders`) + + if (!response.ok) { + throw new Error(`Failed to fetch orders: ${response.status} ${response.statusText}`) + } + const data = await response.json() return z.array(orderSchema).parse(data) },examples/ts-react-search/src/components/ui/calendar.tsx (1)
62-74: Chevron component only handles 'left' orientation explicitly.The
orientationprop includes'up' | 'down'options, but the component only checks for'left'and defaults toChevronRightIconfor everything else. While react-day-picker typically only uses left/right for month navigation, consider handling all cases explicitly for completeness.🔎 Optional: Handle all orientations
const defaultComponents = { Chevron: (props: { className?: string size?: number disabled?: boolean orientation?: 'left' | 'right' | 'up' | 'down' }) => { - if (props.orientation === 'left') { - return <ChevronLeftIcon size={16} {...props} aria-hidden="true" /> + const { orientation, ...rest } = props + if (orientation === 'left') { + return <ChevronLeftIcon size={16} {...rest} aria-hidden="true" /> } - return <ChevronRightIcon size={16} {...props} aria-hidden="true" /> + return <ChevronRightIcon size={16} {...rest} aria-hidden="true" /> }, }examples/ts-react-search/src/features/orders/useOrdersQuery.ts (1)
17-18: Potential confusion with date field filtering.The filter uses
gte(order.from, search.from ?? order.from)andlte(order.to, search.to ?? order.to). Whensearch.fromis undefined, this comparesorder.from >= order.from, which always evaluates to true (the intended no-op behavior).However, the field names are confusing:
order.fromandorder.toappear to be the order's own date range, whilesearch.fromandsearch.toare filter boundaries. Typically, you'd filter based on a single order date (e.g.,order.dateororder.createdAt) against the search range. Consider renaming for clarity or adding a comment explaining the intent.examples/ts-react-search/src/routes/_layout/disputes.tsx (1)
23-23: Avoid usingJSON.stringify()as a React key.Using
JSON.stringify(search)as a key has several drawbacks:
- Performance: Serialization runs on every render
- Instability: Same search object produces new string instances, causing unnecessary remounts
- Unpredictable ordering: JSON.stringify doesn't guarantee property order
The
DisputesFilterscomponent likely doesn't need an explicit key here. React's reconciliation can handle updates based on thesearchprop changes internally. If forced remounting is intentional, consider using a stable hash or specific search field values.🔎 Recommended fix
- <DisputesFilters key={JSON.stringify(search)} search={search} /> + <DisputesFilters search={search} />If you need forced remounting when search changes, use a more stable approach:
- <DisputesFilters key={JSON.stringify(search)} search={search} /> + <DisputesFilters + key={`${search.status}-${search.reason}-${search.from}-${search.to}`} + search={search} + />Note: This same pattern appears in
settlements.tsx(line 23) and likelyorders.tsx. Consider applying the same fix across all route files.examples/ts-react-search/src/features/orders/OrdersTable.tsx (1)
47-47: Questionable use ofw-0utility on table cell.The
w-0class setswidth: 0px, which conflicts with the cell content (a formatted date) and thepr-6padding. This appears to be an attempt to make the column compact, butw-0may cause rendering issues or unexpected layout behavior.If you want the column to be as narrow as possible while still fitting content:
- <TableCell className="w-0 pr-6">{formatDate(order.to)}</TableCell> + <TableCell className="w-auto whitespace-nowrap pr-6">{formatDate(order.to)}</TableCell>Or if you want to remove width constraints entirely:
- <TableCell className="w-0 pr-6">{formatDate(order.to)}</TableCell> + <TableCell className="pr-6">{formatDate(order.to)}</TableCell>examples/ts-react-search/src/routes/_layout/settlements.tsx (1)
23-23: Avoid usingJSON.stringify()as a React key (duplicate issue).This has the same problems as noted in
disputes.tsxline 23. UsingJSON.stringify(search)as a key causes performance overhead and unnecessary component remounts.🔎 Recommended fix
- <SettlementsFilters key={JSON.stringify(search)} search={search} /> + <SettlementsFilters search={search} />Or if forced remounting is needed:
- <SettlementsFilters key={JSON.stringify(search)} search={search} /> + <SettlementsFilters + key={`${search.currency}-${search.from}-${search.to}`} + search={search} + />examples/ts-react-search/src/hooks/useSpeechRecognition.ts (1)
73-73: Optimize useEffect dependencies to prevent unnecessary recreation.The dependencies array includes
options?.lang,options?.continuous, andoptions?.interimResults. If theoptionsobject reference changes on every render (which is common with inline object literals), this will cause theSpeechRecognitioninstance to be recreated unnecessarily.Consider destructuring
optionsat the hook entry or adding a note in the component docs to memoize the options object.🔎 Recommended fix
-export const useSpeechRecognition = (options?: UseSpeechRecognitionOptions) => { +export const useSpeechRecognition = (options?: UseSpeechRecognitionOptions) => { + const lang = options?.lang + const continuous = options?.continuous + const interimResults = options?.interimResults + const [listening, setListening] = useState(false) const [transcript, setTranscript] = useState('') const [error, setError] = useState<string | null>(null) @@ -24,9 +27,9 @@ const recognition = new SpeechRecognitionCtor() - recognition.lang = options?.lang ?? 'en-US' - recognition.continuous = options?.continuous ?? false - recognition.interimResults = options?.interimResults ?? false + recognition.lang = lang ?? 'en-US' + recognition.continuous = continuous ?? false + recognition.interimResults = interimResults ?? false // ... rest of the code - }, [options?.lang, options?.continuous, options?.interimResults]) + }, [lang, continuous, interimResults])Note: Since this is noted as "vibe-coded for a quick demo," this optimization can be deferred if the options are always memoized at the call site.
examples/ts-react-search/src/routes/api/search.ts (1)
53-83: Consider migrating to structured output generation when available.As noted by @jherr in the PR comments, this example should ideally wait for structured output generation support. The current approach uses prompt engineering to coerce the model into returning JSON, which is less reliable than native structured output.
Based on the coding guidelines, the library should support tool definitions with Zod schemas for structured outputs. Once that feature is available, consider refactoring this prompt to use a proper structured output mechanism.
Do you want me to draft an example implementation using
toolDefinition()with Zod schema inference once structured output support is added?examples/ts-react-search/src/features/settlements/constants.ts (1)
15-23: Redundant map where keys equal values.
SETTLEMENT_CURRENCY_MAPmaps each currency code to itself. UnlikeORDER_STATUS_MAPorDISPUTE_STATUS_MAPwhich provide human-readable labels, this map adds no value. Consider removing it or adding meaningful display names if intended for UI labels.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (7)
examples/ts-react-search/public/favicon.icois excluded by!**/*.icoexamples/ts-react-search/public/logo192.pngis excluded by!**/*.pngexamples/ts-react-search/public/logo512.pngis excluded by!**/*.pngexamples/ts-react-search/public/tanstack-circle-logo.pngis excluded by!**/*.pngexamples/ts-react-search/public/tanstack-word-logo-white.svgis excluded by!**/*.svgexamples/ts-react-search/src/logo.svgis excluded by!**/*.svgpnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (74)
examples/ts-react-search/.cta.jsonexamples/ts-react-search/.gitignoreexamples/ts-react-search/.vscode/settings.jsonexamples/ts-react-search/README.mdexamples/ts-react-search/package.jsonexamples/ts-react-search/public/manifest.jsonexamples/ts-react-search/public/robots.txtexamples/ts-react-search/src/components/FilterSelect.tsxexamples/ts-react-search/src/components/HeroSection/Brand.tsxexamples/ts-react-search/src/components/HeroSection/HeroSection.tsxexamples/ts-react-search/src/components/HeroSection/Navigation.tsxexamples/ts-react-search/src/components/HeroSection/ProjectDescription.tsxexamples/ts-react-search/src/components/HeroSection/Search/QuickPrompts.tsxexamples/ts-react-search/src/components/HeroSection/Search/Search.tsxexamples/ts-react-search/src/components/HeroSection/Search/SearchForm.tsxexamples/ts-react-search/src/components/HeroSection/Search/index.tsexamples/ts-react-search/src/components/HeroSection/index.tsexamples/ts-react-search/src/components/Spinner.tsxexamples/ts-react-search/src/components/TableSummary.tsxexamples/ts-react-search/src/components/ui/README.mdexamples/ts-react-search/src/components/ui/button.tsxexamples/ts-react-search/src/components/ui/calendar.tsxexamples/ts-react-search/src/components/ui/date-picker.tsxexamples/ts-react-search/src/components/ui/label.tsxexamples/ts-react-search/src/components/ui/popover.tsxexamples/ts-react-search/src/components/ui/select.tsxexamples/ts-react-search/src/components/ui/table.tsxexamples/ts-react-search/src/constants.tsexamples/ts-react-search/src/features/disputes/DisputesFilters.tsxexamples/ts-react-search/src/features/disputes/DisputesManager.tsxexamples/ts-react-search/src/features/disputes/DisputesTable.tsxexamples/ts-react-search/src/features/disputes/constants.tsexamples/ts-react-search/src/features/disputes/data.tsexamples/ts-react-search/src/features/disputes/disputesCollection.tsexamples/ts-react-search/src/features/disputes/types.tsexamples/ts-react-search/src/features/disputes/useDisputesQuery.tsexamples/ts-react-search/src/features/orders/OrdersFilters.tsxexamples/ts-react-search/src/features/orders/OrdersManager.tsxexamples/ts-react-search/src/features/orders/OrdersTable.tsxexamples/ts-react-search/src/features/orders/constants.tsexamples/ts-react-search/src/features/orders/data.tsexamples/ts-react-search/src/features/orders/ordersCollection.tsexamples/ts-react-search/src/features/orders/types.tsexamples/ts-react-search/src/features/orders/useOrdersQuery.tsexamples/ts-react-search/src/features/settlements/SettlementsFilters.tsxexamples/ts-react-search/src/features/settlements/SettlementsManager.tsxexamples/ts-react-search/src/features/settlements/SettlementsTable.tsxexamples/ts-react-search/src/features/settlements/constants.tsexamples/ts-react-search/src/features/settlements/data.tsexamples/ts-react-search/src/features/settlements/settlementsCollection.tsexamples/ts-react-search/src/features/settlements/types.tsexamples/ts-react-search/src/features/settlements/useSettlementsQuery.tsexamples/ts-react-search/src/hooks/useSpeechRecognition.tsexamples/ts-react-search/src/queryClient.tsexamples/ts-react-search/src/routeTree.gen.tsexamples/ts-react-search/src/router.tsxexamples/ts-react-search/src/routes/__root.tsxexamples/ts-react-search/src/routes/_layout/disputes.tsxexamples/ts-react-search/src/routes/_layout/orders.tsxexamples/ts-react-search/src/routes/_layout/route.tsxexamples/ts-react-search/src/routes/_layout/settlements.tsxexamples/ts-react-search/src/routes/api/disputes.tsexamples/ts-react-search/src/routes/api/orders.tsexamples/ts-react-search/src/routes/api/search.tsexamples/ts-react-search/src/routes/api/settlements.tsexamples/ts-react-search/src/routes/index.tsxexamples/ts-react-search/src/speech.d.tsexamples/ts-react-search/src/styles.cssexamples/ts-react-search/src/types.tsexamples/ts-react-search/src/utils/cn.tsexamples/ts-react-search/src/utils/formatDate.tsexamples/ts-react-search/src/utils/getBaseUrl.tsexamples/ts-react-search/tsconfig.jsonexamples/ts-react-search/vite.config.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use tree-shakeable adapter architecture for provider implementations - export specialized adapters (text, embedding, summarize, image) as separate imports from/adapterssubpath rather than monolithic adapters
Use Zod for runtime schema validation and type inference, particularly for tool input/output definitions withtoolDefinition()and Zod schema inference
Implement isomorphic tool system usingtoolDefinition()with.server()and.client()implementations for dual-environment execution
Use type-safe per-model configuration with provider options typed based on selected model to ensure compile-time safety
Implement stream processing with StreamProcessor for handling chunked responses and support partial JSON parsing for streaming AI responses
Files:
examples/ts-react-search/src/utils/cn.tsexamples/ts-react-search/src/queryClient.tsexamples/ts-react-search/src/components/ui/calendar.tsxexamples/ts-react-search/src/features/disputes/useDisputesQuery.tsexamples/ts-react-search/src/utils/getBaseUrl.tsexamples/ts-react-search/src/features/settlements/settlementsCollection.tsexamples/ts-react-search/src/features/disputes/data.tsexamples/ts-react-search/vite.config.tsexamples/ts-react-search/src/routes/__root.tsxexamples/ts-react-search/src/router.tsxexamples/ts-react-search/src/components/HeroSection/Brand.tsxexamples/ts-react-search/src/components/HeroSection/Navigation.tsxexamples/ts-react-search/src/routes/_layout/route.tsxexamples/ts-react-search/src/features/settlements/SettlementsTable.tsxexamples/ts-react-search/src/features/disputes/types.tsexamples/ts-react-search/src/components/FilterSelect.tsxexamples/ts-react-search/src/features/settlements/useSettlementsQuery.tsexamples/ts-react-search/src/components/HeroSection/Search/QuickPrompts.tsxexamples/ts-react-search/src/features/disputes/DisputesManager.tsxexamples/ts-react-search/src/components/Spinner.tsxexamples/ts-react-search/src/routes/api/orders.tsexamples/ts-react-search/src/components/HeroSection/Search/index.tsexamples/ts-react-search/src/components/ui/label.tsxexamples/ts-react-search/src/features/orders/OrdersManager.tsxexamples/ts-react-search/src/features/disputes/DisputesFilters.tsxexamples/ts-react-search/src/features/disputes/disputesCollection.tsexamples/ts-react-search/src/routes/_layout/settlements.tsxexamples/ts-react-search/src/features/settlements/types.tsexamples/ts-react-search/src/routes/_layout/orders.tsxexamples/ts-react-search/src/features/orders/ordersCollection.tsexamples/ts-react-search/src/components/ui/button.tsxexamples/ts-react-search/src/features/settlements/SettlementsFilters.tsxexamples/ts-react-search/src/routes/api/search.tsexamples/ts-react-search/src/hooks/useSpeechRecognition.tsexamples/ts-react-search/src/features/settlements/data.tsexamples/ts-react-search/src/utils/formatDate.tsexamples/ts-react-search/src/routes/_layout/disputes.tsxexamples/ts-react-search/src/features/disputes/DisputesTable.tsxexamples/ts-react-search/src/components/HeroSection/Search/Search.tsxexamples/ts-react-search/src/components/ui/table.tsxexamples/ts-react-search/src/features/orders/OrdersFilters.tsxexamples/ts-react-search/src/features/settlements/constants.tsexamples/ts-react-search/src/features/disputes/constants.tsexamples/ts-react-search/src/constants.tsexamples/ts-react-search/src/components/ui/popover.tsxexamples/ts-react-search/src/features/settlements/SettlementsManager.tsxexamples/ts-react-search/src/routes/api/disputes.tsexamples/ts-react-search/src/features/orders/constants.tsexamples/ts-react-search/src/components/HeroSection/ProjectDescription.tsxexamples/ts-react-search/src/features/orders/types.tsexamples/ts-react-search/src/features/orders/OrdersTable.tsxexamples/ts-react-search/src/routeTree.gen.tsexamples/ts-react-search/src/components/HeroSection/HeroSection.tsxexamples/ts-react-search/src/components/HeroSection/Search/SearchForm.tsxexamples/ts-react-search/src/routes/index.tsxexamples/ts-react-search/src/routes/api/settlements.tsexamples/ts-react-search/src/components/HeroSection/index.tsexamples/ts-react-search/src/types.tsexamples/ts-react-search/src/components/ui/date-picker.tsxexamples/ts-react-search/src/components/ui/select.tsxexamples/ts-react-search/src/features/orders/useOrdersQuery.tsexamples/ts-react-search/src/features/orders/data.tsexamples/ts-react-search/src/components/TableSummary.tsxexamples/ts-react-search/src/speech.d.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use camelCase for function and variable names throughout the codebase
Files:
examples/ts-react-search/src/utils/cn.tsexamples/ts-react-search/src/queryClient.tsexamples/ts-react-search/src/components/ui/calendar.tsxexamples/ts-react-search/src/features/disputes/useDisputesQuery.tsexamples/ts-react-search/src/utils/getBaseUrl.tsexamples/ts-react-search/src/features/settlements/settlementsCollection.tsexamples/ts-react-search/src/features/disputes/data.tsexamples/ts-react-search/vite.config.tsexamples/ts-react-search/src/routes/__root.tsxexamples/ts-react-search/src/router.tsxexamples/ts-react-search/src/components/HeroSection/Brand.tsxexamples/ts-react-search/src/components/HeroSection/Navigation.tsxexamples/ts-react-search/src/routes/_layout/route.tsxexamples/ts-react-search/src/features/settlements/SettlementsTable.tsxexamples/ts-react-search/src/features/disputes/types.tsexamples/ts-react-search/src/components/FilterSelect.tsxexamples/ts-react-search/src/features/settlements/useSettlementsQuery.tsexamples/ts-react-search/src/components/HeroSection/Search/QuickPrompts.tsxexamples/ts-react-search/src/features/disputes/DisputesManager.tsxexamples/ts-react-search/src/components/Spinner.tsxexamples/ts-react-search/src/routes/api/orders.tsexamples/ts-react-search/src/components/HeroSection/Search/index.tsexamples/ts-react-search/src/components/ui/label.tsxexamples/ts-react-search/src/features/orders/OrdersManager.tsxexamples/ts-react-search/src/features/disputes/DisputesFilters.tsxexamples/ts-react-search/src/features/disputes/disputesCollection.tsexamples/ts-react-search/src/routes/_layout/settlements.tsxexamples/ts-react-search/src/features/settlements/types.tsexamples/ts-react-search/src/routes/_layout/orders.tsxexamples/ts-react-search/src/features/orders/ordersCollection.tsexamples/ts-react-search/src/components/ui/button.tsxexamples/ts-react-search/src/features/settlements/SettlementsFilters.tsxexamples/ts-react-search/src/routes/api/search.tsexamples/ts-react-search/src/hooks/useSpeechRecognition.tsexamples/ts-react-search/src/features/settlements/data.tsexamples/ts-react-search/src/utils/formatDate.tsexamples/ts-react-search/src/routes/_layout/disputes.tsxexamples/ts-react-search/src/features/disputes/DisputesTable.tsxexamples/ts-react-search/src/components/HeroSection/Search/Search.tsxexamples/ts-react-search/src/components/ui/table.tsxexamples/ts-react-search/src/features/orders/OrdersFilters.tsxexamples/ts-react-search/src/features/settlements/constants.tsexamples/ts-react-search/src/features/disputes/constants.tsexamples/ts-react-search/src/constants.tsexamples/ts-react-search/src/components/ui/popover.tsxexamples/ts-react-search/src/features/settlements/SettlementsManager.tsxexamples/ts-react-search/src/routes/api/disputes.tsexamples/ts-react-search/src/features/orders/constants.tsexamples/ts-react-search/src/components/HeroSection/ProjectDescription.tsxexamples/ts-react-search/src/features/orders/types.tsexamples/ts-react-search/src/features/orders/OrdersTable.tsxexamples/ts-react-search/src/routeTree.gen.tsexamples/ts-react-search/src/components/HeroSection/HeroSection.tsxexamples/ts-react-search/src/components/HeroSection/Search/SearchForm.tsxexamples/ts-react-search/src/routes/index.tsxexamples/ts-react-search/src/routes/api/settlements.tsexamples/ts-react-search/src/components/HeroSection/index.tsexamples/ts-react-search/src/types.tsexamples/ts-react-search/src/components/ui/date-picker.tsxexamples/ts-react-search/src/components/ui/select.tsxexamples/ts-react-search/src/features/orders/useOrdersQuery.tsexamples/ts-react-search/src/features/orders/data.tsexamples/ts-react-search/src/components/TableSummary.tsxexamples/ts-react-search/src/speech.d.ts
examples/**
📄 CodeRabbit inference engine (CLAUDE.md)
Examples are not built by Nx and should be run independently from their directories with
pnpm devorpnpm install && pnpm dev
Files:
examples/ts-react-search/src/utils/cn.tsexamples/ts-react-search/src/queryClient.tsexamples/ts-react-search/src/components/ui/calendar.tsxexamples/ts-react-search/src/features/disputes/useDisputesQuery.tsexamples/ts-react-search/public/robots.txtexamples/ts-react-search/src/utils/getBaseUrl.tsexamples/ts-react-search/src/features/settlements/settlementsCollection.tsexamples/ts-react-search/src/features/disputes/data.tsexamples/ts-react-search/vite.config.tsexamples/ts-react-search/src/routes/__root.tsxexamples/ts-react-search/src/router.tsxexamples/ts-react-search/src/components/HeroSection/Brand.tsxexamples/ts-react-search/src/components/HeroSection/Navigation.tsxexamples/ts-react-search/src/routes/_layout/route.tsxexamples/ts-react-search/src/features/settlements/SettlementsTable.tsxexamples/ts-react-search/src/features/disputes/types.tsexamples/ts-react-search/src/components/FilterSelect.tsxexamples/ts-react-search/src/features/settlements/useSettlementsQuery.tsexamples/ts-react-search/src/components/HeroSection/Search/QuickPrompts.tsxexamples/ts-react-search/src/features/disputes/DisputesManager.tsxexamples/ts-react-search/src/components/Spinner.tsxexamples/ts-react-search/src/routes/api/orders.tsexamples/ts-react-search/src/components/HeroSection/Search/index.tsexamples/ts-react-search/src/components/ui/label.tsxexamples/ts-react-search/src/features/orders/OrdersManager.tsxexamples/ts-react-search/src/features/disputes/DisputesFilters.tsxexamples/ts-react-search/src/features/disputes/disputesCollection.tsexamples/ts-react-search/src/routes/_layout/settlements.tsxexamples/ts-react-search/src/features/settlements/types.tsexamples/ts-react-search/src/routes/_layout/orders.tsxexamples/ts-react-search/src/features/orders/ordersCollection.tsexamples/ts-react-search/src/components/ui/button.tsxexamples/ts-react-search/src/features/settlements/SettlementsFilters.tsxexamples/ts-react-search/src/routes/api/search.tsexamples/ts-react-search/src/hooks/useSpeechRecognition.tsexamples/ts-react-search/src/features/settlements/data.tsexamples/ts-react-search/src/utils/formatDate.tsexamples/ts-react-search/src/routes/_layout/disputes.tsxexamples/ts-react-search/src/features/disputes/DisputesTable.tsxexamples/ts-react-search/src/components/HeroSection/Search/Search.tsxexamples/ts-react-search/tsconfig.jsonexamples/ts-react-search/src/components/ui/table.tsxexamples/ts-react-search/src/features/orders/OrdersFilters.tsxexamples/ts-react-search/src/features/settlements/constants.tsexamples/ts-react-search/src/features/disputes/constants.tsexamples/ts-react-search/src/constants.tsexamples/ts-react-search/src/components/ui/popover.tsxexamples/ts-react-search/src/features/settlements/SettlementsManager.tsxexamples/ts-react-search/src/routes/api/disputes.tsexamples/ts-react-search/src/features/orders/constants.tsexamples/ts-react-search/src/components/HeroSection/ProjectDescription.tsxexamples/ts-react-search/src/features/orders/types.tsexamples/ts-react-search/src/components/ui/README.mdexamples/ts-react-search/src/features/orders/OrdersTable.tsxexamples/ts-react-search/src/routeTree.gen.tsexamples/ts-react-search/src/components/HeroSection/HeroSection.tsxexamples/ts-react-search/src/components/HeroSection/Search/SearchForm.tsxexamples/ts-react-search/src/styles.cssexamples/ts-react-search/src/routes/index.tsxexamples/ts-react-search/package.jsonexamples/ts-react-search/src/routes/api/settlements.tsexamples/ts-react-search/src/components/HeroSection/index.tsexamples/ts-react-search/src/types.tsexamples/ts-react-search/README.mdexamples/ts-react-search/src/components/ui/date-picker.tsxexamples/ts-react-search/src/components/ui/select.tsxexamples/ts-react-search/src/features/orders/useOrdersQuery.tsexamples/ts-react-search/src/features/orders/data.tsexamples/ts-react-search/src/components/TableSummary.tsxexamples/ts-react-search/src/speech.d.tsexamples/ts-react-search/public/manifest.json
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Implement framework integrations using the headless `tanstack/ai-client` for state management with framework-specific hooks (useChat) on top
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Implement stream processing with StreamProcessor for handling chunked responses and support partial JSON parsing for streaming AI responses
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/index.ts : Export tree-shakeable adapters with clear subpath exports in package.json (e.g., `tanstack/ai/adapters`, `tanstack/ai-openai/adapters`) to minimize bundle size
Applied to files:
examples/ts-react-search/src/utils/cn.tsexamples/ts-react-search/src/features/settlements/settlementsCollection.tsexamples/ts-react-search/vite.config.tsexamples/ts-react-search/src/components/HeroSection/Search/index.tsexamples/ts-react-search/.cta.jsonexamples/ts-react-search/.gitignoreexamples/ts-react-search/tsconfig.jsonexamples/ts-react-search/src/routeTree.gen.tsexamples/ts-react-search/package.jsonexamples/ts-react-search/src/components/HeroSection/index.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.test.ts : Write unit tests using Vitest alongside source files with `.test.ts` naming convention
Applied to files:
examples/ts-react-search/vite.config.tsexamples/ts-react-search/tsconfig.json
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Use Zod for runtime schema validation and type inference, particularly for tool input/output definitions with `toolDefinition()` and Zod schema inference
Applied to files:
examples/ts-react-search/src/features/disputes/types.tsexamples/ts-react-search/src/features/settlements/types.tsexamples/ts-react-search/tsconfig.jsonexamples/ts-react-search/src/features/disputes/constants.tsexamples/ts-react-search/src/features/orders/constants.tsexamples/ts-react-search/src/features/orders/types.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Implement framework integrations using the headless `tanstack/ai-client` for state management with framework-specific hooks (useChat) on top
Applied to files:
examples/ts-react-search/src/components/HeroSection/Search/Search.tsxexamples/ts-react-search/README.md
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to .eslintrc* : Use ESLint with custom TanStack config for linting all TypeScript and JavaScript files
Applied to files:
examples/ts-react-search/tsconfig.jsonexamples/ts-react-search/README.md
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Use tree-shakeable adapter architecture for provider implementations - export specialized adapters (text, embedding, summarize, image) as separate imports from `/adapters` subpath rather than monolithic adapters
Applied to files:
examples/ts-react-search/tsconfig.jsonexamples/ts-react-search/src/routeTree.gen.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Use type-safe per-model configuration with provider options typed based on selected model to ensure compile-time safety
Applied to files:
examples/ts-react-search/tsconfig.json
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use camelCase for function and variable names throughout the codebase
Applied to files:
examples/ts-react-search/tsconfig.json
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/adapters/*.ts : Create individual adapter implementations for each provider capability (text, embed, summarize, image) with separate exports to enable tree-shaking
Applied to files:
examples/ts-react-search/tsconfig.jsonexamples/ts-react-search/src/routeTree.gen.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Implement isomorphic tool system using `toolDefinition()` with `.server()` and `.client()` implementations for dual-environment execution
Applied to files:
examples/ts-react-search/tsconfig.json
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/model-meta.ts : Maintain model metadata files that define provider options and capabilities per model for per-model type safety
Applied to files:
examples/ts-react-search/src/features/orders/data.ts
🧬 Code graph analysis (35)
examples/ts-react-search/src/components/ui/calendar.tsx (1)
examples/ts-react-search/src/components/ui/button.tsx (1)
buttonVariants(61-61)
examples/ts-react-search/src/features/disputes/useDisputesQuery.ts (1)
examples/ts-react-search/src/features/disputes/types.ts (1)
DisputesSearch(15-15)
examples/ts-react-search/src/features/settlements/settlementsCollection.ts (1)
examples/ts-react-search/src/features/settlements/constants.ts (1)
settlementSchema(25-30)
examples/ts-react-search/src/features/disputes/data.ts (1)
examples/ts-react-search/src/features/disputes/types.ts (1)
Dispute(13-13)
examples/ts-react-search/src/routes/_layout/route.tsx (5)
examples/ts-react-search/src/routes/__root.tsx (1)
Route(15-40)examples/ts-react-search/src/routes/_layout/disputes.tsx (1)
Route(9-16)examples/ts-react-search/src/routes/_layout/orders.tsx (1)
Route(9-16)examples/ts-react-search/src/routes/_layout/settlements.tsx (1)
Route(9-16)examples/ts-react-search/src/routes/index.tsx (1)
Route(3-3)
examples/ts-react-search/src/features/settlements/SettlementsTable.tsx (2)
examples/ts-react-search/src/features/settlements/types.ts (1)
Settlement(10-10)examples/ts-react-search/src/components/ui/table.tsx (6)
Table(108-108)TableHeader(109-109)TableRow(113-113)TableHead(112-112)TableBody(110-110)TableCell(114-114)
examples/ts-react-search/src/features/disputes/types.ts (1)
examples/ts-react-search/src/features/disputes/constants.ts (4)
DISPUTE_STATUSES(5-10)DISPUTE_REASONS(19-26)disputeSchema(37-43)disputesSearchSchema(45-50)
examples/ts-react-search/src/components/FilterSelect.tsx (1)
examples/ts-react-search/src/constants.ts (1)
ALL_OPTION(1-1)
examples/ts-react-search/src/features/settlements/useSettlementsQuery.ts (1)
examples/ts-react-search/src/features/settlements/types.ts (1)
SettlementsSearch(12-12)
examples/ts-react-search/src/features/disputes/DisputesManager.tsx (1)
examples/ts-react-search/src/features/disputes/types.ts (1)
DisputesSearch(15-15)
examples/ts-react-search/src/features/orders/OrdersManager.tsx (1)
examples/ts-react-search/src/features/orders/types.ts (1)
OrdersSearch(15-15)
examples/ts-react-search/src/features/disputes/DisputesFilters.tsx (4)
examples/ts-react-search/src/features/disputes/types.ts (1)
DisputesSearch(15-15)examples/ts-react-search/src/constants.ts (1)
ALL_OPTION(1-1)examples/ts-react-search/src/features/disputes/constants.ts (3)
disputesSearchSchema(45-50)DISPUTE_STATUS_MAP(12-17)DISPUTE_REASON_MAP(28-35)examples/ts-react-search/src/components/ui/date-picker.tsx (1)
DatePicker(26-66)
examples/ts-react-search/src/features/disputes/disputesCollection.ts (1)
examples/ts-react-search/src/features/disputes/constants.ts (1)
disputeSchema(37-43)
examples/ts-react-search/src/routes/_layout/settlements.tsx (2)
examples/ts-react-search/src/routes/_layout/orders.tsx (1)
Route(9-16)examples/ts-react-search/src/features/settlements/constants.ts (1)
settlementsSearchSchema(32-36)
examples/ts-react-search/src/features/settlements/types.ts (1)
examples/ts-react-search/src/features/settlements/constants.ts (3)
SETTLEMENT_CURRENCIES(5-13)settlementSchema(25-30)settlementsSearchSchema(32-36)
examples/ts-react-search/src/routes/_layout/orders.tsx (1)
examples/ts-react-search/src/features/orders/constants.ts (1)
ordersSearchSchema(43-48)
examples/ts-react-search/src/features/orders/ordersCollection.ts (1)
examples/ts-react-search/src/features/orders/constants.ts (1)
orderSchema(35-41)
examples/ts-react-search/src/features/settlements/SettlementsFilters.tsx (5)
examples/ts-react-search/src/features/settlements/types.ts (1)
SettlementsSearch(12-12)examples/ts-react-search/src/constants.ts (1)
ALL_OPTION(1-1)examples/ts-react-search/src/features/settlements/constants.ts (2)
settlementsSearchSchema(32-36)SETTLEMENT_CURRENCY_MAP(15-23)examples/ts-react-search/src/components/ui/date-picker.tsx (1)
DatePicker(26-66)examples/ts-react-search/src/components/ui/button.tsx (1)
Button(61-61)
examples/ts-react-search/src/routes/api/search.ts (5)
examples/ts-react-search/src/types.ts (1)
ISO8601UTC(1-1)examples/ts-react-search/src/features/orders/constants.ts (2)
ORDER_STATUS_MAP(13-19)PAYMENT_METHOD_MAP(28-33)examples/ts-react-search/src/features/disputes/constants.ts (2)
DISPUTE_STATUS_MAP(12-17)DISPUTE_REASON_MAP(28-35)examples/ts-react-search/src/features/settlements/constants.ts (1)
SETTLEMENT_CURRENCY_MAP(15-23)packages/typescript/ai-openai/src/index.ts (1)
openaiText(9-9)
examples/ts-react-search/src/features/settlements/data.ts (1)
examples/ts-react-search/src/features/settlements/types.ts (1)
Settlement(10-10)
examples/ts-react-search/src/routes/_layout/disputes.tsx (3)
examples/ts-react-search/src/routes/_layout/orders.tsx (1)
Route(9-16)examples/ts-react-search/src/routes/_layout/settlements.tsx (1)
Route(9-16)examples/ts-react-search/src/features/disputes/constants.ts (1)
disputesSearchSchema(45-50)
examples/ts-react-search/src/features/disputes/DisputesTable.tsx (2)
examples/ts-react-search/src/features/disputes/types.ts (1)
Dispute(13-13)examples/ts-react-search/src/components/ui/table.tsx (6)
Table(108-108)TableHeader(109-109)TableRow(113-113)TableHead(112-112)TableBody(110-110)TableCell(114-114)
examples/ts-react-search/src/features/orders/OrdersFilters.tsx (4)
examples/ts-react-search/src/features/orders/types.ts (1)
OrdersSearch(15-15)examples/ts-react-search/src/constants.ts (1)
ALL_OPTION(1-1)examples/ts-react-search/src/features/orders/constants.ts (3)
ordersSearchSchema(43-48)ORDER_STATUS_MAP(13-19)PAYMENT_METHOD_MAP(28-33)examples/ts-react-search/src/components/ui/date-picker.tsx (1)
DatePicker(26-66)
examples/ts-react-search/src/features/settlements/constants.ts (1)
examples/ts-react-search/src/features/settlements/types.ts (1)
SettlementCurrency(8-8)
examples/ts-react-search/src/features/disputes/constants.ts (1)
examples/ts-react-search/src/features/disputes/types.ts (2)
DisputeStatus(9-9)DisputeReason(11-11)
examples/ts-react-search/src/features/settlements/SettlementsManager.tsx (1)
examples/ts-react-search/src/features/settlements/types.ts (1)
SettlementsSearch(12-12)
examples/ts-react-search/src/routes/api/disputes.ts (1)
examples/ts-react-search/src/features/disputes/data.ts (1)
DISPUTES(3-74)
examples/ts-react-search/src/features/orders/constants.ts (1)
examples/ts-react-search/src/features/orders/types.ts (2)
OrderStatus(9-9)PaymentMethod(11-11)
examples/ts-react-search/src/features/orders/types.ts (1)
examples/ts-react-search/src/features/orders/constants.ts (4)
ORDER_STATUSES(5-11)PAYMENT_METHODS(21-26)orderSchema(35-41)ordersSearchSchema(43-48)
examples/ts-react-search/src/features/orders/OrdersTable.tsx (2)
examples/ts-react-search/src/features/orders/types.ts (1)
Order(13-13)examples/ts-react-search/src/components/ui/table.tsx (6)
Table(108-108)TableHeader(109-109)TableRow(113-113)TableHead(112-112)TableBody(110-110)TableCell(114-114)
examples/ts-react-search/src/components/HeroSection/Search/SearchForm.tsx (1)
examples/ts-react-search/src/hooks/useSpeechRecognition.ts (1)
useSpeechRecognition(10-92)
examples/ts-react-search/src/routes/index.tsx (5)
examples/ts-react-search/src/routes/__root.tsx (1)
Route(15-40)examples/ts-react-search/src/routes/_layout/disputes.tsx (1)
Route(9-16)examples/ts-react-search/src/routes/_layout/orders.tsx (1)
Route(9-16)examples/ts-react-search/src/routes/_layout/settlements.tsx (1)
Route(9-16)examples/ts-react-search/src/routes/_layout/route.tsx (1)
Route(3-5)
examples/ts-react-search/src/routes/api/settlements.ts (3)
examples/ts-react-search/src/routes/api/disputes.ts (1)
Route(5-11)examples/ts-react-search/src/routes/api/orders.ts (1)
Route(5-11)examples/ts-react-search/src/features/settlements/data.ts (1)
SETTLEMENTS(3-64)
examples/ts-react-search/src/features/orders/useOrdersQuery.ts (1)
examples/ts-react-search/src/features/orders/types.ts (1)
OrdersSearch(15-15)
examples/ts-react-search/src/features/orders/data.ts (1)
examples/ts-react-search/src/features/orders/types.ts (1)
Order(13-13)
🪛 LanguageTool
examples/ts-react-search/README.md
[grammar] ~34-~34: Use a hyphen to join words.
Context: ...com/router). The initial setup is a file based router. Which means that the route...
(QB_NEW_EN_HYPHEN)
[grammar] ~125-~125: Use a hyphen to join words.
Context: ... }, }) ``` Loaders simplify your data fetching logic dramatically. Check out m...
(QB_NEW_EN_HYPHEN)
[grammar] ~129-~129: Ensure spelling is correct
Context: ...o route loading and integrating it into you application is a breeze. First add you...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~212-~212: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...ting point for your project. First you need to add TanStack Store as a dependency: ``...
(REP_NEED_TO_VB)
[style] ~287-~287: Consider removing “of” to be more concise
Context: ... # Learn More You can learn more about all of the offerings from TanStack in the [TanStac...
(ALL_OF_THE)
⏰ 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). (2)
- GitHub Check: Preview
- GitHub Check: Test
| "addOnOptions": {}, | ||
| "git": true, | ||
| "version": 1, | ||
| "framework": "react-cra", |
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.
Framework declaration inconsistent with actual setup.
The configuration specifies "framework": "react-cra" (Create React App), but the project uses Vite with TanStack Start (as shown in vite.config.ts). This appears to be stale scaffolding metadata.
Consider either updating to "framework": "vite-react" or removing this configuration file if it's not actively used by tooling.
🤖 Prompt for AI Agents
In examples/ts-react-search/.cta.json around line 10 the "framework":
"react-cra" setting is incorrect for this project which uses Vite/TanStack
Start; update the value to "vite-react" (or remove the .cta.json if unused) so
the framework metadata matches the actual build tooling and avoid stale
scaffolding; ensure any dependent tooling is tested after the change.
| "dev": "vite dev --port 3000", | ||
| "build": "vite build", | ||
| "serve": "vite preview", | ||
| "test": "exit 0" |
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.
Test script is a placeholder and doesn't run actual tests.
Line 9 shows "test": "exit 0", which always exits successfully without running any tests. This means CI/CD pipelines will pass even if tests fail or don't exist.
🔎 Proposed fix to run actual tests
- "test": "exit 0"
+ "test": "vitest run"📝 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.
| "test": "exit 0" | |
| "test": "vitest run" |
🤖 Prompt for AI Agents
In examples/ts-react-search/package.json around line 9, the "test": "exit 0"
placeholder always succeeds and should be replaced with a real test command;
update the "test" script to run the project's test runner (for example use
"react-scripts test --watchAll=false" if using Create React App, or "vitest" /
"jest --runInBand" if the repo uses Vitest/Jest), install/configure the chosen
test runner if not present, and ensure CI calls npm test so real tests are
executed instead of always passing.
| "class-variance-authority": "^0.7.1", | ||
| "clsx": "^2.1.1", | ||
| "lucide-react": "^0.561.0", | ||
| "nitro": "latest", |
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
Pin the nitro dependency version.
Line 30 specifies "nitro": "latest", which means the version will float to the latest available version. This can lead to unexpected breaking changes and non-reproducible builds.
🔎 Recommended fix to pin the version
After determining the current latest version, update to:
- "nitro": "latest",
+ "nitro": "^2.x.x",Replace 2.x.x with the actual latest stable version number.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In examples/ts-react-search/package.json around line 30, the dependency "nitro":
"latest" is floating; replace "latest" with the concrete current stable nitro
version (find the exact version from npm or the repo, e.g., 2.x.x) to pin the
dependency, then update the lockfile by running your package manager install
(npm/yarn/pnpm) and verify the project builds/tests to ensure no regressions.
| return ( | ||
| <div className="flex min-w-0 flex-col gap-2"> | ||
| <Label htmlFor={id}>{label}</Label> | ||
| <Select name="status" value={value || ''} onValueChange={onChange}> |
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.
Hardcoded name="status" in a generic component.
The name attribute is hardcoded to "status", but FilterSelect is used for multiple filter types (status, paymentMethod, currency). This could cause form serialization issues and is semantically incorrect.
🔎 Proposed fix
- <Select name="status" value={value || ''} onValueChange={onChange}>
+ <Select name={id} value={value || ''} onValueChange={onChange}>📝 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.
| <Select name="status" value={value || ''} onValueChange={onChange}> | |
| <Select name={id} value={value || ''} onValueChange={onChange}> |
🤖 Prompt for AI Agents
In examples/ts-react-search/src/components/FilterSelect.tsx around line 29, the
Select element has a hardcoded name="status" which is incorrect for a generic
FilterSelect used for status, paymentMethod, currency; update the component to
accept a name prop (or derive it from an existing prop like filterKey/field) and
pass that prop to the Select's name attribute instead of the hardcoded string,
ensure callers are updated to supply the correct name or rely on a sensible
default, and add/adjust the component's TypeScript props interface so name is
typed (optional if default provided).
| onFinish(message) { | ||
| if (message.role === 'assistant' && message.parts[0].type === 'text') { | ||
| const result = message.parts[0].content | ||
| const { name, parameters } = JSON.parse(result) || {} | ||
|
|
||
| if (name && parameters) { | ||
| navigate({ to: `/${name}`, search: parameters }) | ||
| } | ||
| } |
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.
Unsafe JSON parsing and array access can cause runtime exceptions.
Several issues in the onFinish callback:
message.parts[0]accesses without checking ifpartsis non-emptyJSON.parse(result)can throwSyntaxErroron malformed JSON, which the|| {}fallback doesn't catch (it only handlesnull/undefined)
🔎 Proposed fix with defensive error handling
onFinish(message) {
- if (message.role === 'assistant' && message.parts[0].type === 'text') {
- const result = message.parts[0].content
- const { name, parameters } = JSON.parse(result) || {}
-
- if (name && parameters) {
- navigate({ to: `/${name}`, search: parameters })
+ if (message.role === 'assistant' && message.parts[0]?.type === 'text') {
+ try {
+ const result = message.parts[0].content
+ const { name, parameters } = JSON.parse(result)
+
+ if (name && parameters) {
+ navigate({ to: `/${name}`, search: parameters })
+ }
+ } catch {
+ console.error('Failed to parse search response')
}
}
},📝 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.
| onFinish(message) { | |
| if (message.role === 'assistant' && message.parts[0].type === 'text') { | |
| const result = message.parts[0].content | |
| const { name, parameters } = JSON.parse(result) || {} | |
| if (name && parameters) { | |
| navigate({ to: `/${name}`, search: parameters }) | |
| } | |
| } | |
| onFinish(message) { | |
| if (message.role === 'assistant' && message.parts[0]?.type === 'text') { | |
| try { | |
| const result = message.parts[0].content | |
| const { name, parameters } = JSON.parse(result) | |
| if (name && parameters) { | |
| navigate({ to: `/${name}`, search: parameters }) | |
| } | |
| } catch { | |
| console.error('Failed to parse search response') | |
| } | |
| } | |
| }, |
🤖 Prompt for AI Agents
In examples/ts-react-search/src/components/HeroSection/Search/Search.tsx around
lines 16 to 24, the onFinish handler unsafely indexes message.parts[0] and calls
JSON.parse without error handling; update the function to first check that
message.parts is an array and has at least one element and that parts[0].type
=== 'text', then wrap JSON.parse(result) in a try/catch to handle malformed JSON
(returning or skipping on parse error), validate that the parsed value is an
object with string name and parameters in the expected shape before calling
navigate, and only call navigate when all validations pass.
| queryFn: async () => { | ||
| const response = await fetch(`${getBaseUrl()}/api/disputes`) | ||
| const data = await response.json() | ||
|
|
||
| return z.array(disputeSchema).parse(data) | ||
| }, |
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.
Missing error handling for failed fetch responses.
The queryFn doesn't check response.ok before parsing. If the API returns an error (4xx/5xx), response.json() may return an error object that will fail Zod validation with an unclear error message, or worse, the response might not be valid JSON.
🔎 Proposed fix
queryFn: async () => {
const response = await fetch(`${getBaseUrl()}/api/disputes`)
+ if (!response.ok) {
+ throw new Error(`Failed to fetch disputes: ${response.status}`)
+ }
const data = await response.json()
return z.array(disputeSchema).parse(data)
},📝 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.
| queryFn: async () => { | |
| const response = await fetch(`${getBaseUrl()}/api/disputes`) | |
| const data = await response.json() | |
| return z.array(disputeSchema).parse(data) | |
| }, | |
| queryFn: async () => { | |
| const response = await fetch(`${getBaseUrl()}/api/disputes`) | |
| if (!response.ok) { | |
| throw new Error(`Failed to fetch disputes: ${response.status}`) | |
| } | |
| const data = await response.json() | |
| return z.array(disputeSchema).parse(data) | |
| }, |
🤖 Prompt for AI Agents
In examples/ts-react-search/src/features/disputes/disputesCollection.ts around
lines 11 to 16, the queryFn currently calls response.json() and runs Zod
validation without checking response.ok; update it to first check response.ok
and, if false, read the response body (text or json) and throw a descriptive
error that includes status and body so callers can handle it, otherwise proceed
to parse the JSON and then validate with z.array(disputeSchema).parse(data).
| options={Object.entries(DISPUTE_STATUS_MAP)} | ||
| /> | ||
| <FilterSelect | ||
| id="resason" |
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 typo in id attribute.
The id attribute has a typo: "resason" should be "reason".
🔎 Proposed fix
<FilterSelect
- id="resason"
+ id="reason"
label="Reason"
value={pendingReason}
onChange={setPendingReason}📝 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.
| id="resason" | |
| <FilterSelect | |
| id="reason" | |
| label="Reason" | |
| value={pendingReason} | |
| onChange={setPendingReason} |
🤖 Prompt for AI Agents
In examples/ts-react-search/src/features/disputes/DisputesFilters.tsx around
line 71, the id attribute is misspelled as "resason"; update the id value to
"reason" wherever it's referenced in this file (and update any corresponding
htmlFor or label references) to ensure consistency and correct accessibility
linkage.
| queryFn: async () => { | ||
| const response = await fetch(`${getBaseUrl()}/api/settlements`) | ||
| const data = await response.json() | ||
|
|
||
| return z.array(settlementSchema).parse(data) | ||
| }, |
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.
Add error handling for fetch and parse operations.
The queryFn doesn't handle potential failures from the fetch request (network errors, non-2xx responses) or from the Zod validation. While TanStack Query will catch thrown errors, explicit error handling would provide better error messages and debugging context.
🔎 Suggested error handling
queryFn: async () => {
const response = await fetch(`${getBaseUrl()}/api/settlements`)
+
+ if (!response.ok) {
+ throw new Error(`Failed to fetch settlements: ${response.statusText}`)
+ }
+
const data = await response.json()
- return z.array(settlementSchema).parse(data)
+ const result = z.array(settlementSchema).safeParse(data)
+
+ if (!result.success) {
+ throw new Error(`Invalid settlements data: ${result.error.message}`)
+ }
+
+ return result.data
},📝 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.
| queryFn: async () => { | |
| const response = await fetch(`${getBaseUrl()}/api/settlements`) | |
| const data = await response.json() | |
| return z.array(settlementSchema).parse(data) | |
| }, | |
| queryFn: async () => { | |
| const response = await fetch(`${getBaseUrl()}/api/settlements`) | |
| if (!response.ok) { | |
| throw new Error(`Failed to fetch settlements: ${response.statusText}`) | |
| } | |
| const data = await response.json() | |
| const result = z.array(settlementSchema).safeParse(data) | |
| if (!result.success) { | |
| throw new Error(`Invalid settlements data: ${result.error.message}`) | |
| } | |
| return result.data | |
| }, |
🤖 Prompt for AI Agents
In examples/ts-react-search/src/features/settlements/settlementsCollection.ts
around lines 11 to 16, the queryFn currently assumes fetch and Zod parsing
always succeed; wrap the fetch/parse in a try/catch, check response.ok and throw
a descriptive Error if the HTTP status is not 2xx (include status and
statusText), attempt to parse JSON only after a successful response, catch Zod
parse errors and rethrow or wrap them with context (e.g., "Failed to validate
settlements: <zod message>"), and ensure any network/fetch exceptions are also
caught and rethrown with a clear message so TanStack Query receives informative
errors for debugging.
| ) | ||
| } | ||
|
|
||
| const { messages, conversationId } = await request.json() |
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
Add error handling for JSON parsing.
await request.json() will throw if the request body is not valid JSON, resulting in an unhandled promise rejection. The error would not be caught by the try-catch block since it's outside the try block.
🔎 Proposed fix
- const { messages, conversationId } = await request.json()
-
try {
+ const { messages, conversationId } = await request.json()
+
const stream = chat({
adapter: openaiText('gpt-5-nano'),
messages,
conversationId,
systemPrompts: [SYSTEM_PROMPT],
})
return toServerSentEventsResponse(stream)
} catch (error: any) {
return new Response(
JSON.stringify({
error: error.message || 'An error occurred',
}),
{
status: 500,
headers: { 'Content-Type': 'application/json' },
},
)
}📝 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 { messages, conversationId } = await request.json() | |
| try { | |
| const { messages, conversationId } = await request.json() | |
| const stream = chat({ | |
| adapter: openaiText('gpt-5-nano'), | |
| messages, | |
| conversationId, | |
| systemPrompts: [SYSTEM_PROMPT], | |
| }) | |
| return toServerSentEventsResponse(stream) | |
| } catch (error: any) { | |
| return new Response( | |
| JSON.stringify({ | |
| error: error.message || 'An error occurred', | |
| }), | |
| { | |
| status: 500, | |
| headers: { 'Content-Type': 'application/json' }, | |
| }, | |
| ) | |
| } |
🤖 Prompt for AI Agents
In examples/ts-react-search/src/routes/api/search.ts around line 101, the call
to await request.json() is currently outside the try-catch and will throw on
invalid JSON; wrap the JSON parsing in a try-catch (or move it inside the
existing try block), catch JSON parse errors and return a 400 response with a
clear error message, and validate that the parsed object contains the expected
messages and conversationId before proceeding.
| onerror: | ||
| | ((this: SpeechRecognition, ev: SpeechRecognitionErrorEvent) => any) | ||
| | null |
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.
Missing SpeechRecognitionErrorEvent interface.
The onerror handler references SpeechRecognitionErrorEvent but this interface is not defined in the file. This will cause TypeScript errors when accessing properties like event.error in the useSpeechRecognition hook.
🔎 Proposed fix - add missing interface
+interface SpeechRecognitionErrorEvent extends Event {
+ error: string
+ message?: string
+}
+
interface SpeechRecognition extends EventTarget {Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In examples/ts-react-search/src/speech.d.ts around lines 12 to 14, the onerror
handler references SpeechRecognitionErrorEvent which is not defined; add a
SpeechRecognitionErrorEvent interface matching the standard (including at least
a readonly property 'error': string and optional 'message' or other relevant
fields) and export it or declare it globally so TypeScript consumers (like
useSpeechRecognition) can access event.error without type errors; update the
file declarations to reference this new interface for the onerror signature.
720ebf6 to
993fd11
Compare
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: 10
🤖 Fix all issues with AI agents
In @examples/ts-react-search/README.md:
- Line 34: Fix grammar and style issues in the README by replacing specific
phrases: change "file based router" to "file-based router" (line containing "The
initial setup is a file based router"), correct "integrating it into you
application" to "integrating it into your application", reword the repeated
"First you need to add" (e.g., change the second occurrence to "Next, add" or
"Start by adding") to avoid repetition, and replace "all of the offerings" with
"all offerings"; update the sentences in their respective paragraphs to preserve
punctuation and capitalization.
- Around line 7-9: Update the startup command in the README examples to follow
the guidelines: replace any usage of "pnpm start" with "pnpm dev" and provide
the alternate combined form "pnpm install && pnpm dev" so users can run the
example independently; ensure both occurrences in the README (the code block
showing installation/startup) are updated accordingly.
In @examples/ts-react-search/src/components/HeroSection/Search/SearchForm.tsx:
- Around line 26-30: The useEffect in SearchForm currently depends on transcript
but references onChange without including it in the dependency array; update the
effect declaration (the useEffect that calls onChange(transcript)) to include
onChange in the dependency array (e.g., [transcript, onChange]) so the hook
responds correctly if the onChange callback changes.
In @examples/ts-react-search/src/components/Spinner.tsx:
- Around line 3-5: The Spinner component currently returns only a decorative
LoaderCircleIcon and lacks accessibility semantics; update Spinner to provide
screen-reader information by marking the icon as decorative (aria-hidden="true")
and adding a status region (e.g., a wrapper element with role="status" and
aria-live="polite") that contains a visually hidden text node like "Loading…" so
assistive tech announces the loading state; use the existing function name
Spinner and LoaderCircleIcon to locate where to add the role/aria-live wrapper
and the sr-only text.
In @examples/ts-react-search/src/components/ui/select.tsx:
- Line 1: Remove the top-level 'use client' directive from the file—this Select
component is a pure wrapper around Radix primitives and does not use React hooks
or client-only APIs, and TanStack Start is client-first; simply delete the "'use
client'" line at the top of
examples/ts-react-search/src/components/ui/select.tsx so the Select component
(the exported Select wrapper around Radix) conforms to the project conventions.
In @examples/ts-react-search/src/features/disputes/constants.ts:
- Around line 1-4: There is a circular import between constants.ts and types.ts
because constants.ts imports DisputeReason/DisputeStatus that are actually
derived from constants here (e.g., DISPUTE_STATUSES). Fix by removing the
imports from types.ts in constants.ts, derive and export the types inline in
constants.ts (e.g., export type DisputeStatus = (typeof
DISPUTE_STATUSES)[number] and same for DisputeReason), and then update types.ts
to re-export those types from constants.ts if other modules expect them; ensure
all references use the exported types from constants.ts to break the cycle.
In @examples/ts-react-search/src/features/disputes/DisputesFilters.tsx:
- Around line 70-76: The id prop on the FilterSelect component is misspelled;
change id="resason" to id="reason" in the FilterSelect usage (the component that
sets id, label="Reason", value={pendingReason}, onChange={setPendingReason},
options={Object.entries(DISPUTE_REASON_MAP)}) so the id matches the label and
other logic that may reference "reason".
In @examples/ts-react-search/src/features/settlements/useSettlementsQuery.ts:
- Around line 5-19: The where-clause uses nullish coalescing which creates
tautologies (e.g., eq(settlement.currency, search.currency ??
settlement.currency)) so filters never apply; update useSettlementsQuery (and
analogously useOrdersQuery and useDisputesQuery) to build the predicate list
conditionally: inside the useLiveQuery callback, assemble an array of condition
expressions only when search.currency, search.from, search.to (or their
equivalents) are defined and then pass that array into and(...) (or call and
with spread of the filtered array); ensure you reference settlementsCollection
and the settlement alias when creating the conditional predicates so undefined
search fields are not turned into self-comparisons.
In @examples/ts-react-search/src/routes/__root.tsx:
- Around line 48-49: The Tailwind gradient class names on the root JSX elements
are misspelled: replace `bg-linear-to-b` with `bg-gradient-to-b` on the <body>
element and replace `bg-linear-to-r` with `bg-gradient-to-r` on the container
<div> (look for the elements using those className strings) so the gradients
render correctly.
In @examples/ts-react-search/src/types.ts:
- Line 1: Remove the unused exported type ISO8601UTC: delete the line "export
type ISO8601UTC = 'ISO-8601 UTC'" from the types file and ensure no other code
relies on ISO8601UTC; if any references exist, replace them with the appropriate
concrete type or remove those references before deleting the export.
🧹 Nitpick comments (7)
examples/ts-react-search/README.md (1)
1-90: Add context-specific information about this AI search example.The README is generic boilerplate and doesn't explain what this example demonstrates. Consider adding a brief introduction describing the AI-powered natural language search functionality, the domain (orders, disputes, settlements), and key features. This helps users understand the example's purpose without reading through generic setup instructions.
examples/ts-react-search/src/components/Spinner.tsx (1)
3-5: Consider making the component more flexible.The spinner could accept props for customization (e.g., size, className, label) to improve reusability across different contexts.
♻️ Example implementation with props
interface SpinnerProps { size?: string className?: string label?: string } function Spinner({ size = 'size-4', className = '', label = 'Loading' }: SpinnerProps) { return ( <div role="status" aria-live="polite" aria-label={label}> <LoaderCircleIcon className={`animate-spin m-auto ${size} ${className}`} aria-hidden="true" /> </div> ) }examples/ts-react-search/src/constants.ts (1)
1-1: Consider aligning with camelCase naming per coding guidelines.The coding guidelines specify camelCase for variable names throughout the codebase. However, the codebase uses SCREAMING_SNAKE_CASE for constants (e.g.,
CHAT_KEY,OPENAI_CHAT_MODELS), so this is an optional alignment rather than a strict violation.♻️ Proposed refactor to camelCase
-export const ALL_OPTION = 'ALL' +export const allOption = 'ALL'examples/ts-react-search/src/components/ui/date-picker.tsx (1)
68-72: Timezone mismatch insafeParsemay shift dates.
safeParseextracts UTC components from the parsed date but constructs a localDateobject. When the Calendar displays this, it interprets it as a local date. If the user's timezone is behind UTC, an ISO string like"2024-01-15T00:00:00Z"will be parsed as2024-01-14locally, causing the displayed date to be off by one day.Consider keeping the date in UTC consistently or using local components:
♻️ Suggested fix using local date interpretation
function safeParse(value: string) { const date = new Date(value) if (Number.isNaN(date.getTime())) return undefined - return new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()) + // Keep as-is if you want the calendar to show the UTC date as local, + // or use local components if the ISO string represents local midnight: + return new Date(date.getFullYear(), date.getMonth(), date.getDate()) }examples/ts-react-search/src/components/HeroSection/Search/SearchForm.tsx (2)
60-68: Add accessibility attributes to the voice input button.The voice input button lacks an accessible name and toggle state indicators, making it difficult for screen reader users to understand its purpose and state.
♿ Proposed accessibility improvements
<button className="absolute inset-y-3 end-12 flex size-8 items-center justify-center transition-[color,box-shadow,background-color] outline-none hover:text-foreground focus:z-10 focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 data-[active=true]:text-blue-600 disabled:pointer-events-none disabled:opacity-40 cursor-pointer bg-input/70 hover:bg-input/50 rounded-full" type="button" data-active={listening} disabled={isLoading} onClick={handleVoiceOverClick} + aria-label={listening ? 'Stop voice input' : 'Start voice input'} + aria-pressed={listening} > <MicIcon className="size-4" /> </button>
69-79: Add an accessible label to the submit button.The submit button lacks an accessible name. While submit buttons in forms have some implicit context, an explicit label improves the experience for screen reader users.
♿ Proposed accessibility improvement
<button className="absolute inset-y-0 end-0 flex h-full w-11 items-center justify-center rounded-e-2xl text-muted-foreground/80 transition-[color,box-shadow,background-color] outline-none hover:text-foreground focus:z-10 focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 cursor-pointer pr-2" type="submit" disabled={!hasValue || isLoading} + aria-label={isLoading ? 'Searching...' : 'Submit search'} > {isLoading ? ( <LoaderCircleIcon className="size-4 animate-spin" /> ) : ( <ArrowRightIcon className="size-4" /> )} </button>examples/ts-react-search/src/components/ui/select.tsx (1)
27-50: Consider forwarding refs for better composability.Components like
SelectTrigger,SelectContent,SelectLabel, andSelectItemwould benefit from ref forwarding usingReact.forwardRef. This allows parent components to access the underlying DOM elements when needed, improving composability and enabling use cases like focus management, measurements, and imperative DOM operations.♻️ Example refactor for SelectTrigger with ref forwarding
-function SelectTrigger({ +const SelectTrigger = React.forwardRef< + React.ElementRef<typeof SelectPrimitive.Trigger>, + React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> +>(function SelectTrigger({ className, children, ...props -}: React.ComponentProps<typeof SelectPrimitive.Trigger>) { +}, ref) { return ( <SelectPrimitive.Trigger + ref={ref} className={cn( 'flex h-11 w-full items-center justify-between gap-2 rounded-md border border-input bg-transparent px-3 py-2 text-foreground text-sm shadow-xs outline-none transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[placeholder]:text-muted-foreground *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 dark:aria-invalid:ring-destructive/40 [&>span]:line-clamp-1 [&_svg]:pointer-events-none [&_svg]:shrink-0 dark:hover:bg-input/50 dark:bg-input/30', className, )} data-slot="select-trigger" {...props} > {children} <SelectPrimitive.Icon asChild> <ChevronDownIcon className="shrink-0 in-aria-invalid:text-destructive/80 text-muted-foreground/80" size={16} /> </SelectPrimitive.Icon> </SelectPrimitive.Trigger> ) -} +})Apply similar patterns to
SelectContent,SelectLabel, andSelectItemfor consistency.Also applies to: 52-84, 86-100, 102-124
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (7)
examples/ts-react-search/public/favicon.icois excluded by!**/*.icoexamples/ts-react-search/public/logo192.pngis excluded by!**/*.pngexamples/ts-react-search/public/logo512.pngis excluded by!**/*.pngexamples/ts-react-search/public/tanstack-circle-logo.pngis excluded by!**/*.pngexamples/ts-react-search/public/tanstack-word-logo-white.svgis excluded by!**/*.svgexamples/ts-react-search/src/logo.svgis excluded by!**/*.svgpnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (74)
examples/ts-react-search/.cta.jsonexamples/ts-react-search/.gitignoreexamples/ts-react-search/.vscode/settings.jsonexamples/ts-react-search/README.mdexamples/ts-react-search/package.jsonexamples/ts-react-search/public/manifest.jsonexamples/ts-react-search/public/robots.txtexamples/ts-react-search/src/components/FilterSelect.tsxexamples/ts-react-search/src/components/HeroSection/Brand.tsxexamples/ts-react-search/src/components/HeroSection/HeroSection.tsxexamples/ts-react-search/src/components/HeroSection/Navigation.tsxexamples/ts-react-search/src/components/HeroSection/ProjectDescription.tsxexamples/ts-react-search/src/components/HeroSection/Search/QuickPrompts.tsxexamples/ts-react-search/src/components/HeroSection/Search/Search.tsxexamples/ts-react-search/src/components/HeroSection/Search/SearchForm.tsxexamples/ts-react-search/src/components/HeroSection/Search/index.tsexamples/ts-react-search/src/components/HeroSection/index.tsexamples/ts-react-search/src/components/Spinner.tsxexamples/ts-react-search/src/components/TableSummary.tsxexamples/ts-react-search/src/components/ui/README.mdexamples/ts-react-search/src/components/ui/button.tsxexamples/ts-react-search/src/components/ui/calendar.tsxexamples/ts-react-search/src/components/ui/date-picker.tsxexamples/ts-react-search/src/components/ui/label.tsxexamples/ts-react-search/src/components/ui/popover.tsxexamples/ts-react-search/src/components/ui/select.tsxexamples/ts-react-search/src/components/ui/table.tsxexamples/ts-react-search/src/constants.tsexamples/ts-react-search/src/features/disputes/DisputesFilters.tsxexamples/ts-react-search/src/features/disputes/DisputesManager.tsxexamples/ts-react-search/src/features/disputes/DisputesTable.tsxexamples/ts-react-search/src/features/disputes/constants.tsexamples/ts-react-search/src/features/disputes/data.tsexamples/ts-react-search/src/features/disputes/disputesCollection.tsexamples/ts-react-search/src/features/disputes/types.tsexamples/ts-react-search/src/features/disputes/useDisputesQuery.tsexamples/ts-react-search/src/features/orders/OrdersFilters.tsxexamples/ts-react-search/src/features/orders/OrdersManager.tsxexamples/ts-react-search/src/features/orders/OrdersTable.tsxexamples/ts-react-search/src/features/orders/constants.tsexamples/ts-react-search/src/features/orders/data.tsexamples/ts-react-search/src/features/orders/ordersCollection.tsexamples/ts-react-search/src/features/orders/types.tsexamples/ts-react-search/src/features/orders/useOrdersQuery.tsexamples/ts-react-search/src/features/settlements/SettlementsFilters.tsxexamples/ts-react-search/src/features/settlements/SettlementsManager.tsxexamples/ts-react-search/src/features/settlements/SettlementsTable.tsxexamples/ts-react-search/src/features/settlements/constants.tsexamples/ts-react-search/src/features/settlements/data.tsexamples/ts-react-search/src/features/settlements/settlementsCollection.tsexamples/ts-react-search/src/features/settlements/types.tsexamples/ts-react-search/src/features/settlements/useSettlementsQuery.tsexamples/ts-react-search/src/hooks/useSpeechRecognition.tsexamples/ts-react-search/src/queryClient.tsexamples/ts-react-search/src/routeTree.gen.tsexamples/ts-react-search/src/router.tsxexamples/ts-react-search/src/routes/__root.tsxexamples/ts-react-search/src/routes/_layout/disputes.tsxexamples/ts-react-search/src/routes/_layout/orders.tsxexamples/ts-react-search/src/routes/_layout/route.tsxexamples/ts-react-search/src/routes/_layout/settlements.tsxexamples/ts-react-search/src/routes/api/disputes.tsexamples/ts-react-search/src/routes/api/orders.tsexamples/ts-react-search/src/routes/api/search.tsexamples/ts-react-search/src/routes/api/settlements.tsexamples/ts-react-search/src/routes/index.tsxexamples/ts-react-search/src/speech.d.tsexamples/ts-react-search/src/styles.cssexamples/ts-react-search/src/types.tsexamples/ts-react-search/src/utils/cn.tsexamples/ts-react-search/src/utils/formatDate.tsexamples/ts-react-search/src/utils/getBaseUrl.tsexamples/ts-react-search/tsconfig.jsonexamples/ts-react-search/vite.config.ts
✅ Files skipped from review due to trivial changes (1)
- examples/ts-react-search/.vscode/settings.json
🚧 Files skipped from review as they are similar to previous changes (51)
- examples/ts-react-search/.gitignore
- examples/ts-react-search/src/components/ui/label.tsx
- examples/ts-react-search/src/components/HeroSection/Navigation.tsx
- examples/ts-react-search/src/components/HeroSection/index.ts
- examples/ts-react-search/src/queryClient.ts
- examples/ts-react-search/src/features/orders/types.ts
- examples/ts-react-search/src/routes/index.tsx
- examples/ts-react-search/src/components/ui/calendar.tsx
- examples/ts-react-search/src/router.tsx
- examples/ts-react-search/src/components/HeroSection/Search/index.ts
- examples/ts-react-search/src/routes/_layout/orders.tsx
- examples/ts-react-search/public/manifest.json
- examples/ts-react-search/src/components/FilterSelect.tsx
- examples/ts-react-search/src/routes/_layout/route.tsx
- examples/ts-react-search/src/features/settlements/constants.ts
- examples/ts-react-search/src/components/HeroSection/HeroSection.tsx
- examples/ts-react-search/package.json
- examples/ts-react-search/src/utils/cn.ts
- examples/ts-react-search/src/features/orders/data.ts
- examples/ts-react-search/src/routes/_layout/disputes.tsx
- examples/ts-react-search/src/features/orders/useOrdersQuery.ts
- examples/ts-react-search/vite.config.ts
- examples/ts-react-search/src/routes/_layout/settlements.tsx
- examples/ts-react-search/src/features/disputes/types.ts
- examples/ts-react-search/src/features/disputes/data.ts
- examples/ts-react-search/src/features/orders/ordersCollection.ts
- examples/ts-react-search/src/utils/formatDate.ts
- examples/ts-react-search/src/components/HeroSection/Search/QuickPrompts.tsx
- examples/ts-react-search/src/features/orders/OrdersManager.tsx
- examples/ts-react-search/tsconfig.json
- examples/ts-react-search/src/components/ui/button.tsx
- examples/ts-react-search/.cta.json
- examples/ts-react-search/src/features/orders/constants.ts
- examples/ts-react-search/src/components/HeroSection/Brand.tsx
- examples/ts-react-search/src/routes/api/search.ts
- examples/ts-react-search/src/routes/api/settlements.ts
- examples/ts-react-search/src/styles.css
- examples/ts-react-search/src/features/settlements/SettlementsTable.tsx
- examples/ts-react-search/public/robots.txt
- examples/ts-react-search/src/speech.d.ts
- examples/ts-react-search/src/components/HeroSection/Search/Search.tsx
- examples/ts-react-search/src/features/settlements/SettlementsFilters.tsx
- examples/ts-react-search/src/features/orders/OrdersFilters.tsx
- examples/ts-react-search/src/features/disputes/useDisputesQuery.ts
- examples/ts-react-search/src/features/settlements/SettlementsManager.tsx
- examples/ts-react-search/src/components/ui/popover.tsx
- examples/ts-react-search/src/hooks/useSpeechRecognition.ts
- examples/ts-react-search/src/components/ui/README.md
- examples/ts-react-search/src/features/settlements/settlementsCollection.ts
- examples/ts-react-search/src/components/HeroSection/ProjectDescription.tsx
- examples/ts-react-search/src/components/TableSummary.tsx
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use tree-shakeable adapter architecture for provider implementations - export specialized adapters (text, embedding, summarize, image) as separate imports from/adapterssubpath rather than monolithic adapters
Use Zod for runtime schema validation and type inference, particularly for tool input/output definitions withtoolDefinition()and Zod schema inference
Implement isomorphic tool system usingtoolDefinition()with.server()and.client()implementations for dual-environment execution
Use type-safe per-model configuration with provider options typed based on selected model to ensure compile-time safety
Implement stream processing with StreamProcessor for handling chunked responses and support partial JSON parsing for streaming AI responses
Files:
examples/ts-react-search/src/features/disputes/disputesCollection.tsexamples/ts-react-search/src/features/settlements/types.tsexamples/ts-react-search/src/features/settlements/data.tsexamples/ts-react-search/src/components/ui/date-picker.tsxexamples/ts-react-search/src/routes/api/disputes.tsexamples/ts-react-search/src/constants.tsexamples/ts-react-search/src/components/ui/table.tsxexamples/ts-react-search/src/components/HeroSection/Search/SearchForm.tsxexamples/ts-react-search/src/features/disputes/DisputesManager.tsxexamples/ts-react-search/src/features/disputes/constants.tsexamples/ts-react-search/src/routes/api/orders.tsexamples/ts-react-search/src/types.tsexamples/ts-react-search/src/routes/__root.tsxexamples/ts-react-search/src/routeTree.gen.tsexamples/ts-react-search/src/features/settlements/useSettlementsQuery.tsexamples/ts-react-search/src/features/orders/OrdersTable.tsxexamples/ts-react-search/src/components/ui/select.tsxexamples/ts-react-search/src/features/disputes/DisputesTable.tsxexamples/ts-react-search/src/utils/getBaseUrl.tsexamples/ts-react-search/src/components/Spinner.tsxexamples/ts-react-search/src/features/disputes/DisputesFilters.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use camelCase for function and variable names throughout the codebase
Files:
examples/ts-react-search/src/features/disputes/disputesCollection.tsexamples/ts-react-search/src/features/settlements/types.tsexamples/ts-react-search/src/features/settlements/data.tsexamples/ts-react-search/src/components/ui/date-picker.tsxexamples/ts-react-search/src/routes/api/disputes.tsexamples/ts-react-search/src/constants.tsexamples/ts-react-search/src/components/ui/table.tsxexamples/ts-react-search/src/components/HeroSection/Search/SearchForm.tsxexamples/ts-react-search/src/features/disputes/DisputesManager.tsxexamples/ts-react-search/src/features/disputes/constants.tsexamples/ts-react-search/src/routes/api/orders.tsexamples/ts-react-search/src/types.tsexamples/ts-react-search/src/routes/__root.tsxexamples/ts-react-search/src/routeTree.gen.tsexamples/ts-react-search/src/features/settlements/useSettlementsQuery.tsexamples/ts-react-search/src/features/orders/OrdersTable.tsxexamples/ts-react-search/src/components/ui/select.tsxexamples/ts-react-search/src/features/disputes/DisputesTable.tsxexamples/ts-react-search/src/utils/getBaseUrl.tsexamples/ts-react-search/src/components/Spinner.tsxexamples/ts-react-search/src/features/disputes/DisputesFilters.tsx
examples/**
📄 CodeRabbit inference engine (CLAUDE.md)
Examples are not built by Nx and should be run independently from their directories with
pnpm devorpnpm install && pnpm dev
Files:
examples/ts-react-search/src/features/disputes/disputesCollection.tsexamples/ts-react-search/src/features/settlements/types.tsexamples/ts-react-search/src/features/settlements/data.tsexamples/ts-react-search/src/components/ui/date-picker.tsxexamples/ts-react-search/src/routes/api/disputes.tsexamples/ts-react-search/src/constants.tsexamples/ts-react-search/src/components/ui/table.tsxexamples/ts-react-search/src/components/HeroSection/Search/SearchForm.tsxexamples/ts-react-search/src/features/disputes/DisputesManager.tsxexamples/ts-react-search/src/features/disputes/constants.tsexamples/ts-react-search/src/routes/api/orders.tsexamples/ts-react-search/src/types.tsexamples/ts-react-search/src/routes/__root.tsxexamples/ts-react-search/src/routeTree.gen.tsexamples/ts-react-search/src/features/settlements/useSettlementsQuery.tsexamples/ts-react-search/src/features/orders/OrdersTable.tsxexamples/ts-react-search/src/components/ui/select.tsxexamples/ts-react-search/src/features/disputes/DisputesTable.tsxexamples/ts-react-search/src/utils/getBaseUrl.tsexamples/ts-react-search/src/components/Spinner.tsxexamples/ts-react-search/src/features/disputes/DisputesFilters.tsxexamples/ts-react-search/README.md
🧠 Learnings (6)
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Use Zod for runtime schema validation and type inference, particularly for tool input/output definitions with `toolDefinition()` and Zod schema inference
Applied to files:
examples/ts-react-search/src/features/settlements/types.tsexamples/ts-react-search/src/features/disputes/constants.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/index.ts : Export tree-shakeable adapters with clear subpath exports in package.json (e.g., `tanstack/ai/adapters`, `tanstack/ai-openai/adapters`) to minimize bundle size
Applied to files:
examples/ts-react-search/src/routeTree.gen.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Use tree-shakeable adapter architecture for provider implementations - export specialized adapters (text, embedding, summarize, image) as separate imports from `/adapters` subpath rather than monolithic adapters
Applied to files:
examples/ts-react-search/src/routeTree.gen.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/adapters/*.ts : Create individual adapter implementations for each provider capability (text, embed, summarize, image) with separate exports to enable tree-shaking
Applied to files:
examples/ts-react-search/src/routeTree.gen.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to .eslintrc* : Use ESLint with custom TanStack config for linting all TypeScript and JavaScript files
Applied to files:
examples/ts-react-search/README.md
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Implement framework integrations using the headless `tanstack/ai-client` for state management with framework-specific hooks (useChat) on top
Applied to files:
examples/ts-react-search/README.md
🧬 Code graph analysis (12)
examples/ts-react-search/src/features/disputes/disputesCollection.ts (1)
examples/ts-react-search/src/features/disputes/constants.ts (1)
disputeSchema(37-43)
examples/ts-react-search/src/features/settlements/types.ts (1)
examples/ts-react-search/src/features/settlements/constants.ts (3)
SETTLEMENT_CURRENCIES(5-13)settlementSchema(25-30)settlementsSearchSchema(32-36)
examples/ts-react-search/src/features/settlements/data.ts (1)
examples/ts-react-search/src/features/settlements/types.ts (1)
Settlement(10-10)
examples/ts-react-search/src/components/ui/date-picker.tsx (4)
examples/ts-react-search/src/components/ui/label.tsx (1)
Label(24-24)examples/ts-react-search/src/components/ui/popover.tsx (3)
Popover(56-56)PopoverTrigger(56-56)PopoverContent(56-56)examples/ts-react-search/src/components/ui/button.tsx (1)
Button(61-61)examples/ts-react-search/src/components/ui/calendar.tsx (1)
Calendar(92-92)
examples/ts-react-search/src/components/HeroSection/Search/SearchForm.tsx (1)
examples/ts-react-search/src/hooks/useSpeechRecognition.ts (1)
useSpeechRecognition(10-92)
examples/ts-react-search/src/features/disputes/DisputesManager.tsx (1)
examples/ts-react-search/src/features/disputes/types.ts (1)
DisputesSearch(15-15)
examples/ts-react-search/src/features/disputes/constants.ts (1)
examples/ts-react-search/src/features/disputes/types.ts (2)
DisputeStatus(9-9)DisputeReason(11-11)
examples/ts-react-search/src/routes/__root.tsx (2)
examples/ts-react-search/src/routes/_layout/route.tsx (1)
Route(3-5)examples/ts-react-search/src/routes/index.tsx (1)
Route(3-3)
examples/ts-react-search/src/features/settlements/useSettlementsQuery.ts (1)
examples/ts-react-search/src/features/settlements/types.ts (1)
SettlementsSearch(12-12)
examples/ts-react-search/src/features/orders/OrdersTable.tsx (2)
examples/ts-react-search/src/features/orders/types.ts (1)
Order(13-13)examples/ts-react-search/src/components/ui/table.tsx (6)
Table(108-108)TableHeader(109-109)TableRow(113-113)TableHead(112-112)TableBody(110-110)TableCell(114-114)
examples/ts-react-search/src/features/disputes/DisputesTable.tsx (2)
examples/ts-react-search/src/features/disputes/types.ts (1)
Dispute(13-13)examples/ts-react-search/src/components/ui/table.tsx (6)
Table(108-108)TableHeader(109-109)TableRow(113-113)TableHead(112-112)TableBody(110-110)TableCell(114-114)
examples/ts-react-search/src/features/disputes/DisputesFilters.tsx (5)
examples/ts-react-search/src/features/disputes/types.ts (1)
DisputesSearch(15-15)examples/ts-react-search/src/constants.ts (1)
ALL_OPTION(1-1)examples/ts-react-search/src/features/disputes/constants.ts (3)
disputesSearchSchema(45-50)DISPUTE_STATUS_MAP(12-17)DISPUTE_REASON_MAP(28-35)examples/ts-react-search/src/components/ui/date-picker.tsx (1)
DatePicker(26-66)examples/ts-react-search/src/components/ui/button.tsx (1)
Button(61-61)
🪛 LanguageTool
examples/ts-react-search/README.md
[grammar] ~34-~34: Use a hyphen to join words.
Context: ...com/router). The initial setup is a file based router. Which means that the route...
(QB_NEW_EN_HYPHEN)
[grammar] ~125-~125: Use a hyphen to join words.
Context: ... }, }) ``` Loaders simplify your data fetching logic dramatically. Check out m...
(QB_NEW_EN_HYPHEN)
[grammar] ~129-~129: Ensure spelling is correct
Context: ...o route loading and integrating it into you application is a breeze. First add you...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~212-~212: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...ting point for your project. First you need to add TanStack Store as a dependency: ``...
(REP_NEED_TO_VB)
[style] ~287-~287: Consider removing “of” to be more concise
Context: ... # Learn More You can learn more about all of the offerings from TanStack in the [TanStac...
(ALL_OF_THE)
⏰ 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). (2)
- GitHub Check: Test
- GitHub Check: Preview
🔇 Additional comments (19)
examples/ts-react-search/src/components/ui/date-picker.tsx (1)
26-66: LGTM!The component is well-structured with proper accessibility (label association via
useId), clean composition of UI primitives, and sensible defaults. The use offormatDatefor display and ISO strings for data exchange is a good pattern.examples/ts-react-search/src/features/orders/OrdersTable.tsx (1)
16-54: LGTM!The component follows good patterns: proper empty state handling with matching
colSpan, semantic table structure, and consistent use of the sharedformatDateutility. The use ofkey={order.id}ensures stable rendering.examples/ts-react-search/src/features/disputes/constants.ts (1)
37-50: Good use of Zod for runtime schema validation.The schema definitions follow the coding guidelines for using Zod with proper enum validation and the
fallbackadapter for optional search parameters. The use ofz.iso.datetime()for date fields ensures proper ISO format validation.examples/ts-react-search/src/components/ui/table.tsx (1)
7-105: LGTM!Well-structured table primitives with proper TypeScript typing via
React.ComponentProps, clean class composition usingcn(), and consistentdata-slotattributes for styling/testing hooks. The responsive wrapper inTableis a good accessibility pattern.examples/ts-react-search/src/routeTree.gen.ts (1)
1-10: Auto-generated file - no review needed.This file is auto-generated by TanStack Router as indicated by the header comments. Manual changes would be overwritten, and the file is excluded from linting/formatting by design.
examples/ts-react-search/src/utils/getBaseUrl.ts (1)
1-7: LGTM!Clean isomorphic utility that correctly handles browser vs. server environments. Returning an empty string for browser enables relative URLs (same-origin requests), while server-side gets a full URL for internal API calls during SSR.
examples/ts-react-search/src/routes/api/orders.ts (1)
5-11: LGTM!Simple API route for the example. The hardcoded data approach aligns with the PR objectives noting this is intentional for now, with plans to migrate to TanStack Query or TanStack DB later.
examples/ts-react-search/src/features/disputes/DisputesTable.tsx (1)
16-56: LGTM!The table component is well-structured with proper empty state handling, appropriate use of Table UI components, and correct date formatting. The column layout correctly maps to the dispute schema fields.
examples/ts-react-search/src/routes/api/disputes.ts (1)
5-11: LGTM!The API route follows the established pattern for serving data endpoints and correctly returns the DISPUTES dataset via the GET handler.
examples/ts-react-search/src/features/disputes/disputesCollection.ts (1)
8-20: LGTM!The collection is properly configured with appropriate query options, Zod schema validation (per coding guidelines), and correct item identification via the
getKeyfunction.examples/ts-react-search/src/features/disputes/DisputesManager.tsx (1)
20-20: No issue found –toArrayis a property getter, not a method.The code correctly accesses
toArrayas a property. According to the @tanstack/react-db Collection API,toArrayis a getter that returns an array directly (get toArray(): T[]), not a method that requires invocation. The usagedisputesCollection.toArray.lengthis correct.Likely an incorrect or invalid review comment.
examples/ts-react-search/src/components/HeroSection/Search/SearchForm.tsx (2)
15-20: Consider exportingSearchFormPropsif it's part of the public API.The AI summary mentions that
SearchFormPropsis a public exported type, but it's currently not exported. If consumers of this component need access to these prop types, add an export.📦 Proposed export addition
-type SearchFormProps = { +export type SearchFormProps = { value: string onChange: (value: string) => void onSubmit: (event: FormEvent) => void isLoading: boolean }
1-1: The'use client'directive is appropriate and necessary for this component. TanStack Start supports React's'use client'directive for marking components that require client-side execution. The SearchForm component uses theuseSpeechRecognitionhook, which is browser-dependent and requires client-side rendering. This directive is used consistently throughout the example project and is not a leftover artifact.Likely an incorrect or invalid review comment.
examples/ts-react-search/src/components/ui/select.tsx (2)
175-186: LGTM!All component exports are properly listed and match the components defined in the file.
4-4: No action needed. The import statement is correct.The
radix-uipackage (version ^1.4.3) is properly installed in the project dependencies. The importimport { Select as SelectPrimitive } from 'radix-ui'is the correct way to access the Select component from this package. The proposed change to import from@radix-ui/react-selectwould cause a module resolution error since that package is not installed in this project.Likely an incorrect or invalid review comment.
examples/ts-react-search/src/features/settlements/useSettlementsQuery.ts (2)
1-3: LGTM: Imports are clean and well-organized.The imports follow camelCase naming conventions and correctly import the necessary utilities from
@tanstack/react-db.
21-21: LGTM: Export follows conventions.The default export follows camelCase naming conventions.
examples/ts-react-search/src/features/settlements/types.ts (1)
1-12: LGTM: Proper use of Zod type inference.This file correctly uses Zod's
z.inferfor type derivation, which aligns with the coding guidelines. The type definitions are clean and follow best practices.Based on coding guidelines, Zod should be used for runtime schema validation and type inference.
examples/ts-react-search/src/features/settlements/data.ts (1)
1-64: LGTM: Clean mock data structure.The static settlement data is properly typed and provides reasonable test data for the example. The structure is consistent across all entries.
| ```bash | ||
| pnpm install | ||
| pnpm start |
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.
Update startup command to match the coding guidelines for examples.
Per the coding guidelines, examples should be run independently with pnpm dev or pnpm install && pnpm dev, not pnpm start.
🔧 Proposed fix
- pnpm install
- pnpm start
+ pnpm install
+ pnpm dev📝 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.
| ```bash | |
| pnpm install | |
| pnpm start |
🤖 Prompt for AI Agents
In @examples/ts-react-search/README.md around lines 7 - 9, Update the startup
command in the README examples to follow the guidelines: replace any usage of
"pnpm start" with "pnpm dev" and provide the alternate combined form "pnpm
install && pnpm dev" so users can run the example independently; ensure both
occurrences in the README (the code block showing installation/startup) are
updated accordingly.
| useEffect(() => { | ||
| if (transcript) { | ||
| onChange(transcript) | ||
| } | ||
| }, [transcript]) |
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.
Add onChange to the useEffect dependency array.
The useEffect hook uses onChange but doesn't include it in the dependency array, violating the React hooks exhaustive-deps rule. This can lead to stale closure bugs if the onChange callback changes between renders.
🔧 Proposed fix
useEffect(() => {
if (transcript) {
onChange(transcript)
}
- }, [transcript])
+ }, [transcript, onChange])📝 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.
| useEffect(() => { | |
| if (transcript) { | |
| onChange(transcript) | |
| } | |
| }, [transcript]) | |
| useEffect(() => { | |
| if (transcript) { | |
| onChange(transcript) | |
| } | |
| }, [transcript, onChange]) |
🤖 Prompt for AI Agents
In @examples/ts-react-search/src/components/HeroSection/Search/SearchForm.tsx
around lines 26 - 30, The useEffect in SearchForm currently depends on
transcript but references onChange without including it in the dependency array;
update the effect declaration (the useEffect that calls onChange(transcript)) to
include onChange in the dependency array (e.g., [transcript, onChange]) so the
hook responds correctly if the onChange callback changes.
| function Spinner() { | ||
| return <LoaderCircleIcon className="animate-spin size-4 m-auto" /> | ||
| } |
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.
Add accessibility attributes for screen readers.
The spinner lacks semantic information for assistive technologies. Loading indicators should announce their state to screen reader users.
♿ Proposed fix to add accessibility support
function Spinner() {
- return <LoaderCircleIcon className="animate-spin size-4 m-auto" />
+ return (
+ <div role="status" aria-live="polite" aria-label="Loading">
+ <LoaderCircleIcon className="animate-spin size-4 m-auto" aria-hidden="true" />
+ </div>
+ )
}📝 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.
| function Spinner() { | |
| return <LoaderCircleIcon className="animate-spin size-4 m-auto" /> | |
| } | |
| function Spinner() { | |
| return ( | |
| <div role="status" aria-live="polite" aria-label="Loading"> | |
| <LoaderCircleIcon className="animate-spin size-4 m-auto" aria-hidden="true" /> | |
| </div> | |
| ) | |
| } |
🤖 Prompt for AI Agents
In @examples/ts-react-search/src/components/Spinner.tsx around lines 3 - 5, The
Spinner component currently returns only a decorative LoaderCircleIcon and lacks
accessibility semantics; update Spinner to provide screen-reader information by
marking the icon as decorative (aria-hidden="true") and adding a status region
(e.g., a wrapper element with role="status" and aria-live="polite") that
contains a visually hidden text node like "Loading…" so assistive tech announces
the loading state; use the existing function name Spinner and LoaderCircleIcon
to locate where to add the role/aria-live wrapper and the sr-only text.
| @@ -0,0 +1,186 @@ | |||
| 'use client' | |||
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.
🧩 Analysis chain
🏁 Script executed:
# First, let's examine the example project structure
find examples/ts-react-search -type f -name "package.json" -o -name "tsconfig.json" -o -name "*.config.*" | head -20Repository: TanStack/ai
Length of output: 171
🏁 Script executed:
# Check the example directory structure
ls -la examples/ts-react-search/ 2>/dev/null || echo "Directory not found"Repository: TanStack/ai
Length of output: 710
🏁 Script executed:
# Look at the package.json to see what framework is being used
cat examples/ts-react-search/package.json 2>/dev/null || echo "File not found"Repository: TanStack/ai
Length of output: 1704
🌐 Web query:
TanStack Start 'use client' directive client-side components
💡 Result:
Short answer: TanStack Start is "client-first" — components and routes run on the client by default, so you rarely need the React "'use client'" directive there. Instead Start exposes explicit server functions / server middleware for server-only work (DB, secrets, etc.), letting your UI remain client components that call those server functions. If you’re embedding Start UI into a framework that uses React Server Components (e.g., Next.js app router) you still must use "'use client'" where that host framework requires client components (for hooks, context providers, hydration). Sources: TanStack Start docs and TanStack Query SSR guide. [1][2][3]
- Why: Start’s model separates “server functions” (explicit server-side APIs) from client UI, avoiding the file-by-file client/server marking that Next’s RSC model uses. [1][3]
- When to still use 'use client': when using features that require client-only React APIs (useState/useEffect/hooks, QueryClientProvider that relies on context) or when embedding Start into an RSC host (Next.js) which enforces the directive. [2][3]
References
[1] TanStack Start comparison / architecture (server functions vs Next.js).
[2] TanStack Query Advanced SSR (example showing 'use client' for QueryClientProvider).
[3] Analysis/article on Start's client-first RSC approach.
🏁 Script executed:
cat -n examples/ts-react-search/src/components/ui/select.tsx | head -50Repository: TanStack/ai
Length of output: 2304
🏁 Script executed:
# Check if the component uses any client-only hooks or context
rg -A 5 "useState|useEffect|useContext|use[A-Z]" examples/ts-react-search/src/components/ui/select.tsxRepository: TanStack/ai
Length of output: 37
🏁 Script executed:
# View the entire select.tsx file to check for all client-only APIs
wc -l examples/ts-react-search/src/components/ui/select.tsxRepository: TanStack/ai
Length of output: 112
🏁 Script executed:
# Get the full file content
cat examples/ts-react-search/src/components/ui/select.tsxRepository: TanStack/ai
Length of output: 5963
Remove the 'use client' directive.
This example uses TanStack Start (as shown in package.json with "@tanstack/react-start"), which is client-first by default. The 'use client' directive is a Next.js App Router pattern and is not needed here. The Select component is a pure wrapper around Radix UI primitives with no React hooks, context providers, or other client-only APIs—Radix UI handles interactivity internally. Removing the directive aligns with TanStack Start's conventions.
🤖 Prompt for AI Agents
In @examples/ts-react-search/src/components/ui/select.tsx at line 1, Remove the
top-level 'use client' directive from the file—this Select component is a pure
wrapper around Radix primitives and does not use React hooks or client-only
APIs, and TanStack Start is client-first; simply delete the "'use client'" line
at the top of examples/ts-react-search/src/components/ui/select.tsx so the
Select component (the exported Select wrapper around Radix) conforms to the
project conventions.
| import { z } from 'zod' | ||
| import { fallback } from '@tanstack/zod-adapter' | ||
| import type { DisputeReason, DisputeStatus } from './types' | ||
|
|
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.
Circular dependency between constants.ts and types.ts.
This file imports DisputeReason and DisputeStatus from ./types, but based on the snippets, types.ts derives these types from constants exported here (e.g., export type DisputeStatus = (typeof DISPUTE_STATUSES)[number]). This creates a circular import that may cause runtime issues or undefined values depending on module resolution order.
Consider inlining the type derivation in this file or restructuring to avoid the cycle:
🔧 Option: Derive types inline in constants.ts
import { z } from 'zod'
import { fallback } from '@tanstack/zod-adapter'
-import type { DisputeReason, DisputeStatus } from './types'
+
+// Derive types inline to avoid circular dependency
+type DisputeStatus = (typeof DISPUTE_STATUSES)[number]
+type DisputeReason = (typeof DISPUTE_REASONS)[number]
export const DISPUTE_STATUSES = [Then export these types from constants.ts and re-export from types.ts if needed.
📝 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.
| import { z } from 'zod' | |
| import { fallback } from '@tanstack/zod-adapter' | |
| import type { DisputeReason, DisputeStatus } from './types' | |
| import { z } from 'zod' | |
| import { fallback } from '@tanstack/zod-adapter' | |
| // Derive types inline to avoid circular dependency | |
| type DisputeStatus = (typeof DISPUTE_STATUSES)[number] | |
| type DisputeReason = (typeof DISPUTE_REASONS)[number] | |
🤖 Prompt for AI Agents
In @examples/ts-react-search/src/features/disputes/constants.ts around lines 1 -
4, There is a circular import between constants.ts and types.ts because
constants.ts imports DisputeReason/DisputeStatus that are actually derived from
constants here (e.g., DISPUTE_STATUSES). Fix by removing the imports from
types.ts in constants.ts, derive and export the types inline in constants.ts
(e.g., export type DisputeStatus = (typeof DISPUTE_STATUSES)[number] and same
for DisputeReason), and then update types.ts to re-export those types from
constants.ts if other modules expect them; ensure all references use the
exported types from constants.ts to break the cycle.
| <FilterSelect | ||
| id="resason" | ||
| label="Reason" | ||
| value={pendingReason} | ||
| onChange={setPendingReason} | ||
| options={Object.entries(DISPUTE_REASON_MAP)} | ||
| /> |
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 typo in id attribute.
Line 71 has a typo: id="resason" should be id="reason".
📝 Proposed fix
<FilterSelect
- id="resason"
+ id="reason"
label="Reason"
value={pendingReason}
onChange={setPendingReason}
options={Object.entries(DISPUTE_REASON_MAP)}
/>📝 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.
| <FilterSelect | |
| id="resason" | |
| label="Reason" | |
| value={pendingReason} | |
| onChange={setPendingReason} | |
| options={Object.entries(DISPUTE_REASON_MAP)} | |
| /> | |
| <FilterSelect | |
| id="reason" | |
| label="Reason" | |
| value={pendingReason} | |
| onChange={setPendingReason} | |
| options={Object.entries(DISPUTE_REASON_MAP)} | |
| /> |
🤖 Prompt for AI Agents
In @examples/ts-react-search/src/features/disputes/DisputesFilters.tsx around
lines 70 - 76, The id prop on the FilterSelect component is misspelled; change
id="resason" to id="reason" in the FilterSelect usage (the component that sets
id, label="Reason", value={pendingReason}, onChange={setPendingReason},
options={Object.entries(DISPUTE_REASON_MAP)}) so the id matches the label and
other logic that may reference "reason".
| function useSettlementsQuery(search: SettlementsSearch) { | ||
| return useLiveQuery( | ||
| (query) => | ||
| query | ||
| .from({ settlement: settlementsCollection }) | ||
| .where(({ settlement }) => | ||
| and( | ||
| eq(settlement.currency, search.currency ?? settlement.currency), | ||
| gte(settlement.from, search.from ?? settlement.from), | ||
| lte(settlement.to, search.to ?? settlement.to), | ||
| ), | ||
| ), | ||
| [search.currency, search.from, search.to], | ||
| ) | ||
| } |
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.
🧩 Analysis chain
🏁 Script executed:
# First, let's examine the actual file
cat -n examples/ts-react-search/src/features/settlements/useSettlementsQuery.tsRepository: TanStack/ai
Length of output: 907
🏁 Script executed:
# Let's find and examine the SettlementsSearch type
find examples/ts-react-search/src -name "*.ts" -o -name "*.tsx" | xargs grep -l "SettlementsSearch"Repository: TanStack/ai
Length of output: 332
🏁 Script executed:
# Search for similar patterns in orders and disputes hooks as mentioned in the review
find examples/ts-react-search/src/features -name "*useQuery.ts" -o -name "*useQuery.tsx"Repository: TanStack/ai
Length of output: 37
🏁 Script executed:
# Look for the and() function definition
rg -n "and\s*\(" examples/ts-react-search/src --type ts -A 2 -B 1 | head -30Repository: TanStack/ai
Length of output: 1795
🏁 Script executed:
# Check the SettlementsSearch type
cat -n examples/ts-react-search/src/features/settlements/types.tsRepository: TanStack/ai
Length of output: 475
🏁 Script executed:
# Check the full useOrdersQuery hook
cat -n examples/ts-react-search/src/features/orders/useOrdersQuery.tsRepository: TanStack/ai
Length of output: 999
🏁 Script executed:
# Check the full useDisputesQuery hook
cat -n examples/ts-react-search/src/features/disputes/useDisputesQuery.tsRepository: TanStack/ai
Length of output: 941
🏁 Script executed:
# Search for and() function documentation or import details
rg -n "export.*and" --type ts -A 5 | head -40Repository: TanStack/ai
Length of output: 3684
🏁 Script executed:
# Check the settlements constants and schema
cat -n examples/ts-react-search/src/features/settlements/constants.tsRepository: TanStack/ai
Length of output: 1110
🏁 Script executed:
# Check orders and disputes constants
cat -n examples/ts-react-search/src/features/orders/constants.tsRepository: TanStack/ai
Length of output: 1610
🏁 Script executed:
# Check disputes constants
cat -n examples/ts-react-search/src/features/disputes/constants.tsRepository: TanStack/ai
Length of output: 1754
🏁 Script executed:
# Search for @tanstack/react-db to understand the and() function behavior
rg -n "and" examples/ts-react-search --type ts --type tsx -B 5 -A 10 | grep -A 15 "react-db"Repository: TanStack/ai
Length of output: 82
🏁 Script executed:
# Check if there are any tests or documentation about the and() function
find examples/ts-react-search -name "*.test.*" -o -name "*.spec.*" | head -10Repository: TanStack/ai
Length of output: 37
Critical: Filter logic creates tautologies that don't filter results.
The nullish coalescing pattern in the where clause creates tautological conditions when search parameters are undefined:
eq(settlement.currency, search.currency ?? settlement.currency)becomescurrency === currency(always true)gte(settlement.from, search.from ?? settlement.from)becomesfrom >= from(always true)lte(settlement.to, search.to ?? settlement.to)becomesto <= to(always true)
This means the filters never actually filter when search parameters are undefined—all records will match regardless of the search criteria. The same issue exists in useOrdersQuery.ts and useDisputesQuery.ts.
🔧 Proposed fix: Conditionally apply filters
function useSettlementsQuery(search: SettlementsSearch) {
return useLiveQuery(
(query) =>
query
.from({ settlement: settlementsCollection })
.where(({ settlement }) =>
and(
- eq(settlement.currency, search.currency ?? settlement.currency),
- gte(settlement.from, search.from ?? settlement.from),
- lte(settlement.to, search.to ?? settlement.to),
+ search.currency !== undefined
+ ? eq(settlement.currency, search.currency)
+ : undefined,
+ search.from !== undefined
+ ? gte(settlement.from, search.from)
+ : undefined,
+ search.to !== undefined
+ ? lte(settlement.to, search.to)
+ : undefined,
),
),
[search.currency, search.from, search.to],
)
}Note: Verify that and() properly handles undefined values by filtering them out. If not, you may need to build the conditions array dynamically.
🤖 Prompt for AI Agents
In @examples/ts-react-search/src/features/settlements/useSettlementsQuery.ts
around lines 5 - 19, The where-clause uses nullish coalescing which creates
tautologies (e.g., eq(settlement.currency, search.currency ??
settlement.currency)) so filters never apply; update useSettlementsQuery (and
analogously useOrdersQuery and useDisputesQuery) to build the predicate list
conditionally: inside the useLiveQuery callback, assemble an array of condition
expressions only when search.currency, search.from, search.to (or their
equivalents) are defined and then pass that array into and(...) (or call and
with spread of the filtered array); ensure you reference settlementsCollection
and the settlement alias when creating the conditional predicates so undefined
search fields are not turned into self-comparisons.
| @@ -0,0 +1 @@ | |||
| export type ISO8601UTC = 'ISO-8601 UTC' | |||
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.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find all usages of ISO8601UTC type in the codebase
rg -n --type=ts --type=tsx '\bISO8601UTC\b' examples/ts-react-search/ -A 2 -B 2Repository: TanStack/ai
Length of output: 82
🏁 Script executed:
#!/bin/bash
# Find all usages of ISO8601UTC type in the codebase
rg -n '\bISO8601UTC\b' examples/ts-react-search/ -A 2 -B 2Repository: TanStack/ai
Length of output: 134
🏁 Script executed:
#!/bin/bash
# Read the full types.ts file
echo "=== Content of types.ts ==="
cat -n examples/ts-react-search/src/types.ts
echo ""
echo "=== Files importing from types.ts ==="
rg -n "from.*types" examples/ts-react-search/ -A 1 -B 1Repository: TanStack/ai
Length of output: 5188
Remove the unused ISO8601UTC type export.
This type is defined but never imported or used anywhere in the example. Dead code should be removed to keep the example clean and maintainable.
🤖 Prompt for AI Agents
In @examples/ts-react-search/src/types.ts at line 1, Remove the unused exported
type ISO8601UTC: delete the line "export type ISO8601UTC = 'ISO-8601 UTC'" from
the types file and ensure no other code relies on ISO8601UTC; if any references
exist, replace them with the appropriate concrete type or remove those
references before deleting the export.
- Introduces a comprehensive React example demonstrating natural language search capabilities - Users can query merchant data (orders, disputes, settlements) using conversational language like "show me orders from last week" - AI converts natural language prompts into structured search parameters with proper filtering and date ranges - Includes full UI with data tables, filters, and responsive design using Tailwind CSS - Leverages TanStack Start, TanStack Router, TanStack AI
- Added a new Navigation component with links to Home, Orders, Disputes, and Settlements pages - Integrated navigation into the hero section for improved user experience
- Replace imported route objects with hardcoded string paths - Remove unused route imports
- Moved api.search.ts to api/search.ts for better organization - Updated route tree imports to reflect new file structure - Maintains existing functionality while improving code organization
- Replace server functions with TanStack DB collections and live queries - Add @tanstack/react-db, @tanstack/query-db-collection, and related packages - Implement disputes, orders, and settlements collections with Zod validation - Create useLiveQuery hooks for reactive data filtering and searching - Update components to use client-side collections instead of server functions
- Migrated from `toStreamResponse` to `toServerSentEventsResponse` for improved streaming - Updated OpenAI adapter to use `openaiText` with model specification - Updated multiple dependencies including React, TanStack Router, and TailwindCSS
…th structured validation - Replaced Server-Sent Events with React Query mutation for search requests - Added Zod schema validation for structured output in search API - Updated search component to handle JSON responses instead of streaming - Improved error handling and type safety for search parameters
993fd11 to
f43c9b4
Compare
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: 10
🤖 Fix all issues with AI agents
In @examples/ts-react-search/README.md:
- Line 129: Fix the typo in the README sentence that currently reads
"React-Query is an excellent addition or alternative to route loading and
integrating it into you application is a breeze." by replacing "you application"
with "your application" so the sentence reads "...into your application is a
breeze."
- Line 34: Update the README sentence to hyphenate the compound adjective:
change "file based router" to "file-based router" in the line describing the
initial setup so it reads "The initial setup is a file-based router." This fixes
the compound-adjective grammar while leaving the surrounding text unchanged.
- Line 125: Update the sentence "Loaders simplify your data fetching logic
dramatically." to use the compound adjective form by inserting a hyphen: change
"data fetching logic" to "data-fetching logic" (so it reads "Loaders simplify
your data-fetching logic dramatically."); no other changes needed.
- Around line 8-9: The README currently instructs "pnpm start" which doesn't
exist in package.json; update the startup command to "pnpm dev" so it matches
the actual script ("vite dev --port 3000") defined in package.json and project
example guidelines; edit the README line showing the two commands (the lines
with "pnpm install" and "pnpm start") to replace "pnpm start" with "pnpm dev".
In @examples/ts-react-search/src/features/settlements/SettlementsManager.tsx:
- Around line 19-22: The code uses settlementsCollection.toArray as a property
when computing totalCount; call the method instead. Update the TableSummary prop
to use settlementsCollection.toArray() so totalCount invokes the toArray()
function (and keep resultCount={settlements.length} unchanged), ensuring
settlementsCollection.toArray() is executed to return the array length.
In @examples/ts-react-search/src/hooks/useSpeechRecognition.ts:
- Around line 75-79: startListening currently calls
recognitionRef.current?.start() unconditionally which will throw
InvalidStateError if recognition is already active; add a guard in
startListening that returns early when recognition is already running by
checking a listening flag (e.g., add a listeningRef or isListening state updated
in recognition.onstart and recognition.onend) or by checking a custom property
on recognitionRef.current, then only call recognitionRef.current.start() when
not already listening; update the recognition onstart/onend handlers to
set/reset this flag so repeated calls to startListening are safe.
- Line 73: The effect in useSpeechRecognition re-triggers whenever the whole
options object identity changes (currently using [options?.lang,
options?.continuous, options?.interimResults]), which can still cause
re-initialization if options is recreated; destructure the primitive values from
options (e.g., const { lang, continuous, interimResults } = options ?? {})
outside the effect and use those primitives in the effect dependency array so
React compares by value, or alternatively store options in a ref and apply
changes only when individual values differ; update the effect to reference those
primitive names (lang, continuous, interimResults) instead of options to avoid
unnecessary teardown/recreation of the SpeechRecognition instance.
In @examples/ts-react-search/src/routes/__root.tsx:
- Around line 48-49: Replace the invalid Tailwind utility names used in the root
JSX: in the <body> element's className change "bg-linear-to-b" to
"bg-gradient-to-b" and in the surrounding <div> element's className change
"bg-linear-to-r" to "bg-gradient-to-r" so the gradient backgrounds render
correctly.
In @examples/ts-react-search/src/styles.css:
- Around line 9-10: The CSS defines --font-sans and --font-mono by pointing them
at undefined variables (--font-geist-sans, --font-geist-mono), so Tailwind's
font-sans/font-mono will be empty; fix by either defining the geist variables
(e.g., add :root { --font-geist-sans: "Inter, system-ui, sans-serif";
--font-geist-mono: "ui-monospace, SFMono-Regular, monospace"; }) or replace the
mappings to use concrete fallbacks directly (e.g., --font-sans: "Inter,
system-ui, sans-serif"; --font-mono: "ui-monospace, SFMono-Regular,
monospace";), or remove these custom variables if Geist fonts are not used.
In @examples/ts-react-search/src/utils/formatDate.ts:
- Around line 1-8: The formatDate function should validate the parsed date and
handle invalid inputs: inside formatDate, construct the Date object from the
input string (new Date(date)), check its validity (e.g.,
isNaN(dateObj.getTime()) or Number.isNaN(...)), and if invalid return a safe
placeholder (empty string or a short dash) instead of letting
Intl.DateTimeFormat render "Invalid Date"; otherwise format the valid date with
the existing Intl.DateTimeFormat options. Also guard the formatter call in a
try/catch to return the same placeholder on unexpected errors.
🧹 Nitpick comments (10)
examples/ts-react-search/README.md (2)
212-212: Replace repetitive phrasing for better readability.The phrase "First you need to add" echoes similar construction used earlier. Consider more varied wording.
♻️ Proposed improvement
- First you need to add TanStack Store as a dependency: + Add TanStack Store as a dependency:
287-287: Remove "of" for conciseness."all of the offerings" is more verbose than necessary; use "all the offerings" instead.
♻️ Proposed improvement
- You can learn more about all of the offerings from TanStack in the [TanStack documentation](https://tanstack.com). + You can learn more about all the offerings from TanStack in the [TanStack documentation](https://tanstack.com).examples/ts-react-search/src/routes/__root.tsx (1)
39-39: Consider enhancing the Not Found component.The current implementation is minimal. Consider adding better UX with styled content, navigation back to home, or a helpful message.
♻️ Optional enhancement
- notFoundComponent: () => <h1>Not Found</h1>, + notFoundComponent: () => ( + <div className="flex flex-col items-center justify-center min-h-screen text-white"> + <h1 className="text-4xl font-bold mb-4">404 - Page Not Found</h1> + <p className="text-gray-400 mb-8">The page you're looking for doesn't exist.</p> + <a href="/" className="text-cyan-400 hover:text-cyan-300 underline"> + Return to Home + </a> + </div> + ),examples/ts-react-search/src/components/HeroSection/Search/QuickPrompts.tsx (1)
20-45: Consider simplifying the click handler and improving key uniqueness.Two optional refinements:
- Simplify click handler: The
makePromptClickHandlerfunction can be inlined to reduce unnecessary closures.- Improve key prop: Using
promptas the key (line 32) assumes prompts are unique. Consider using a combination oflocaleandprompt, or the array index, for better uniqueness guarantees.♻️ Proposed refactor
function QuickPrompts({ onClick }: QuickPromptsProps) { - function makePromptClickHandler(value: string) { - return () => onClick(value) - } - return ( <div className="space-y-2"> <p className="text-center text-sm text-muted-foreground"> Quick prompts: </p> <ul className="flex flex-wrap justify-center gap-2"> - {PROMPTS.map(({ prompt, locale }) => ( - <li key={prompt}> + {PROMPTS.map(({ prompt, locale }, index) => ( + <li key={`${locale}-${index}`}> <button className="text-sm px-2 py-1 rounded bg-slate-700 text-cyan-400 cursor-pointer hover:bg-slate-600 transition-[color,box-shadow,background-color] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50" type="button" - onClick={makePromptClickHandler(prompt)} + onClick={() => onClick(prompt)} > {locale} • {prompt} </button> </li> ))} </ul> </div> ) }examples/ts-react-search/src/hooks/useSpeechRecognition.ts (2)
21-24: Consider exposing browser support status.When SpeechRecognition is unsupported, the error is set but the controls are still returned. Consumers might render UI elements that silently do nothing when clicked. Consider exposing an
isSupportedboolean to help consumers handle this case explicitly.♻️ Proposed enhancement
+ const [isSupported, setIsSupported] = useState(true) + useEffect(() => { const SpeechRecognitionCtor = window.SpeechRecognition || window.webkitSpeechRecognition if (!SpeechRecognitionCtor) { setError('SpeechRecognition is not supported in this browser.') + setIsSupported(false) return } // ... rest of setup }, [options?.lang, options?.continuous, options?.interimResults]) // ... rest of hook return { listening, transcript, error, + isSupported, startListening, stopListening, }Also applies to: 85-91
75-83: Consider using useCallback for stable function references.The
startListeningandstopListeningfunctions are recreated on every render. While not critical, wrapping them inuseCallbackwould provide stable references and prevent unnecessary re-renders if consumers use these functions in dependency arrays or pass them as props to memoized child components.♻️ Optional: Wrap in useCallback
+ const startListening = useCallback(() => { - const startListening = () => { setTranscript('') setError(null) recognitionRef.current?.start() - } + }, []) + const stopListening = useCallback(() => { - const stopListening = () => { recognitionRef.current?.stop() - }, []) + }examples/ts-react-search/src/utils/formatDate.ts (1)
2-7: Consider externalizing locale configuration for i18n support.The locale is hardcoded to
'en-GB'. For an example demonstrating best practices, consider accepting locale as an optional parameter or reading it from a configuration/context to support internationalization.♻️ Optional refactor to support configurable locale
-function formatDate(date: string) { - return new Intl.DateTimeFormat('en-GB', { +function formatDate(date: string, locale: string = 'en-GB') { + return new Intl.DateTimeFormat(locale, { year: 'numeric', month: 'short', day: '2-digit', timeZone: 'UTC', }).format(new Date(date)) }examples/ts-react-search/src/components/ui/table.tsx (1)
1-1: Consider whether 'use client' directive is necessary.The
'use client'directive marks this module for client-side execution in React Server Components. Since these are basic presentational primitives without interactive state or browser APIs, they could potentially run on the server. Verify if this directive is required in your TanStack Start setup.examples/ts-react-search/src/queryClient.ts (1)
3-3: Consider configuring QueryClient defaults for better UX.The QueryClient is instantiated with default options. For a production-like example, consider configuring defaults such as
staleTime,gcTime(formerlycacheTime), andretrybehavior to demonstrate best practices.♻️ Example configuration
-const queryClient = new QueryClient() +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + staleTime: 1000 * 60 * 5, // 5 minutes + gcTime: 1000 * 60 * 10, // 10 minutes + retry: 1, + }, + }, +})examples/ts-react-search/src/routes/_layout/disputes.tsx (1)
23-23: Consider if remountingDisputesFilterson search change is necessary.Using
key={JSON.stringify(search)}forces a full component remount whenever any search parameter changes. If the filter inputs are controlled components that derive their values from thesearchprop, this remount may be unnecessary and could cause brief UI flicker or reset any local component state.If the remount is intentional (e.g., to reset internal focus or validation state), consider adding a brief comment to document this intent.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (7)
examples/ts-react-search/public/favicon.icois excluded by!**/*.icoexamples/ts-react-search/public/logo192.pngis excluded by!**/*.pngexamples/ts-react-search/public/logo512.pngis excluded by!**/*.pngexamples/ts-react-search/public/tanstack-circle-logo.pngis excluded by!**/*.pngexamples/ts-react-search/public/tanstack-word-logo-white.svgis excluded by!**/*.svgexamples/ts-react-search/src/logo.svgis excluded by!**/*.svgpnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (74)
examples/ts-react-search/.cta.jsonexamples/ts-react-search/.gitignoreexamples/ts-react-search/.vscode/settings.jsonexamples/ts-react-search/README.mdexamples/ts-react-search/package.jsonexamples/ts-react-search/public/manifest.jsonexamples/ts-react-search/public/robots.txtexamples/ts-react-search/src/components/FilterSelect.tsxexamples/ts-react-search/src/components/HeroSection/Brand.tsxexamples/ts-react-search/src/components/HeroSection/HeroSection.tsxexamples/ts-react-search/src/components/HeroSection/Navigation.tsxexamples/ts-react-search/src/components/HeroSection/ProjectDescription.tsxexamples/ts-react-search/src/components/HeroSection/Search/QuickPrompts.tsxexamples/ts-react-search/src/components/HeroSection/Search/Search.tsxexamples/ts-react-search/src/components/HeroSection/Search/SearchForm.tsxexamples/ts-react-search/src/components/HeroSection/Search/index.tsexamples/ts-react-search/src/components/HeroSection/index.tsexamples/ts-react-search/src/components/Spinner.tsxexamples/ts-react-search/src/components/TableSummary.tsxexamples/ts-react-search/src/components/ui/README.mdexamples/ts-react-search/src/components/ui/button.tsxexamples/ts-react-search/src/components/ui/calendar.tsxexamples/ts-react-search/src/components/ui/date-picker.tsxexamples/ts-react-search/src/components/ui/label.tsxexamples/ts-react-search/src/components/ui/popover.tsxexamples/ts-react-search/src/components/ui/select.tsxexamples/ts-react-search/src/components/ui/table.tsxexamples/ts-react-search/src/constants.tsexamples/ts-react-search/src/features/disputes/DisputesFilters.tsxexamples/ts-react-search/src/features/disputes/DisputesManager.tsxexamples/ts-react-search/src/features/disputes/DisputesTable.tsxexamples/ts-react-search/src/features/disputes/constants.tsexamples/ts-react-search/src/features/disputes/data.tsexamples/ts-react-search/src/features/disputes/disputesCollection.tsexamples/ts-react-search/src/features/disputes/types.tsexamples/ts-react-search/src/features/disputes/useDisputesQuery.tsexamples/ts-react-search/src/features/orders/OrdersFilters.tsxexamples/ts-react-search/src/features/orders/OrdersManager.tsxexamples/ts-react-search/src/features/orders/OrdersTable.tsxexamples/ts-react-search/src/features/orders/constants.tsexamples/ts-react-search/src/features/orders/data.tsexamples/ts-react-search/src/features/orders/ordersCollection.tsexamples/ts-react-search/src/features/orders/types.tsexamples/ts-react-search/src/features/orders/useOrdersQuery.tsexamples/ts-react-search/src/features/settlements/SettlementsFilters.tsxexamples/ts-react-search/src/features/settlements/SettlementsManager.tsxexamples/ts-react-search/src/features/settlements/SettlementsTable.tsxexamples/ts-react-search/src/features/settlements/constants.tsexamples/ts-react-search/src/features/settlements/data.tsexamples/ts-react-search/src/features/settlements/settlementsCollection.tsexamples/ts-react-search/src/features/settlements/types.tsexamples/ts-react-search/src/features/settlements/useSettlementsQuery.tsexamples/ts-react-search/src/hooks/useSpeechRecognition.tsexamples/ts-react-search/src/queryClient.tsexamples/ts-react-search/src/routeTree.gen.tsexamples/ts-react-search/src/router.tsxexamples/ts-react-search/src/routes/__root.tsxexamples/ts-react-search/src/routes/_layout/disputes.tsxexamples/ts-react-search/src/routes/_layout/orders.tsxexamples/ts-react-search/src/routes/_layout/route.tsxexamples/ts-react-search/src/routes/_layout/settlements.tsxexamples/ts-react-search/src/routes/api/disputes.tsexamples/ts-react-search/src/routes/api/orders.tsexamples/ts-react-search/src/routes/api/search.tsexamples/ts-react-search/src/routes/api/settlements.tsexamples/ts-react-search/src/routes/index.tsxexamples/ts-react-search/src/speech.d.tsexamples/ts-react-search/src/styles.cssexamples/ts-react-search/src/types.tsexamples/ts-react-search/src/utils/cn.tsexamples/ts-react-search/src/utils/formatDate.tsexamples/ts-react-search/src/utils/getBaseUrl.tsexamples/ts-react-search/tsconfig.jsonexamples/ts-react-search/vite.config.ts
✅ Files skipped from review due to trivial changes (1)
- examples/ts-react-search/.vscode/settings.json
🚧 Files skipped from review as they are similar to previous changes (48)
- examples/ts-react-search/src/features/orders/OrdersManager.tsx
- examples/ts-react-search/src/components/HeroSection/Search/index.ts
- examples/ts-react-search/package.json
- examples/ts-react-search/src/routes/api/orders.ts
- examples/ts-react-search/src/features/disputes/useDisputesQuery.ts
- examples/ts-react-search/src/components/HeroSection/HeroSection.tsx
- examples/ts-react-search/src/components/ui/calendar.tsx
- examples/ts-react-search/src/components/HeroSection/Search/Search.tsx
- examples/ts-react-search/src/features/settlements/SettlementsTable.tsx
- examples/ts-react-search/src/features/orders/OrdersFilters.tsx
- examples/ts-react-search/src/components/ui/button.tsx
- examples/ts-react-search/vite.config.ts
- examples/ts-react-search/src/features/orders/types.ts
- examples/ts-react-search/src/router.tsx
- examples/ts-react-search/src/features/settlements/constants.ts
- examples/ts-react-search/src/components/ui/date-picker.tsx
- examples/ts-react-search/.gitignore
- examples/ts-react-search/public/robots.txt
- examples/ts-react-search/src/features/settlements/settlementsCollection.ts
- examples/ts-react-search/src/components/TableSummary.tsx
- examples/ts-react-search/src/components/ui/popover.tsx
- examples/ts-react-search/.cta.json
- examples/ts-react-search/src/routes/_layout/settlements.tsx
- examples/ts-react-search/src/features/orders/data.ts
- examples/ts-react-search/src/components/ui/README.md
- examples/ts-react-search/src/components/HeroSection/Brand.tsx
- examples/ts-react-search/src/components/ui/label.tsx
- examples/ts-react-search/src/components/Spinner.tsx
- examples/ts-react-search/src/features/settlements/types.ts
- examples/ts-react-search/src/routes/api/search.ts
- examples/ts-react-search/src/features/disputes/types.ts
- examples/ts-react-search/public/manifest.json
- examples/ts-react-search/src/components/HeroSection/Navigation.tsx
- examples/ts-react-search/src/features/disputes/constants.ts
- examples/ts-react-search/src/utils/cn.ts
- examples/ts-react-search/src/types.ts
- examples/ts-react-search/src/features/settlements/data.ts
- examples/ts-react-search/src/speech.d.ts
- examples/ts-react-search/src/components/FilterSelect.tsx
- examples/ts-react-search/src/features/disputes/DisputesFilters.tsx
- examples/ts-react-search/src/components/HeroSection/index.ts
- examples/ts-react-search/src/features/disputes/DisputesManager.tsx
- examples/ts-react-search/src/utils/getBaseUrl.ts
- examples/ts-react-search/src/routes/_layout/route.tsx
- examples/ts-react-search/tsconfig.json
- examples/ts-react-search/src/components/HeroSection/Search/SearchForm.tsx
- examples/ts-react-search/src/routes/index.tsx
- examples/ts-react-search/src/components/ui/select.tsx
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use tree-shakeable adapter architecture for provider implementations - export specialized adapters (text, embedding, summarize, image) as separate imports from/adapterssubpath rather than monolithic adapters
Use Zod for runtime schema validation and type inference, particularly for tool input/output definitions withtoolDefinition()and Zod schema inference
Implement isomorphic tool system usingtoolDefinition()with.server()and.client()implementations for dual-environment execution
Use type-safe per-model configuration with provider options typed based on selected model to ensure compile-time safety
Implement stream processing with StreamProcessor for handling chunked responses and support partial JSON parsing for streaming AI responses
Files:
examples/ts-react-search/src/routes/api/disputes.tsexamples/ts-react-search/src/features/settlements/SettlementsFilters.tsxexamples/ts-react-search/src/routes/_layout/orders.tsxexamples/ts-react-search/src/routes/api/settlements.tsexamples/ts-react-search/src/features/orders/useOrdersQuery.tsexamples/ts-react-search/src/features/settlements/SettlementsManager.tsxexamples/ts-react-search/src/features/disputes/DisputesTable.tsxexamples/ts-react-search/src/constants.tsexamples/ts-react-search/src/components/HeroSection/Search/QuickPrompts.tsxexamples/ts-react-search/src/features/disputes/data.tsexamples/ts-react-search/src/routeTree.gen.tsexamples/ts-react-search/src/queryClient.tsexamples/ts-react-search/src/components/HeroSection/ProjectDescription.tsxexamples/ts-react-search/src/utils/formatDate.tsexamples/ts-react-search/src/features/orders/constants.tsexamples/ts-react-search/src/components/ui/table.tsxexamples/ts-react-search/src/routes/_layout/disputes.tsxexamples/ts-react-search/src/features/orders/ordersCollection.tsexamples/ts-react-search/src/routes/__root.tsxexamples/ts-react-search/src/features/settlements/useSettlementsQuery.tsexamples/ts-react-search/src/features/disputes/disputesCollection.tsexamples/ts-react-search/src/features/orders/OrdersTable.tsxexamples/ts-react-search/src/hooks/useSpeechRecognition.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use camelCase for function and variable names throughout the codebase
Files:
examples/ts-react-search/src/routes/api/disputes.tsexamples/ts-react-search/src/features/settlements/SettlementsFilters.tsxexamples/ts-react-search/src/routes/_layout/orders.tsxexamples/ts-react-search/src/routes/api/settlements.tsexamples/ts-react-search/src/features/orders/useOrdersQuery.tsexamples/ts-react-search/src/features/settlements/SettlementsManager.tsxexamples/ts-react-search/src/features/disputes/DisputesTable.tsxexamples/ts-react-search/src/constants.tsexamples/ts-react-search/src/components/HeroSection/Search/QuickPrompts.tsxexamples/ts-react-search/src/features/disputes/data.tsexamples/ts-react-search/src/routeTree.gen.tsexamples/ts-react-search/src/queryClient.tsexamples/ts-react-search/src/components/HeroSection/ProjectDescription.tsxexamples/ts-react-search/src/utils/formatDate.tsexamples/ts-react-search/src/features/orders/constants.tsexamples/ts-react-search/src/components/ui/table.tsxexamples/ts-react-search/src/routes/_layout/disputes.tsxexamples/ts-react-search/src/features/orders/ordersCollection.tsexamples/ts-react-search/src/routes/__root.tsxexamples/ts-react-search/src/features/settlements/useSettlementsQuery.tsexamples/ts-react-search/src/features/disputes/disputesCollection.tsexamples/ts-react-search/src/features/orders/OrdersTable.tsxexamples/ts-react-search/src/hooks/useSpeechRecognition.ts
examples/**
📄 CodeRabbit inference engine (CLAUDE.md)
Examples are not built by Nx and should be run independently from their directories with
pnpm devorpnpm install && pnpm dev
Files:
examples/ts-react-search/src/routes/api/disputes.tsexamples/ts-react-search/src/features/settlements/SettlementsFilters.tsxexamples/ts-react-search/src/routes/_layout/orders.tsxexamples/ts-react-search/src/routes/api/settlements.tsexamples/ts-react-search/src/features/orders/useOrdersQuery.tsexamples/ts-react-search/src/features/settlements/SettlementsManager.tsxexamples/ts-react-search/src/features/disputes/DisputesTable.tsxexamples/ts-react-search/src/constants.tsexamples/ts-react-search/src/components/HeroSection/Search/QuickPrompts.tsxexamples/ts-react-search/src/styles.cssexamples/ts-react-search/src/features/disputes/data.tsexamples/ts-react-search/src/routeTree.gen.tsexamples/ts-react-search/src/queryClient.tsexamples/ts-react-search/src/components/HeroSection/ProjectDescription.tsxexamples/ts-react-search/src/utils/formatDate.tsexamples/ts-react-search/src/features/orders/constants.tsexamples/ts-react-search/src/components/ui/table.tsxexamples/ts-react-search/src/routes/_layout/disputes.tsxexamples/ts-react-search/src/features/orders/ordersCollection.tsexamples/ts-react-search/src/routes/__root.tsxexamples/ts-react-search/src/features/settlements/useSettlementsQuery.tsexamples/ts-react-search/src/features/disputes/disputesCollection.tsexamples/ts-react-search/src/features/orders/OrdersTable.tsxexamples/ts-react-search/src/hooks/useSpeechRecognition.tsexamples/ts-react-search/README.md
🧠 Learnings (7)
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/index.ts : Export tree-shakeable adapters with clear subpath exports in package.json (e.g., `tanstack/ai/adapters`, `tanstack/ai-openai/adapters`) to minimize bundle size
Applied to files:
examples/ts-react-search/src/routeTree.gen.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Use tree-shakeable adapter architecture for provider implementations - export specialized adapters (text, embedding, summarize, image) as separate imports from `/adapters` subpath rather than monolithic adapters
Applied to files:
examples/ts-react-search/src/routeTree.gen.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to packages/typescript/*/src/adapters/*.ts : Create individual adapter implementations for each provider capability (text, embed, summarize, image) with separate exports to enable tree-shaking
Applied to files:
examples/ts-react-search/src/routeTree.gen.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to **/*.{ts,tsx} : Use Zod for runtime schema validation and type inference, particularly for tool input/output definitions with `toolDefinition()` and Zod schema inference
Applied to files:
examples/ts-react-search/src/features/orders/constants.ts
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to examples/** : Examples are not built by Nx and should be run independently from their directories with `pnpm dev` or `pnpm install && pnpm dev`
Applied to files:
examples/ts-react-search/README.md
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Applies to .eslintrc* : Use ESLint with custom TanStack config for linting all TypeScript and JavaScript files
Applied to files:
examples/ts-react-search/README.md
📚 Learning: 2025-12-13T17:09:09.794Z
Learnt from: CR
Repo: TanStack/ai PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:09:09.794Z
Learning: Implement framework integrations using the headless `tanstack/ai-client` for state management with framework-specific hooks (useChat) on top
Applied to files:
examples/ts-react-search/README.md
🧬 Code graph analysis (14)
examples/ts-react-search/src/routes/api/disputes.ts (3)
examples/ts-react-search/src/routes/api/orders.ts (1)
Route(5-11)examples/ts-react-search/src/routes/api/settlements.ts (1)
Route(5-11)examples/ts-react-search/src/features/disputes/data.ts (1)
DISPUTES(3-74)
examples/ts-react-search/src/features/settlements/SettlementsFilters.tsx (4)
examples/ts-react-search/src/features/settlements/types.ts (1)
SettlementsSearch(12-12)examples/ts-react-search/src/constants.ts (1)
ALL_OPTION(1-1)examples/ts-react-search/src/features/settlements/constants.ts (2)
settlementsSearchSchema(32-36)SETTLEMENT_CURRENCY_MAP(15-23)examples/ts-react-search/src/components/ui/date-picker.tsx (1)
DatePicker(26-66)
examples/ts-react-search/src/routes/_layout/orders.tsx (3)
examples/ts-react-search/src/routes/_layout/disputes.tsx (1)
Route(9-16)examples/ts-react-search/src/routes/_layout/settlements.tsx (1)
Route(9-16)examples/ts-react-search/src/features/orders/constants.ts (1)
ordersSearchSchema(43-48)
examples/ts-react-search/src/routes/api/settlements.ts (3)
examples/ts-react-search/src/routes/api/disputes.ts (1)
Route(5-11)examples/ts-react-search/src/routes/api/orders.ts (1)
Route(5-11)examples/ts-react-search/src/features/settlements/data.ts (1)
SETTLEMENTS(3-64)
examples/ts-react-search/src/features/orders/useOrdersQuery.ts (1)
examples/ts-react-search/src/features/orders/types.ts (1)
OrdersSearch(15-15)
examples/ts-react-search/src/features/settlements/SettlementsManager.tsx (1)
examples/ts-react-search/src/features/settlements/types.ts (1)
SettlementsSearch(12-12)
examples/ts-react-search/src/features/disputes/DisputesTable.tsx (2)
examples/ts-react-search/src/features/disputes/types.ts (1)
Dispute(13-13)examples/ts-react-search/src/components/ui/table.tsx (6)
Table(108-108)TableHeader(109-109)TableRow(113-113)TableHead(112-112)TableBody(110-110)TableCell(114-114)
examples/ts-react-search/src/features/disputes/data.ts (1)
examples/ts-react-search/src/features/disputes/types.ts (1)
Dispute(13-13)
examples/ts-react-search/src/routeTree.gen.ts (1)
examples/ts-react-search/src/router.tsx (1)
getRouter(7-15)
examples/ts-react-search/src/features/orders/constants.ts (1)
examples/ts-react-search/src/features/orders/types.ts (2)
OrderStatus(9-9)PaymentMethod(11-11)
examples/ts-react-search/src/routes/_layout/disputes.tsx (2)
examples/ts-react-search/src/routes/_layout/orders.tsx (1)
Route(9-16)examples/ts-react-search/src/features/disputes/constants.ts (1)
disputesSearchSchema(45-50)
examples/ts-react-search/src/features/orders/ordersCollection.ts (1)
examples/ts-react-search/src/features/orders/constants.ts (1)
orderSchema(35-41)
examples/ts-react-search/src/features/settlements/useSettlementsQuery.ts (1)
examples/ts-react-search/src/features/settlements/types.ts (1)
SettlementsSearch(12-12)
examples/ts-react-search/src/features/disputes/disputesCollection.ts (1)
examples/ts-react-search/src/features/disputes/constants.ts (1)
disputeSchema(37-43)
🪛 LanguageTool
examples/ts-react-search/README.md
[grammar] ~34-~34: Use a hyphen to join words.
Context: ...com/router). The initial setup is a file based router. Which means that the route...
(QB_NEW_EN_HYPHEN)
[grammar] ~125-~125: Use a hyphen to join words.
Context: ... }, }) ``` Loaders simplify your data fetching logic dramatically. Check out m...
(QB_NEW_EN_HYPHEN)
[grammar] ~129-~129: Ensure spelling is correct
Context: ...o route loading and integrating it into you application is a breeze. First add you...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~212-~212: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...ting point for your project. First you need to add TanStack Store as a dependency: ``...
(REP_NEED_TO_VB)
[style] ~287-~287: Consider removing “of” to be more concise
Context: ... # Learn More You can learn more about all of the offerings from TanStack in the [TanStac...
(ALL_OF_THE)
⏰ 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). (1)
- GitHub Check: Test
🔇 Additional comments (26)
examples/ts-react-search/src/components/HeroSection/ProjectDescription.tsx (1)
1-15: LGTM!Clean, simple presentational component with proper semantic HTML and responsive Tailwind styling. The implementation is well-suited for the HeroSection composition.
examples/ts-react-search/src/routes/__root.tsx (1)
1-13: LGTM: Imports are well-organized.The imports are properly structured, grouping external TanStack packages and local modules logically.
examples/ts-react-search/src/constants.ts (1)
1-1: LGTM!The constant is clear, semantic, and follows proper naming conventions.
examples/ts-react-search/src/features/settlements/SettlementsFilters.tsx (1)
17-50: LGTM!The filter state management and navigation logic are well-implemented. The conversion of
ALL_OPTIONand empty strings toundefinedbefore schema validation ensures clean query parameters.examples/ts-react-search/src/features/settlements/useSettlementsQuery.ts (1)
5-19: LGTM! Clever optional filtering pattern.The nullish coalescing pattern (e.g.,
search.currency ?? settlement.currency) elegantly makes each filter optional by making the condition always true when the search parameter is undefined. This is idiomatic for TanStack DB.examples/ts-react-search/src/styles.css (5)
1-4: LGTM!Correct Tailwind v4 import syntax and properly scoped dark mode variant.
46-79: LGTM!Well-structured semantic color tokens using the oklch() color space for perceptually uniform colors. The light theme palette is comprehensive and covers all necessary UI components.
81-113: LGTM!Dark mode overrides are complete and maintain consistent color relationships with appropriate contrast inversions.
115-122: LGTM!Base layer follows the shadcn/ui pattern for consistent border and outline styling. The subtle foreground tint for the body background provides visual depth.
124-136: LGTM!Standard system font stack with appropriate font smoothing for cross-platform rendering. The monospace stack for code elements is well-chosen.
examples/ts-react-search/src/components/HeroSection/Search/QuickPrompts.tsx (2)
3-14: Nice multilingual example prompts.The PROMPTS array effectively demonstrates the search functionality with examples in different languages (English, Japanese, Swedish). This showcases the international capability of the natural language search feature.
1-1: No changes needed. The'use client'directive is appropriate for TanStack Start, which implements a Server Components model similar to Next.js. This directive is consistently used throughout the example codebase in multiple components (managers, filters, UI components, and search components), confirming it is an expected pattern for marking client-side components.Likely an incorrect or invalid review comment.
examples/ts-react-search/src/hooks/useSpeechRecognition.ts (1)
1-1: Acknowledge demo status but address critical issues below.The disclaimer is appropriate for an example. However, there are race conditions and edge cases that could cause confusing errors even in a demo context. See comments below.
examples/ts-react-search/src/features/disputes/DisputesTable.tsx (1)
16-56: LGTM! Clean table implementation with proper empty state handling.The component correctly handles the empty state with an appropriate colspan and provides clear user feedback. The table structure is well-organized with semantic column headers.
examples/ts-react-search/src/components/ui/table.tsx (1)
7-105: LGTM! Well-structured table primitives with consistent patterns.The components follow a consistent pattern with proper TypeScript typing, semantic HTML elements, data-slot attributes for debugging, and composed classNames. The Table wrapper's overflow handling provides good responsive behavior.
examples/ts-react-search/src/routes/api/settlements.ts (1)
5-11: LGTM! Consistent API route pattern.The implementation follows the same pattern as the other API routes (orders, disputes) in the codebase, providing a clean GET endpoint that returns settlements data as JSON.
examples/ts-react-search/src/features/disputes/data.ts (1)
1-74: LGTM! Well-structured example data.The dispute data is properly typed, follows consistent formatting, and provides good coverage of different statuses and reasons for demonstration purposes. All date ranges are valid (from < to).
examples/ts-react-search/src/features/orders/ordersCollection.ts (1)
1-22: LGTM! Clean collection implementation.The collection setup correctly uses Zod schema validation and follows TanStack React-DB patterns. The implementation is consistent with the disputes and settlements collections in the example.
examples/ts-react-search/src/routes/api/disputes.ts (1)
1-11: LGTM! Consistent API route implementation.The route handler correctly returns the disputes data using the json helper. The implementation follows the same pattern as the orders and settlements API routes.
examples/ts-react-search/src/routes/_layout/orders.tsx (1)
1-29: LGTM! Well-structured route implementation.The route properly preloads the orders collection, validates search parameters with Zod, and uses ClientOnly to handle hydration. The pattern is consistent with the disputes and settlements routes.
examples/ts-react-search/src/features/disputes/disputesCollection.ts (1)
1-22: LGTM! Consistent collection implementation.The collection setup properly uses Zod schema validation and follows the same reliable pattern as the orders and settlements collections. Well-structured for the example use case.
examples/ts-react-search/src/features/orders/useOrdersQuery.ts (1)
1-23: LGTM!The hook correctly implements conditional filtering with the fallback pattern. When a search parameter is undefined, comparing a field to itself (e.g.,
gte(order.from, order.from)) is always true, effectively disabling that filter condition. The dependency array properly tracks the individual search properties.examples/ts-react-search/src/features/orders/OrdersTable.tsx (1)
16-54: LGTM!The component is well-structured with proper TypeScript typing, correct empty-state handling that spans all 5 columns, and consistent use of the
formatDateutility for date formatting.examples/ts-react-search/src/routes/_layout/disputes.tsx (1)
9-16: LGTM on route configuration.The route correctly preloads the collection data in the loader and uses
zodValidatorwithdisputesSearchSchemafor type-safe search parameter validation. This pattern aligns with the orders route structure.examples/ts-react-search/src/routeTree.gen.ts (1)
1-9: Auto-generated file – skipping detailed review.This file is generated by TanStack Router and includes directives to disable linting and TypeScript checks. No manual modifications should be made.
examples/ts-react-search/src/features/orders/constants.ts (1)
1-48: Well-structured schema definitions following best practices.The file correctly uses Zod for runtime schema validation with proper type inference. The type-only import on line 3 avoids circular dependency issues at runtime while maintaining type safety for the
Recordtype annotations. The use offallbackfrom@tanstack/zod-adapterfor search schema fields is appropriate for URL parameter handling.
| pnpm install | ||
| pnpm start |
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.
🧩 Analysis chain
🏁 Script executed:
cat examples/ts-react-search/package.jsonRepository: TanStack/ai
Length of output: 1704
Fix the startup command — pnpm start does not exist in this example.
The README instructs pnpm start (lines 8–9), but the package.json defines no start script. The correct command is pnpm dev, which matches both the actual scripts in package.json (vite dev --port 3000) and project guidelines for examples.
Proposed fix
- pnpm start
+ pnpm dev📝 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.
| pnpm install | |
| pnpm start | |
| pnpm install | |
| pnpm dev |
🤖 Prompt for AI Agents
In @examples/ts-react-search/README.md around lines 8 - 9, The README currently
instructs "pnpm start" which doesn't exist in package.json; update the startup
command to "pnpm dev" so it matches the actual script ("vite dev --port 3000")
defined in package.json and project example guidelines; edit the README line
showing the two commands (the lines with "pnpm install" and "pnpm start") to
replace "pnpm start" with "pnpm dev".
|
|
||
| ## Routing | ||
|
|
||
| This project uses [TanStack Router](https://tanstack.com/router). The initial setup is a file based router. Which means that the routes are managed as files in `src/routes`. |
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.
Add hyphen to compound adjective.
"file based" should be hyphenated as "file-based" when used as a compound adjective.
✏️ Proposed fix
- This project uses [TanStack Router](https://tanstack.com/router). The initial setup is a file based router.
+ This project uses [TanStack Router](https://tanstack.com/router). The initial setup is a file-based router.📝 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.
| This project uses [TanStack Router](https://tanstack.com/router). The initial setup is a file based router. Which means that the routes are managed as files in `src/routes`. | |
| This project uses [TanStack Router](https://tanstack.com/router). The initial setup is a file-based router. Which means that the routes are managed as files in `src/routes`. |
🧰 Tools
🪛 LanguageTool
[grammar] ~34-~34: Use a hyphen to join words.
Context: ...com/router). The initial setup is a file based router. Which means that the route...
(QB_NEW_EN_HYPHEN)
🤖 Prompt for AI Agents
In @examples/ts-react-search/README.md at line 34, Update the README sentence to
hyphenate the compound adjective: change "file based router" to "file-based
router" in the line describing the initial setup so it reads "The initial setup
is a file-based router." This fixes the compound-adjective grammar while leaving
the surrounding text unchanged.
| }) | ||
| ``` | ||
|
|
||
| Loaders simplify your data fetching logic dramatically. Check out more information in the [Loader documentation](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading#loader-parameters). |
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.
Add hyphen to compound adjective "data-fetching".
"data fetching" should be hyphenated as "data-fetching" when used as a compound adjective modifying "logic".
✏️ Proposed fix
- Loaders simplify your data fetching logic dramatically.
+ Loaders simplify your data-fetching logic dramatically.📝 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.
| Loaders simplify your data fetching logic dramatically. Check out more information in the [Loader documentation](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading#loader-parameters). | |
| Loaders simplify your data-fetching logic dramatically. Check out more information in the [Loader documentation](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading#loader-parameters). |
🧰 Tools
🪛 LanguageTool
[grammar] ~125-~125: Use a hyphen to join words.
Context: ... }, }) ``` Loaders simplify your data fetching logic dramatically. Check out m...
(QB_NEW_EN_HYPHEN)
🤖 Prompt for AI Agents
In @examples/ts-react-search/README.md at line 125, Update the sentence "Loaders
simplify your data fetching logic dramatically." to use the compound adjective
form by inserting a hyphen: change "data fetching logic" to "data-fetching
logic" (so it reads "Loaders simplify your data-fetching logic dramatically.");
no other changes needed.
|
|
||
| ### React-Query | ||
|
|
||
| React-Query is an excellent addition or alternative to route loading and integrating it into you application is a breeze. |
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 typo: "you application" → "your application".
✏️ Proposed fix
- React-Query is an excellent addition or alternative to route loading and integrating it into you application is a breeze.
+ React-Query is an excellent addition or alternative to route loading and integrating it into your application is a breeze.📝 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.
| React-Query is an excellent addition or alternative to route loading and integrating it into you application is a breeze. | |
| React-Query is an excellent addition or alternative to route loading and integrating it into your application is a breeze. |
🧰 Tools
🪛 LanguageTool
[grammar] ~129-~129: Ensure spelling is correct
Context: ...o route loading and integrating it into you application is a breeze. First add you...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
🤖 Prompt for AI Agents
In @examples/ts-react-search/README.md at line 129, Fix the typo in the README
sentence that currently reads "React-Query is an excellent addition or
alternative to route loading and integrating it into you application is a
breeze." by replacing "you application" with "your application" so the sentence
reads "...into your application is a breeze."
| <TableSummary | ||
| totalCount={settlementsCollection.toArray.length} | ||
| resultCount={settlements.length} | ||
| /> |
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: toArray should be called as a method.
Line 20 accesses toArray as a property rather than calling it as a method. This will likely cause a runtime error.
🐛 Proposed fix
<TableSummary
- totalCount={settlementsCollection.toArray.length}
+ totalCount={settlementsCollection.toArray().length}
resultCount={settlements.length}
/>📝 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.
| <TableSummary | |
| totalCount={settlementsCollection.toArray.length} | |
| resultCount={settlements.length} | |
| /> | |
| <TableSummary | |
| totalCount={settlementsCollection.toArray().length} | |
| resultCount={settlements.length} | |
| /> |
🤖 Prompt for AI Agents
In @examples/ts-react-search/src/features/settlements/SettlementsManager.tsx
around lines 19 - 22, The code uses settlementsCollection.toArray as a property
when computing totalCount; call the method instead. Update the TableSummary prop
to use settlementsCollection.toArray() so totalCount invokes the toArray()
function (and keep resultCount={settlements.length} unchanged), ensuring
settlementsCollection.toArray() is executed to return the array length.
| recognitionRef.current?.abort() | ||
| recognitionRef.current = null | ||
| } | ||
| }, [options?.lang, options?.continuous, options?.interimResults]) |
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.
Dependency array may cause unnecessary re-initialization.
If the options object is recreated on every render by the consuming component, this effect will re-run on every render, tearing down and recreating the SpeechRecognition instance. This is expensive and could abort ongoing recognition sessions.
Consider either:
- Documenting that consumers should memoize the
optionsobject - Extracting individual values outside the effect and using primitive comparisons
- Using
useRefto store options and only apply changes when they differ
♻️ Option 2: Use individual primitive values
export const useSpeechRecognition = (options?: UseSpeechRecognitionOptions) => {
const [listening, setListening] = useState(false)
const [transcript, setTranscript] = useState('')
const [error, setError] = useState<string | null>(null)
+
+ const lang = options?.lang ?? 'en-US'
+ const continuous = options?.continuous ?? false
+ const interimResults = options?.interimResults ?? false
const recognitionRef = useRef<SpeechRecognition | null>(null)
useEffect(() => {
const SpeechRecognitionCtor =
window.SpeechRecognition || window.webkitSpeechRecognition
if (!SpeechRecognitionCtor) {
setError('SpeechRecognition is not supported in this browser.')
return
}
const recognition = new SpeechRecognitionCtor()
- recognition.lang = options?.lang ?? 'en-US'
- recognition.continuous = options?.continuous ?? false
- recognition.interimResults = options?.interimResults ?? false
+ recognition.lang = lang
+ recognition.continuous = continuous
+ recognition.interimResults = interimResults
recognition.onstart = () => {
setListening(true)
setError(null)
}
recognition.onend = () => {
setListening(false)
}
recognition.onerror = (event) => {
setError(event.error)
setListening(false)
}
recognition.onresult = (event) => {
let finalTranscript = ''
for (let i = event.resultIndex; i < event.results.length; i++) {
const res = event.results[i]
if (res.isFinal) {
finalTranscript += res[0].transcript
}
}
if (finalTranscript) {
setTranscript((prev) =>
prev
? `${prev.trim()} ${finalTranscript.trim()}`
: finalTranscript.trim(),
)
}
}
recognitionRef.current = recognition
return () => {
recognition.onstart = null
recognition.onend = null
recognition.onerror = null
recognition.onresult = null
recognitionRef.current?.abort()
recognitionRef.current = null
}
- }, [options?.lang, options?.continuous, options?.interimResults])
+ }, [lang, continuous, interimResults])🤖 Prompt for AI Agents
In @examples/ts-react-search/src/hooks/useSpeechRecognition.ts at line 73, The
effect in useSpeechRecognition re-triggers whenever the whole options object
identity changes (currently using [options?.lang, options?.continuous,
options?.interimResults]), which can still cause re-initialization if options is
recreated; destructure the primitive values from options (e.g., const { lang,
continuous, interimResults } = options ?? {}) outside the effect and use those
primitives in the effect dependency array so React compares by value, or
alternatively store options in a ref and apply changes only when individual
values differ; update the effect to reference those primitive names (lang,
continuous, interimResults) instead of options to avoid unnecessary
teardown/recreation of the SpeechRecognition instance.
| const startListening = () => { | ||
| setTranscript('') | ||
| setError(null) | ||
| recognitionRef.current?.start() | ||
| } |
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.
Guard against calling start() while already listening.
The SpeechRecognition API throws InvalidStateError if start() is called while recognition is already active. This creates a poor user experience if startListening() is invoked multiple times.
🛡️ Proposed fix: Add guard clause
const startListening = () => {
+ if (listening) return
setTranscript('')
setError(null)
recognitionRef.current?.start()
}📝 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 startListening = () => { | |
| setTranscript('') | |
| setError(null) | |
| recognitionRef.current?.start() | |
| } | |
| const startListening = () => { | |
| if (listening) return | |
| setTranscript('') | |
| setError(null) | |
| recognitionRef.current?.start() | |
| } |
🤖 Prompt for AI Agents
In @examples/ts-react-search/src/hooks/useSpeechRecognition.ts around lines 75 -
79, startListening currently calls recognitionRef.current?.start()
unconditionally which will throw InvalidStateError if recognition is already
active; add a guard in startListening that returns early when recognition is
already running by checking a listening flag (e.g., add a listeningRef or
isListening state updated in recognition.onstart and recognition.onend) or by
checking a custom property on recognitionRef.current, then only call
recognitionRef.current.start() when not already listening; update the
recognition onstart/onend handlers to set/reset this flag so repeated calls to
startListening are safe.
| <body className="bg-linear-to-b from-slate-900 via-slate-800 to-slate-900"> | ||
| <div className="min-h-screen bg-linear-to-r from-cyan-500/10 via-blue-500/10 to-purple-500/10 flex flex-col"> |
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 incorrect Tailwind CSS gradient class names.
The class names use bg-linear-to-b and bg-linear-to-r, which are not valid Tailwind CSS utilities. The correct classes are bg-gradient-to-b and bg-gradient-to-r. Without this fix, the gradient backgrounds will not render.
🐛 Proposed fix
- <body className="bg-linear-to-b from-slate-900 via-slate-800 to-slate-900">
- <div className="min-h-screen bg-linear-to-r from-cyan-500/10 via-blue-500/10 to-purple-500/10 flex flex-col">
+ <body className="bg-gradient-to-b from-slate-900 via-slate-800 to-slate-900">
+ <div className="min-h-screen bg-gradient-to-r from-cyan-500/10 via-blue-500/10 to-purple-500/10 flex flex-col">📝 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.
| <body className="bg-linear-to-b from-slate-900 via-slate-800 to-slate-900"> | |
| <div className="min-h-screen bg-linear-to-r from-cyan-500/10 via-blue-500/10 to-purple-500/10 flex flex-col"> | |
| <body className="bg-gradient-to-b from-slate-900 via-slate-800 to-slate-900"> | |
| <div className="min-h-screen bg-gradient-to-r from-cyan-500/10 via-blue-500/10 to-purple-500/10 flex flex-col"> |
🤖 Prompt for AI Agents
In @examples/ts-react-search/src/routes/__root.tsx around lines 48 - 49, Replace
the invalid Tailwind utility names used in the root JSX: in the <body> element's
className change "bg-linear-to-b" to "bg-gradient-to-b" and in the surrounding
<div> element's className change "bg-linear-to-r" to "bg-gradient-to-r" so the
gradient backgrounds render correctly.
| --font-sans: var(--font-geist-sans); | ||
| --font-mono: var(--font-geist-mono); |
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.
Undefined font CSS variables.
--font-geist-sans and --font-geist-mono are referenced but never defined in this file or :root. Tailwind's font-sans and font-mono utilities will resolve to empty values unless these are set elsewhere (e.g., via Next.js font optimization or a font loader).
If Geist fonts aren't being used, consider removing these mappings or defining fallback values:
Suggested fix
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
- --font-sans: var(--font-geist-sans);
- --font-mono: var(--font-geist-mono);
+ --font-sans: ui-sans-serif, system-ui, sans-serif;
+ --font-mono: ui-monospace, monospace;📝 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.
| --font-sans: var(--font-geist-sans); | |
| --font-mono: var(--font-geist-mono); | |
| --font-sans: ui-sans-serif, system-ui, sans-serif; | |
| --font-mono: ui-monospace, monospace; |
🤖 Prompt for AI Agents
In @examples/ts-react-search/src/styles.css around lines 9 - 10, The CSS defines
--font-sans and --font-mono by pointing them at undefined variables
(--font-geist-sans, --font-geist-mono), so Tailwind's font-sans/font-mono will
be empty; fix by either defining the geist variables (e.g., add :root {
--font-geist-sans: "Inter, system-ui, sans-serif"; --font-geist-mono:
"ui-monospace, SFMono-Regular, monospace"; }) or replace the mappings to use
concrete fallbacks directly (e.g., --font-sans: "Inter, system-ui, sans-serif";
--font-mono: "ui-monospace, SFMono-Regular, monospace";), or remove these custom
variables if Geist fonts are not used.
| function formatDate(date: string) { | ||
| return new Intl.DateTimeFormat('en-GB', { | ||
| year: 'numeric', | ||
| month: 'short', | ||
| day: '2-digit', | ||
| timeZone: 'UTC', | ||
| }).format(new Date(date)) | ||
| } |
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.
Add error handling for invalid date strings.
The function doesn't validate the input date string. If an invalid date string is passed, new Date(date) will create an Invalid Date object, which Intl.DateTimeFormat will format as "Invalid Date". This could display error text in the UI tables that consume this utility.
🛡️ Proposed fix with validation
function formatDate(date: string) {
+ const parsedDate = new Date(date)
+ if (isNaN(parsedDate.getTime())) {
+ return 'Invalid date'
+ }
return new Intl.DateTimeFormat('en-GB', {
year: 'numeric',
month: 'short',
day: '2-digit',
timeZone: 'UTC',
- }).format(new Date(date))
+ }).format(parsedDate)
}🤖 Prompt for AI Agents
In @examples/ts-react-search/src/utils/formatDate.ts around lines 1 - 8, The
formatDate function should validate the parsed date and handle invalid inputs:
inside formatDate, construct the Date object from the input string (new
Date(date)), check its validity (e.g., isNaN(dateObj.getTime()) or
Number.isNaN(...)), and if invalid return a safe placeholder (empty string or a
short dash) instead of letting Intl.DateTimeFormat render "Invalid Date";
otherwise format the valid date with the existing Intl.DateTimeFormat options.
Also guard the formatter call in a try/catch to return the same placeholder on
unexpected errors.
- Moved search API mutation logic from Search component into dedicated useSearchMutation hook - Improves code reusability and separation of concerns - Enables search functionality to be used across multiple components - Reduces code duplication and improves maintainability
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: 0
🧹 Nitpick comments (3)
examples/ts-react-search/src/hooks/useSearchMutation.ts (3)
8-20: Consider adding timeout and more detailed error handling.For production readiness, consider the following improvements:
- Add a timeout to the fetch request to prevent indefinite hangs
- Include response status and details in the error message for better debugging
🔧 Example with timeout and detailed errors
mutationFn: async (content: string) => { + const controller = new AbortController() + const timeoutId = setTimeout(() => controller.abort(), 10000) // 10s timeout + const response = await fetch('/api/search', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ content }), + signal: controller.signal, }) + clearTimeout(timeoutId) + if (!response.ok) { - throw new Error('Search request failed') + const errorText = await response.text().catch(() => 'Unknown error') + throw new Error(`Search request failed with status ${response.status}: ${errorText}`) } return response.json() },
19-27: Consider adding response validation per coding guidelines.The coding guidelines recommend using Zod for runtime schema validation. While the current optional chaining provides basic safety, explicit validation would catch schema mismatches early and provide type safety.
📋 Example with Zod validation
First, define a schema at the top of the file:
import { z } from 'zod' const searchResponseSchema = z.object({ data: z.object({ name: z.string(), parameters: z.record(z.unknown()), }), })Then validate in onSuccess:
onSuccess: async (json) => { - const { name, parameters } = json?.data ?? {} + const result = searchResponseSchema.safeParse(json) + + if (!result.success) { + console.error('Invalid search response:', result.error) + return + } + + const { name, parameters } = result.data.data if (name && parameters) { await navigate({ to: `/${name}`, search: parameters }) } },Note: The
awaiton Line 25 is unnecessary since the mutation doesn't need to wait for navigation to complete, though it's harmless.
31-31: Consider using named export for consistency.Other hooks in this codebase appear to use named exports. Using a named export would improve consistency and enable better tree-shaking.
-export default useSearchMutation +export { useSearchMutation }Then update the import in consuming components from
import useSearchMutation from '...'toimport { useSearchMutation } from '...'.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
examples/ts-react-search/src/components/HeroSection/Search/Search.tsxexamples/ts-react-search/src/hooks/useSearchMutation.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- examples/ts-react-search/src/components/HeroSection/Search/Search.tsx
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use tree-shakeable adapter architecture for provider implementations - export specialized adapters (text, embedding, summarize, image) as separate imports from/adapterssubpath rather than monolithic adapters
Use Zod for runtime schema validation and type inference, particularly for tool input/output definitions withtoolDefinition()and Zod schema inference
Implement isomorphic tool system usingtoolDefinition()with.server()and.client()implementations for dual-environment execution
Use type-safe per-model configuration with provider options typed based on selected model to ensure compile-time safety
Implement stream processing with StreamProcessor for handling chunked responses and support partial JSON parsing for streaming AI responses
Files:
examples/ts-react-search/src/hooks/useSearchMutation.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use camelCase for function and variable names throughout the codebase
Files:
examples/ts-react-search/src/hooks/useSearchMutation.ts
examples/**
📄 CodeRabbit inference engine (CLAUDE.md)
Examples are not built by Nx and should be run independently from their directories with
pnpm devorpnpm install && pnpm dev
Files:
examples/ts-react-search/src/hooks/useSearchMutation.ts
⏰ 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). (2)
- GitHub Check: Test
- GitHub Check: Preview

🎯 Changes
Quote from my article
Commit message
Preview
Next steps
✅ Checklist
pnpm run test:pr🚀 Release Impact
This change introduces only the new example.
Summary by CodeRabbit
New Features
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.