@tanstack/cli create --router-only, don't hand-roll. It wires TypeScript, Tailwind, and file/code-based routing choice interactively.$param = dynamic segment, $ alone = splat, _prefix = pathless layout, _suffix = non-nested, -prefix = excluded from routing, (group) = organizational only, {-$param} = optional param, [x] = escape a literal routing-significant character.loader, not useEffect in the component. Loaders run in parallel with route matching and support the built-in cache, preloading, and SSR out of the box; component-level fetching causes waterfalls and loading flashes.loaderDeps, never read search directly inside loader. Only include params the loader actually consumes; extras cause unneeded reloads.<Await>), don't block the whole route with a pendingComponent. Requires Streaming SSR to actually stream server-side; without it, deferral is client-only.validateSearch + Route.useSearch(), never raw URLSearchParams. Search params are typed application state, not ad hoc strings; use .catch() fallbacks so malformed URLs degrade gracefully instead of erroring.retainSearchParams/stripSearchParams middleware on the route, not manual logic at every <Link>.{ to, params, search } object across Link/navigate/redirect → wrap it in linkOptions(), not a bare object literal. Bare literals only surface type errors where they're spread into Link, not at the point of definition.Link for a UI library or custom styling → use createLink(), not a generic prop-spread wrapper. Preserves full type safety and preload="intent" support.redirect() from the parent route's beforeLoad, not from the component. Parent beforeLoad always runs before child beforeLoad, so one guard protects the whole subtree; use isRedirect() when catching errors around the check.notFound() from loader, not from the component. Keeps loader data correctly typed and avoids UI flicker; reserve CatchNotFound for component-thrown cases only.notFoundMode: 'root' for the former, default 'fuzzy' for the latter.staticData, not context/beforeLoad. staticData is synchronous and identical per route; use context only when the value is async or depends on params/auth.router.invalidate(); use { sync: true } only when you must wait before proceeding (e.g. before a redirect).createRootRouteWithContext), not module-level imports.beforeLoad/loader can see its result → call the hook in a component and pass the value through <RouterProvider context={...}>. Hooks cannot run inside beforeLoad/loader (Rules of Hooks).defaultPreload: 'intent'. It's the single highest-value default; use 'viewport' for below-the-fold links, 'render' for near-always-needed routes.defaultPreloadStaleTime: 0 so the external library's freshness rules govern reuse instead of the router's own preloadStaleTime.to/params/search externally → type it with ValidateLinkOptions/ValidateLinkOptionsArray/etc., not the internal LinkProps type. Using LinkProps directly is a documented TypeScript-performance trap.strict: false on the hook, don't guess a from.createRoute/createFileRoute → always put params/validateSearch → context → beforeLoad → loader in that order. loader before beforeLoad breaks context type inference; enable the create-route-property-order ESLint rule and let --fix handle it.typescript-eslint's only-throw-error (type-checked rulesets) → allowlist Redirect and NotFoundError from @tanstack/router-core, don't disable the rule wholesale.select to the router-state hook; if select returns a freshly-computed object, also set structuralSharing: true.mask on Link/navigate, or routeMasks + createRouteMask()), not a separate non-nested route with manual URL rewriting. Remember masked state resets on reload unless unmaskOnReload: true./{-$locale}/about (optional param), not separate route trees per locale.useBlocker()/<Block>; for tab close/refresh → enableBeforeUnload. These are two separate mechanisms, both are needed for full protection.createMemoryHistory({ initialEntries }), not the default browser history.index.html → createHashHistory, not the default browser history.createRouter/getRouter(), never at module scope. Module-level singletons leak state across requests.react-router-dom early to let TypeScript surface every remaining call site as a compile error, faster than manual grepping.| Setting | Default | Notes |
|---|---|---|
staleTime | 0 | Immediately stale; revalidates in background on reuse |
gcTime | 5 min | Retention before cached loader data is GC-eligible |
preloadStaleTime | 30 sec | Separate freshness window for preloaded data |
preloadGcTime | 5 min | Separate retention window for preloaded data |
defaultPreloadDelay | 50 ms | Delay before intent/viewport preload starts |
notFoundMode | 'fuzzy' | Nearest route with notFoundComponent, not always root |
routeFileIgnorePrefix | - | Files/folders excluded from route generation |
routeToken / indexToken | route / index | Layout-route / index-route filename markers |
quoteStyle | single | Generated route tree formatting |
autoCodeSplitting | false (bundler plugin) | Will default to true in v2 |
unmaskOnReload | false | Masked URLs persist across reload unless set |