Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
TanStack Router treats search params as JSON-first application state. They are automatically parsed from the URL into structured objects (numbers, booleans, arrays, nested objects) and validated via validateSearch on each route.
CRITICAL: When using zodValidator() and Zod v3, use fallback() from @tanstack/zod-adapter, NOT zod's .catch(). Using .catch() with the zod adapter makes the output type unknown, destroying type safety. This does not apply to Valibot or ArkType (which use their own fallback mechanisms). It also does not apply to Zod v4, which should use .catch() and not use the zodValidator().
CRITICAL: Types are fully inferred. Never annotate the return of useSearch().
exportconstRoute = createFileRoute("/products")({
validateSearch: productSearchSchema,
// Pick ONLY the params the loader needs — not the entire search objectloaderDeps: ({ search }) => ({ page: search.page }),
loader: async ({ deps }) => {
returnfetchProducts({ page: deps.page })
},
})
Common Mistakes
1. HIGH: Using zod v3's .catch() with zodValidator() instead of adapter fallback()
// WRONG — .catch() with zodValidator makes the type unknownconst schema = z.object({ page: z.number().catch(1) })
validateSearch: zodValidator(schema) // page is typed as unknown!// CORRECT — fallback() preserves the inferred typeimport { fallback } from"@tanstack/zod-adapter"const schema = z.object({ page: fallback(z.number(), 1) })
Important: This only applies when using Zod v3, not when using Zod v4. For v4, using .catch() is correct.
2. HIGH: Returning entire search object from loaderDeps
// WRONG — loader re-runs on ANY search param changeloaderDeps: ({ search }) => search
// CORRECT — loader only re-runs when page changesloaderDeps: ({ search }) => ({ page: search.page })
3. HIGH: Passing Date objects in search params
// WRONG — Date does not serialize correctly to JSON in URLs
<Link search={{ startDate: newDate() }}>
// CORRECT — convert to ISO string<Linksearch={{startDate:newDate().toISOString() }}>