NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
npm · #2363 most downloaded on npm
Modern and scalable routing for React applications
Last release 4 days ago
30 Sep 2026
Ships fairly regularly
a new release about every 1 weeks
Nearly every release is documented
notes for 60 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
2 years old
415 releases · first in 2025
One column per month.
Updated dependencies [ d521abd ]:
d521abd]:
Updated dependencies [ 488d046 , 0c1b5e3 , 3cdd1af ]:
#8297 488d046 - Update seroval and seroval-plugins from 1.6.2 to 1.6.7. This picks up the typed array length guard, the maxBase64Length and compactArrayBufferViews options, and the isStream export.
#8353 76a7c0b - Avoid an unused array when registering server-function middleware.
Updated dependencies [488d046, 0c1b5e3, 3cdd1af]:
Start now cancels discarded middleware and HEAD response bodies, including plain streams and derived branches.
#8204 cbbfbe3 - Stream large deferred SSR hydration payloads through a backpressure-aware router transport, fail known setup errors before response creation, and close cancelled or expired transforms safely.
Start now cancels discarded middleware and HEAD response bodies, including plain streams and derived branches.
Server-function raw streams share one ordered response. Arbitrary or sequential consumption can require potentially unbounded buffering of unread data on the client. Cancelling one raw stream discards it locally, while aborting the whole call cancels the response and server work. Consume streams concurrently, cancel unused streams promptly, or use separate calls when independent backpressure is required. A raw stream that exceeds its unread-byte limit now fails alone; sibling streams and the JSON result keep flowing.
The JSON wire shape of a RawStream server-function argument changed. Clients and servers must run matching versions for requests that pass a RawStream.
The frame-protocol constants (FRAME_TYPE_*, MAX_FRAME_PAYLOAD_SIZE, MAX_FRAMED_STREAMS) moved from the @tanstack/start-client-core root to the @tanstack/start-client-core/client-rpc subpath.
Router requests whose Accept header allows neither text/html nor */* now receive 406 Not Acceptable instead of 500.
Framework adapters share the body <Scripts> composition (getSsrBodyScriptParts, composeSsrBodyScripts) and the eager HTML response wrapper (renderSsrHtmlResponse) from @tanstack/router-core.
Solid SSR now emits one document type and renders late lazy errors through route boundaries. A Solid <Await> without a fallback no longer holds the streamed shell; it renders inside the nearest <Suspense> boundary like React and Vue, and now renders falsy resolved values.
Static server functions decode cached RawStream values with the client deserializer plugins.
SSR Query integrations now keep request cleanup and stream ownership aligned with the router lifecycle.
Updated dependencies [bc80866, e561fa1, cbbfbe3, a1c8d1a, cbbfbe3, a0b2ad9, 1ca361b]:
Updated dependencies [ d76a332 , b747fb8 , 6cfb1e8 , 700a714 , 700a714 , 7e349c3 , 873c830 , 7e349c3 , 634da91 , e9396c9 , 634da91 , f151ab0 , bc57fa3
d76a332, b747fb8, 6cfb1e8, 700a714, 700a714, 7e349c3, 873c830, 7e349c3, 634da91, e9396c9, 634da91, f151ab0, bc57fa3, 9872d2a, d76a332, 634da91, 634da91, 7e349c3, 9448caa, e9396c9, 700a714, 634da91, 634da91]:
Updated dependencies [`f9836f1`, `9c1871c`, `9871c06`, `0654c0a`]:
Updated dependencies [ edf0e16 , 2f20c00 , 28a5e45 , 08eff50 , 216c0c4 , 2f91503 , f0b5eda , 50eafca , 0497cae , ee28348 , c18e690 ]:
Updated dependencies [ fa65287 , cb281d7 ]:
Updated dependencies [`3e016ac`]:
3e016ac]:
Updated dependencies [`5d3785d`, `63d2cc9`]:
Updated dependencies \[`7e93431`]:
#8045 f500760 - Warn when an Outlet is rendered inside a pending, error, or not-found component.
#8043 1aafca9 - remove the undocumented Link isTransitioning state and data-transitioning attribute
#8044 aa10b65 - Apply preloadDelay to viewport link preloading and cancel pending preloads when links leave the viewport.
Updated dependencies [7e93431]:
51138a8]:
### Patch Changes - #7952 `95dec51` - bail out of Link re-renders when the resolved href and active state are unchanged
31882c7]:
51138a8]:
Updated dependencies \[`ea3a665`]:
ea3a665]:
7e93431]:
RouterCore.getMatchedRoutes() now returns [matchedRoutes, rawParams, foundRoute] instead of an object.
#7970 2435885 - createFileRoute does not rely on FileRoute class
#7985 9cac62a - perf: compact private bundle boundaries- #7975
#7971 86bf510 - clean intersection observer options in link component
#7967 6aefb33 - Preserve path params in their raw string form while matching routes so structured values returned by params.parse produce stable match IDs and do not reuse stale loader data.
RouterCore.getMatchedRoutes() now returns [matchedRoutes, rawParams, foundRoute] instead of an object.
Updated dependencies [84db4a8, 9cac62a, 6aefb33]:
#7961 697ebb6 - Prevent a blank frame before zero-delay initial pending UI by using a
component-scoped React transition for match publication. Pending timing,
boundary selection, and rendered matches continue to come from the router
core.
#7970 2435885 - createFileRoute does not rely on FileRoute class
#7971 86bf510 - clean intersection observer options in link component
#7967 6aefb33 - Preserve path params in their raw string form while matching routes so structured values returned by params.parse produce stable match IDs and do not reuse stale loader data.
RouterCore.getMatchedRoutes() now returns [matchedRoutes, rawParams, foundRoute] instead of an object.
Updated dependencies [84db4a8, 9cac62a, 6aefb33]:
51138a8]:
ea3a665]:
RouterCore.getMatchedRoutes() now returns [matchedRoutes, rawParams, foundRoute] instead of an object.
#7970 2435885 - createFileRoute does not rely on FileRoute class
#7985 9cac62a - perf: compact private bundle boundaries- #7975
#7971 86bf510 - clean intersection observer options in link component
#7967 6aefb33 - Preserve path params in their raw string form while matching routes so structured values returned by params.parse produce stable match IDs and do not reuse stale loader data.
RouterCore.getMatchedRoutes() now returns [matchedRoutes, rawParams, foundRoute] instead of an object.
Updated dependencies [84db4a8, 9cac62a, 6aefb33]:
b2908c6]:
#8009 c59788c - perf: drop consumed chunks from the client frame decoder buffer with an O(1) head pointer instead of Array.prototype.shift() (O(n)). The previous approach degraded to O(n^2) when a single large frame (e.g. a big RawStream payload) was assembled from many small network reads.
Updated dependencies [44a8c3e, 5253e70]:
Invalidation now retires matching active preloads so older speculative loader results cannot become fresh cache data after invalidation.
#7805 45c4ad8 - Rewrite match loading around a lane-based scheduler that tracks each navigation, preload, and background reload as an ordered unit of work. This fixes pending/redirect/retry state leaking between overlapping navigations, restores correct SSR status codes for redirects, errors, and not-found responses, and closes hydration gaps where the client re-ran work the server had already completed.
headers() now only runs on the server, matching the documented behavior — it is no longer invoked during client-side asset projection.gcTime and preloadGcTime now match the existing runtime default of 5 minutes (300_000).Removed / changed exported internals
RouterState no longer includes loadedAt, isTransitioning, statusCode, or redirect. Use match.updatedAt in place of loadedAt; subscribe to router.state.status / router.state.isLoading in place of isTransitioning; server response status and redirect handling are now internal to the server loader and are no longer exposed on router.state.RouteMatch.fetchCount has been removed, with no replacement — it was purely informational.RouteMatch.status no longer includes 'redirected' (it remains 'pending' | 'success' | 'error' | 'notFound') — redirected matches are dropped from the match list instead of being rendered.RouteMatch.globalNotFound has been renamed and privatized to the internal _notFound field. Use match.status === 'notFound' instead.Match components now accept routeId instead of matchId.RouterStores adapter contract now uses route-keyed presentation stores: matchesId is replaced by ids, matchStores by byRoute, and getRouteMatchStore() by getMatchStore(). The separate loadedAt, isLoading, isTransitioning, statusCode, and redirect stores have been removed, along with the pending/cache stores and their setters. StoreConfig.init has also been removed. Read application-facing state from router.state; preload and cache coordination are now internal.RouterCore members getMatch(), updateMatch(), cancelMatch(), and cancelMatches() — read matches from router.state.matches (e.g. router.state.matches.find((m) => m.id === id)); there is no replacement for mutating or cancelling an individual in-flight match from outside the router.RouterCore.hasNotFoundMatch() — use router.state.matches.some((m) => m.status === 'notFound').RouterCore.looseRoutesById — use routesById.RouterCore.isPrerendering(), RouterCore.isViewTransitionTypesSupported, and RouterCore.viewTransitionPromise, with no replacement.RouterCore.getParsedLocationHref() and RouterCore.clearExpiredCache(), with no replacement — expired cache entries are now reconciled automatically as part of match commit.RouterCore.latestLoadPromise and RouterCore.beforeLoad(), with no replacement.RouterCore.commitLocationPromise and RouterCore.pendingBuiltLocation have been replaced by the internal _commitPromise and _pendingLocation fields.GetMatchFn and UpdateMatchFn types, along with the methods they typed.getMatchedRoutes() export from @tanstack/router-core — use the router.getMatchedRoutes() instance method instead.RouterCore.loadRouteChunk() no longer accepts an array of component types as its second argument. One-argument usage is unchanged; the optional second argument is now 'errorComponent', 'notFoundComponent', or false for internal boundary loading.Redirect.redirectHandled, which was internal redirect bookkeeping.MatchRoutesOpts.preload and MatchRoutesOpts.dest have been removed.StartTransitionFn is now (fn, expected) => Promise<boolean> (previously (fn) => void). This only affects custom framework adapters that implement startTransition.Updated dependencies [45c4ad8]:
b2908c6]:
Updated dependencies \[`ea3a665`]:
ea3a665]:
#7805 45c4ad8 - Rewrite match loading around a lane-based scheduler that tracks each navigation, preload, and background reload as an ordered unit of work. This fixes pending/redirect/retry state leaking between overlapping navigations, restores correct SSR status codes for redirects, errors, and not-found responses, and closes hydration gaps where the client re-ran work the server had already completed.
headers() now only runs on the server, matching the documented behavior — it is no longer invoked during client-side asset projection.gcTime and preloadGcTime now match the existing runtime default of 5 minutes (300_000).Removed / changed exported internals
RouterState no longer includes loadedAt, isTransitioning, statusCode, or redirect. Use match.updatedAt in place of loadedAt; subscribe to router.state.status / router.state.isLoading in place of isTransitioning; server response status and redirect handling are now internal to the server loader and are no longer exposed on router.state.RouteMatch.fetchCount has been removed, with no replacement — it was purely informational.RouteMatch.status no longer includes 'redirected' (it remains 'pending' | 'success' | 'error' | 'notFound') — redirected matches are dropped from the match list instead of being rendered.RouteMatch.globalNotFound has been renamed and privatized to the internal _notFound field. Use match.status === 'notFound' instead.Match components now accept routeId instead of matchId.RouterStores adapter contract now uses route-keyed presentation stores: matchesId is replaced by ids, matchStores by byRoute, and getRouteMatchStore() by getMatchStore(). The separate loadedAt, isLoading, isTransitioning, statusCode, and redirect stores have been removed, along with the pending/cache stores and their setters. StoreConfig.init has also been removed. Read application-facing state from router.state; preload and cache coordination are now internal.RouterCore members getMatch(), updateMatch(), cancelMatch(), and cancelMatches() — read matches from router.state.matches (e.g. router.state.matches.find((m) => m.id === id)); there is no replacement for mutating or cancelling an individual in-flight match from outside the router.RouterCore.hasNotFoundMatch() — use router.state.matches.some((m) => m.status === 'notFound').RouterCore.looseRoutesById — use routesById.RouterCore.isPrerendering(), RouterCore.isViewTransitionTypesSupported, and RouterCore.viewTransitionPromise, with no replacement.RouterCore.getParsedLocationHref() and RouterCore.clearExpiredCache(), with no replacement — expired cache entries are now reconciled automatically as part of match commit.RouterCore.latestLoadPromise and RouterCore.beforeLoad(), with no replacement.RouterCore.commitLocationPromise and RouterCore.pendingBuiltLocation have been replaced by the internal _commitPromise and _pendingLocation fields.GetMatchFn and UpdateMatchFn types, along with the methods they typed.getMatchedRoutes() export from @tanstack/router-core — use the router.getMatchedRoutes() instance method instead.RouterCore.loadRouteChunk() no longer accepts an array of component types as its second argument. One-argument usage is unchanged; the optional second argument is now 'errorComponent', 'notFoundComponent', or false for internal boundary loading.Redirect.redirectHandled, which was internal redirect bookkeeping.MatchRoutesOpts.preload and MatchRoutesOpts.dest have been removed.StartTransitionFn is now (fn, expected) => Promise<boolean> (previously (fn) => void). This only affects custom framework adapters that implement startTransition.Updated dependencies [45c4ad8]:
Updated dependencies \[`84db4a8`, `9cac62a`, `6aefb33`]:
Updated dependencies \[`b2908c6`]:
Updated dependencies \[`45c4ad8`]:
45c4ad8]:
Nothing published for this version
Updated dependencies [`e2dd204`]:
e2dd204]:
Updated dependencies [`9809a06`]:
#7662 ba52d2b - perf: zero-copy frame payload extraction in the client frame decoder. When a frame's bytes are fully contained in the first buffered chunk (the common case), return a subarray view instead of allocating a new buffer and copying. This is on the hot path for decoding streamed server-function responses and RawStream payloads.
Updated dependencies [9809a06]:
### Patch Changes - #7566 `9bebf8d` - Add validator() as the canonical server function and middleware validator method. Deprecate inputValidator() and
Updated dependencies [`776d8ef`]:
776d8ef]:
Updated dependencies [`df1076c`]:
df1076c]:
Updated dependencies [`ac10815`]:
ac10815]:
Updated dependencies [`2cca73c`, `7a83e67`, `76b3d3b`]:
Updated dependencies [`b4cd5af`]:
b4cd5af]:
Updated dependencies [`2f53749`]:
2f53749]:
Updated dependencies [`d1997b6`]:
d1997b6]:
Fix serialization adapter module resolution in TanStack Start. Vite dev now uses clean runtime-specific virtual module IDs instead of browser requests
#tanstack-start-plugin-adapters through the package empty-adapter fallback. (#7484)Updated dependencies [`51a97a1`]:
51a97a1]:
Updated dependencies [`5268ba4`]:
5268ba4]:
Updated dependencies [`0300f87`, `0300f87`]:
Add deferred Hydrate boundary support for TanStack Start.
Add deferred Hydrate boundary support for TanStack Start. (#7362)
Hydrate boundaries can now be code-split by the Start compiler, preload their generated client chunks, preserve server-rendered fallback HTML, and replay interaction-triggered events after hydration. The compiler integration now uses a Start-owned compiler plugin for Hydrate virtual modules across Vite and Rsbuild, with dev invalidation for generated virtual modules.
Shared AST utilities used by the router code-splitter and Hydrate virtual modules were moved into @tanstack/router-utils so both pipelines can retain referenced top-level declarations, unwrap local exports, and let dead-code elimination remove unused route module code.
5fa9e55]:
Updated dependencies [`b60eb36`]:
b60eb36]:
Updated dependencies [`d9cf933`]:
d9cf933]:
Updated dependencies [`d533f87`]:
d533f87]:
Updated dependencies [`2387a2e`]:
2387a2e]:
Updated dependencies [`b1c061a`, `201e150`, `5ae2ae5`]:
Update seroval dependencies to version 1.5.4.
Invalidation now retires matching active preloads so older speculative loader results cannot become fresh cache data after invalidation.
#7805 45c4ad8 - Rewrite match loading around a lane-based scheduler that tracks each navigation, preload, and background reload as an ordered unit of work. This fixes pending/redirect/retry state leaking between overlapping navigations, restores correct SSR status codes for redirects, errors, and not-found responses, and closes hydration gaps where the client re-ran work the server had already completed.
headers() now only runs on the server, matching the documented behavior — it is no longer invoked during client-side asset projection.gcTime and preloadGcTime now match the existing runtime default of 5 minutes (300_000).Removed / changed exported internals
RouterState no longer includes loadedAt, isTransitioning, statusCode, or redirect. Use match.updatedAt in place of loadedAt; subscribe to router.state.status / router.state.isLoading in place of isTransitioning; server response status and redirect handling are now internal to the server loader and are no longer exposed on router.state.RouteMatch.fetchCount has been removed, with no replacement — it was purely informational.RouteMatch.status no longer includes 'redirected' (it remains 'pending' | 'success' | 'error' | 'notFound') — redirected matches are dropped from the match list instead of being rendered.RouteMatch.globalNotFound has been renamed and privatized to the internal _notFound field. Use match.status === 'notFound' instead.Match components now accept routeId instead of matchId.RouterStores adapter contract now uses route-keyed presentation stores: matchesId is replaced by ids, matchStores by byRoute, and getRouteMatchStore() by getMatchStore(). The separate loadedAt, isLoading, isTransitioning, statusCode, and redirect stores have been removed, along with the pending/cache stores and their setters. StoreConfig.init has also been removed. Read application-facing state from router.state; preload and cache coordination are now internal.RouterCore members getMatch(), updateMatch(), cancelMatch(), and cancelMatches() — read matches from router.state.matches (e.g. router.state.matches.find((m) => m.id === id)); there is no replacement for mutating or cancelling an individual in-flight match from outside the router.RouterCore.hasNotFoundMatch() — use router.state.matches.some((m) => m.status === 'notFound').RouterCore.looseRoutesById — use routesById.RouterCore.isPrerendering(), RouterCore.isViewTransitionTypesSupported, and RouterCore.viewTransitionPromise, with no replacement.RouterCore.getParsedLocationHref() and RouterCore.clearExpiredCache(), with no replacement — expired cache entries are now reconciled automatically as part of match commit.RouterCore.latestLoadPromise and RouterCore.beforeLoad(), with no replacement.RouterCore.commitLocationPromise and RouterCore.pendingBuiltLocation have been replaced by the internal _commitPromise and _pendingLocation fields.GetMatchFn and UpdateMatchFn types, along with the methods they typed.getMatchedRoutes() export from @tanstack/router-core — use the router.getMatchedRoutes() instance method instead.RouterCore.loadRouteChunk() no longer accepts an array of component types as its second argument. One-argument usage is unchanged; the optional second argument is now 'errorComponent', 'notFoundComponent', or false for internal boundary loading.Redirect.redirectHandled, which was internal redirect bookkeeping.MatchRoutesOpts.preload and MatchRoutesOpts.dest have been removed.StartTransitionFn is now (fn, expected) => Promise<boolean> (previously (fn) => void). This only affects custom framework adapters that implement startTransition.Updated dependencies [45c4ad8]:
4a1e63f]:
Add a strict option to createServerFn for type-level server function serialization checks. Use strict: false to opt out for input and output values, o
strict option to createServerFn for type-level server function serialization checks. Use strict: false to opt out for input and output values, or strict: { output: false } to opt out for return values only. (#7277)Updated dependencies \[`2435885`, `84db4a8`, `9cac62a`, `86bf510`, `6aefb33`]:
9cac62a]:
45c4ad8]:
c992495]:
Updated dependencies \[`b2908c6`]:
b2908c6]:
ea3a665]:
b5c4183]:
Updated dependencies \[`84db4a8`, `9cac62a`, `6aefb33`]:
45c4ad8]:
493148b]:
Updated dependencies \[`b2908c6`]:
b2908c6]:
CustomFetch type (#7258)Updated dependencies \[`45c4ad8`]:
45c4ad8]:
4d864ee]:
Updated dependencies [`16f6892`]:
16f6892]:
Updated dependencies [`0e2c900`]:
0e2c900]:
Updated dependencies [`812792f`]:
812792f]:
Updated dependencies [`8ec9ca9`]:
8ec9ca9]:
Updated dependencies [`6355bb7`]:
6355bb7]:
migrate createStore > createAtom for simpler API
### Patch Changes - fix publishing (`f8ac427`)
f8ac427)Ensure request middleware context wins over colliding client-provided context in server function execution paths, including SSR, GET, and FormData req
Updated dependencies [`796406d`]:
796406d]:
Updated dependencies [`2d1ec86`]:
2d1ec86]:
Updated dependencies [`6ee0e79`]:
6ee0e79]:
Your coding agent can read these notes before it upgrades. Set up the MCP server →