Skip to content

Conversation

@schiller-manuel
Copy link
Contributor

@schiller-manuel schiller-manuel commented Jan 12, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Route.redirect() method: a type-safe redirect function bound to the route, with auto-filled from parameter for cleaner relative redirects (e.g., "./overview").
    • Added getRouteApi().redirect() for programmatic redirects outside route definitions with automatic context awareness.
  • Documentation

    • Expanded redirect documentation with examples covering standalone usage, route-bound patterns, and RouteApi approaches for various redirect scenarios.

✏️ Tip: You can customize this high-level summary in your review settings.

@github-actions github-actions bot added documentation Everything documentation related package: router-core labels Jan 12, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 12, 2026

📝 Walkthrough

Walkthrough

This pull request introduces a new route-bound redirect API surface. The Route and RouteApi types now expose a .redirect() method that automatically pre-fills the from parameter with the route's path, enabling type-safe relative redirects. Documentation, type definitions, implementation, and comprehensive tests are added across the router-core package and e2e test suite.

Changes

Cohort / File(s) Summary
Documentation
docs/router/framework/react/api/router/RouteApiType.md, RouteType.md, redirectFunction.md
Added documentation for the new .redirect() method on RouteApiType and Route, with usage examples and benefits. Expanded redirect function documentation to cover standalone, Route.redirect, and getRouteApi().redirect variants.
Type Definitions
packages/router-core/src/redirect.ts, index.ts
Introduced RedirectOptionsRoute type (omitting from field) and RedirectFnRoute interface (route-bound redirect function). Exported both types from the redirect module.
Route Implementation
packages/router-core/src/route.ts
Added redirect property to Route interface, BaseRoute class, and BaseRouteApi class, each implementing the route-bound redirect with auto-filled from parameter.
Type Tests
packages/router-core/tests/redirect.test-d.ts
Added comprehensive TypeScript type assertions verifying RedirectFnRoute, RedirectOptionsRoute, and route-bound redirect behavior across Route and RouteApi.
E2E Test Routes
e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx, via-route-redirect-beforeLoad.tsx, via-route-redirect-loader.tsx, via-routeApi-redirect-beforeLoad.tsx, via-routeApi-redirect-loader.tsx
Added five new test route files covering redirect functionality via Route.redirect, RouteApi.redirect, beforeLoad hooks, and loaders with internal/external redirect scenarios.
E2E Tests & Route Updates
e2e/react-router/basic-file-based/src/routes/redirect/$target/index.tsx, tests/redirect.spec.ts, src/routeTree.gen.ts
Added test UI links exercising new redirect variants, comprehensive e2e test suite covering internal/external redirects with multiple throwing variants, and auto-generated route tree entries.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

package: router-core, package: react-router, documentation

Suggested reviewers

  • nlynzaad
  • Sheraff

Poem

🐰 A redirect so slick, with the path auto-bound,
No more from to repeat, cleaner code all around!
From Route and RouteApi, relative paths take flight,
Type-safe redirects tested—working just right! 🚀✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the primary change: adding Route.redirect and getRouteApi.redirect methods. It is concise, clear, and directly reflects the main feature additions across the codebase.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link

nx-cloud bot commented Jan 12, 2026

View your CI Pipeline Execution ↗ for commit c913f75

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ✅ Succeeded 15m 56s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 1m 42s View ↗

☁️ Nx Cloud last updated this comment at 2026-01-12 21:37:34 UTC

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 12, 2026

More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/arktype-adapter@6373

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/eslint-plugin-router@6373

@tanstack/history

npm i https://pkg.pr.new/TanStack/router/@tanstack/history@6373

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/nitro-v2-vite-plugin@6373

@tanstack/react-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router@6373

@tanstack/react-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-devtools@6373

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-ssr-query@6373

@tanstack/react-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start@6373

@tanstack/react-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-client@6373

@tanstack/react-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-server@6373

@tanstack/router-cli

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-cli@6373

@tanstack/router-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-core@6373

@tanstack/router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools@6373

@tanstack/router-devtools-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools-core@6373

@tanstack/router-generator

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-generator@6373

@tanstack/router-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-plugin@6373

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-ssr-query-core@6373

@tanstack/router-utils

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-utils@6373

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-vite-plugin@6373

@tanstack/solid-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router@6373

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-devtools@6373

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-ssr-query@6373

@tanstack/solid-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start@6373

@tanstack/solid-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-client@6373

@tanstack/solid-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-server@6373

@tanstack/start-client-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-client-core@6373

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-fn-stubs@6373

@tanstack/start-plugin-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-plugin-core@6373

@tanstack/start-server-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-core@6373

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-static-server-functions@6373

@tanstack/start-storage-context

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-storage-context@6373

@tanstack/valibot-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/valibot-adapter@6373

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/TanStack/router/@tanstack/virtual-file-routes@6373

@tanstack/vue-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router@6373

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router-devtools@6373

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router-ssr-query@6373

@tanstack/vue-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start@6373

@tanstack/vue-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start-client@6373

@tanstack/vue-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start-server@6373

@tanstack/zod-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/zod-adapter@6373

commit: c913f75

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In @docs/router/framework/react/api/router/RouteApiType.md:
- Around line 152-182: The docs show RouteApi.redirect as redirect(opts?:
RedirectOptions): Redirect but the text says "all options except from" and
implies from is injected; update the signature to reflect that by changing it to
redirect(opts: Omit<RedirectOptions, 'from'>): Redirect (i.e., make the opts
parameter required and omit 'from' from RedirectOptions) and adjust the
surrounding description to match this signature; reference the RouteApi.redirect
method, RedirectOptions type, and Redirect return type when making the change.

In @packages/router-core/src/route.ts:
- Around line 778-786: Update the doc comment for Route.redirect:
RedirectFnRoute<TFullPath> to consistently use "full path" terminology instead
of "route’s path" (e.g., change "this route's path" to "this route's full path"
or "this route's fullPath") and ensure the description and examples (if any)
reference TFullPath meaningfully so the docs align with the type parameter.
🧹 Nitpick comments (4)
packages/router-core/src/redirect.ts (1)

58-86: Consider aligning default generic params with RedirectOptions (notably TMaskTo) for consistency.
Right now RedirectOptionsRoute defaults TMaskTo to '' while RedirectOptions defaults it to '.', which can make inference/expectations differ between redirect() and Route.redirect().

packages/router-core/src/route.ts (1)

1917-1925: Prevent opts.from from overriding the auto-bound from.
Using { from: this.fullPath, ...opts } allows an any-cast caller to override from, which contradicts the API contract.

Proposed fix
-  redirect: RedirectFnRoute<TFullPath> = (opts) =>
-    redirect({ from: this.fullPath, ...opts } as any)
+  redirect: RedirectFnRoute<TFullPath> = (opts) =>
+    redirect({ ...opts, from: this.fullPath } as any)
packages/router-core/tests/redirect.test-d.ts (1)

1-140: Add a runtime assertion that from is actually auto-populated in .options (not just “returns Response”).
Right now the tests would still pass if from stopped being injected.

Proposed test tightening
   test('should create redirect with to option', () => {
@@
     const result = usersRoute.redirect({ to: '/' })
     expectTypeOf(result).toMatchTypeOf<Response>()
+    expectTypeOf((result as any).options.from).toEqualTypeOf<'/users/$userId'>()
   })
 })
@@
   test('should create redirect with to option', () => {
     const routeApi = new BaseRouteApi({ id: '/users/$userId' })
@@
     const result = routeApi.redirect({ to: '/' })
     expectTypeOf(result).toMatchTypeOf<Response>()
+    expectTypeOf((result as any).options.from).toEqualTypeOf<string>()
   })
 })
docs/router/framework/react/api/router/redirectFunction.md (1)

85-103: Minor style nit: "outside of" → "outside".

Per static analysis, "outside of" is redundant.

📝 Suggested change
 ### Using getRouteApi().redirect
 
-For accessing the redirect method outside of the route definition file, you can use `getRouteApi`:
+For accessing the redirect method outside the route definition file, you can use `getRouteApi`:
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1c440c3 and c913f75.

📒 Files selected for processing (15)
  • docs/router/framework/react/api/router/RouteApiType.md
  • docs/router/framework/react/api/router/RouteType.md
  • docs/router/framework/react/api/router/redirectFunction.md
  • e2e/react-router/basic-file-based/src/routeTree.gen.ts
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/index.tsx
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-beforeLoad.tsx
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-loader.tsx
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsx
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-loader.tsx
  • e2e/react-router/basic-file-based/tests/redirect.spec.ts
  • packages/router-core/src/index.ts
  • packages/router-core/src/redirect.ts
  • packages/router-core/src/route.ts
  • packages/router-core/tests/redirect.test-d.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript strict mode with extensive type safety for all code

Files:

  • e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-loader.tsx
  • packages/router-core/src/index.ts
  • e2e/react-router/basic-file-based/tests/redirect.spec.ts
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-beforeLoad.tsx
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-loader.tsx
  • packages/router-core/src/redirect.ts
  • packages/router-core/tests/redirect.test-d.ts
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/index.tsx
  • packages/router-core/src/route.ts
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsx
  • e2e/react-router/basic-file-based/src/routeTree.gen.ts
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Implement ESLint rules for router best practices using the ESLint plugin router

Files:

  • e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-loader.tsx
  • packages/router-core/src/index.ts
  • e2e/react-router/basic-file-based/tests/redirect.spec.ts
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-beforeLoad.tsx
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-loader.tsx
  • packages/router-core/src/redirect.ts
  • packages/router-core/tests/redirect.test-d.ts
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/index.tsx
  • packages/router-core/src/route.ts
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsx
  • e2e/react-router/basic-file-based/src/routeTree.gen.ts
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (AGENTS.md)

Use relative links to docs/ folder format (e.g., ./guide/data-loading) for internal documentation references

Files:

  • docs/router/framework/react/api/router/RouteType.md
  • docs/router/framework/react/api/router/redirectFunction.md
  • docs/router/framework/react/api/router/RouteApiType.md
🧠 Learnings (10)
📓 Common learnings
Learnt from: schiller-manuel
Repo: TanStack/router PR: 5330
File: packages/router-core/src/router.ts:2231-2245
Timestamp: 2025-10-01T18:30:26.591Z
Learning: In `packages/router-core/src/router.ts`, the `resolveRedirect` method intentionally strips the router's origin from redirect URLs when they match (e.g., `https://foo.com/bar` → `/bar` for same-origin redirects) while preserving the full URL for cross-origin redirects. This logic should not be removed or simplified to use `location.publicHref` directly.
📚 Learning: 2025-10-01T18:30:26.591Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 5330
File: packages/router-core/src/router.ts:2231-2245
Timestamp: 2025-10-01T18:30:26.591Z
Learning: In `packages/router-core/src/router.ts`, the `resolveRedirect` method intentionally strips the router's origin from redirect URLs when they match (e.g., `https://foo.com/bar` → `/bar` for same-origin redirects) while preserving the full URL for cross-origin redirects. This logic should not be removed or simplified to use `location.publicHref` directly.

Applied to files:

  • e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-loader.tsx
  • packages/router-core/src/index.ts
  • e2e/react-router/basic-file-based/tests/redirect.spec.ts
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-beforeLoad.tsx
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-loader.tsx
  • docs/router/framework/react/api/router/RouteType.md
  • packages/router-core/src/redirect.ts
  • docs/router/framework/react/api/router/redirectFunction.md
  • docs/router/framework/react/api/router/RouteApiType.md
  • packages/router-core/tests/redirect.test-d.ts
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/index.tsx
  • packages/router-core/src/route.ts
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsx
  • e2e/react-router/basic-file-based/src/routeTree.gen.ts
📚 Learning: 2025-10-08T08:11:47.088Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5402
File: packages/router-generator/tests/generator/no-formatted-route-tree/routeTree.nonnested.snapshot.ts:19-21
Timestamp: 2025-10-08T08:11:47.088Z
Learning: Test snapshot files in the router-generator tests directory (e.g., files matching the pattern `packages/router-generator/tests/generator/**/routeTree*.snapshot.ts` or `routeTree*.snapshot.js`) should not be modified or have issues flagged, as they are fixtures used to verify the generator's output and are intentionally preserved as-is.

Applied to files:

  • packages/router-core/src/index.ts
  • e2e/react-router/basic-file-based/tests/redirect.spec.ts
  • packages/router-core/tests/redirect.test-d.ts
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/index.tsx
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsx
  • e2e/react-router/basic-file-based/src/routeTree.gen.ts
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Applies to **/*.{js,ts,tsx} : Implement ESLint rules for router best practices using the ESLint plugin router

Applied to files:

  • packages/router-core/src/index.ts
  • packages/router-core/tests/redirect.test-d.ts
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/index.tsx
  • e2e/react-router/basic-file-based/src/routeTree.gen.ts
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Use file-based routing in `src/routes/` directories or code-based routing with route definitions

Applied to files:

  • docs/router/framework/react/api/router/redirectFunction.md
📚 Learning: 2025-10-01T18:31:35.420Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 5330
File: e2e/react-start/custom-basepath/src/routeTree.gen.ts:58-61
Timestamp: 2025-10-01T18:31:35.420Z
Learning: Do not review files named `routeTree.gen.ts` in TanStack Router repositories, as these are autogenerated files that should not be manually modified.

Applied to files:

  • e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx
  • e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsx
  • e2e/react-router/basic-file-based/src/routeTree.gen.ts
📚 Learning: 2025-11-02T16:16:24.898Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5732
File: packages/start-client-core/src/client/hydrateStart.ts:6-9
Timestamp: 2025-11-02T16:16:24.898Z
Learning: In packages/start-client-core/src/client/hydrateStart.ts, the `import/no-duplicates` ESLint disable is necessary for imports from `#tanstack-router-entry` and `#tanstack-start-entry` because both aliases resolve to the same placeholder file (`fake-start-entry.js`) in package.json during static analysis, even though they resolve to different files at runtime.

Applied to files:

  • e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx
📚 Learning: 2025-12-17T02:17:55.086Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 6120
File: packages/router-generator/src/generator.ts:654-657
Timestamp: 2025-12-17T02:17:55.086Z
Learning: In `packages/router-generator/src/generator.ts`, pathless_layout routes must receive a `path` property when they have a `cleanedPath`, even though they are non-path routes. This is necessary because child routes inherit the path from their parent, and without this property, child routes would not have the correct full path at runtime.

Applied to files:

  • e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx
  • packages/router-core/src/route.ts
  • e2e/react-router/basic-file-based/src/routeTree.gen.ts
📚 Learning: 2025-12-21T12:52:35.231Z
Learnt from: Sheraff
Repo: TanStack/router PR: 6171
File: packages/router-core/src/new-process-route-tree.ts:898-898
Timestamp: 2025-12-21T12:52:35.231Z
Learning: In `packages/router-core/src/new-process-route-tree.ts`, the matching logic intentionally allows paths without trailing slashes to match index routes with trailing slashes (e.g., `/a` can match `/a/` route), but not vice-versa (e.g., `/a/` cannot match `/a` layout route). This is implemented via the condition `!pathIsIndex || node.kind === SEGMENT_TYPE_INDEX` and is a deliberate design decision to provide better UX by being permissive with missing trailing slashes.

Applied to files:

  • e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx
  • packages/router-core/src/route.ts
  • e2e/react-router/basic-file-based/src/routeTree.gen.ts
📚 Learning: 2025-09-28T21:41:45.233Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5284
File: e2e/react-start/basic/server.js:50-0
Timestamp: 2025-09-28T21:41:45.233Z
Learning: In Express v5, catch-all routes must use named wildcards. Use `/*splat` to match everything except root path, or `/{*splat}` (with braces) to match including root path. The old `*` syntax is not allowed and will cause "Missing parameter name" errors. This breaking change requires explicit naming of wildcard parameters.

Applied to files:

  • e2e/react-router/basic-file-based/src/routeTree.gen.ts
🧬 Code graph analysis (7)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-loader.tsx (5)
e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx (1)
  • Route (3-9)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-beforeLoad.tsx (1)
  • Route (3-17)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-loader.tsx (1)
  • Route (3-20)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsx (1)
  • Route (7-21)
packages/router-core/src/route.ts (1)
  • Route (588-786)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-beforeLoad.tsx (4)
e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx (1)
  • Route (3-9)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-loader.tsx (1)
  • Route (3-20)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsx (1)
  • Route (7-21)
packages/router-core/src/route.ts (1)
  • Route (588-786)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-loader.tsx (5)
e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx (1)
  • Route (3-9)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-beforeLoad.tsx (1)
  • Route (3-17)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsx (1)
  • Route (7-21)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-loader.tsx (1)
  • Route (5-22)
packages/router-core/src/index.ts (1)
  • Route (159-159)
packages/router-core/tests/redirect.test-d.ts (3)
packages/router-core/src/index.ts (5)
  • RedirectFnRoute (366-366)
  • RedirectOptionsRoute (365-365)
  • BaseRoute (109-109)
  • BaseRouteApi (109-109)
  • redirect (372-372)
packages/router-core/src/redirect.ts (3)
  • RedirectFnRoute (77-85)
  • RedirectOptionsRoute (62-70)
  • redirect (104-147)
packages/router-core/src/route.ts (2)
  • BaseRoute (1545-1926)
  • BaseRouteApi (1928-1949)
e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx (2)
packages/router-core/src/index.ts (1)
  • Route (159-159)
packages/router-core/src/route.ts (1)
  • Route (588-786)
e2e/react-router/basic-file-based/src/routes/redirect/$target/index.tsx (6)
e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx (1)
  • Route (3-9)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-beforeLoad.tsx (1)
  • Route (3-17)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-loader.tsx (1)
  • Route (3-20)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsx (1)
  • Route (7-21)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-loader.tsx (1)
  • Route (5-22)
packages/router-core/src/index.ts (1)
  • Route (159-159)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsx (4)
e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx (1)
  • Route (3-9)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-loader.tsx (1)
  • Route (3-20)
e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-loader.tsx (1)
  • Route (5-22)
packages/router-core/src/route.ts (1)
  • Route (588-786)
🪛 LanguageTool
docs/router/framework/react/api/router/redirectFunction.md

[style] ~87-~87: This phrase is redundant. Consider using “outside”.
Context: ...rect For accessing the redirect method outside of the route definition file, you can use ...

(OUTSIDE_OF)

⏰ 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
🔇 Additional comments (14)
packages/router-core/src/index.ts (1)

362-369: Public exports look good (new redirect route-bound types are discoverable).

packages/router-core/src/route.ts (1)

4-9: No circular dependency issue with the redirect import.

The import of redirect from ./redirect does not create a circular dependency. While route.tsredirect.tsrouter.ts forms a chain, redirect.ts does not import from route.ts (only type imports from router.ts), so the cycle is broken. Additionally, the redirect() function calls at lines 1925 and 1948 occur in class method definitions that are lazily bound at call time, not during module initialization, so bundling and init order remain stable.

e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-loader.tsx (1)

1-22: LGTM! Test route correctly exercises getRouteApi().redirect() in loader context.

The implementation is consistent with sibling route variants (via-route-redirect-loader, via-routeApi-redirect-beforeLoad). The relative redirect to ../destination properly tests the key feature of automatic from parameter binding.

e2e/react-router/basic-file-based/tests/redirect.spec.ts (2)

137-205: Comprehensive test coverage for Route.redirect() API.

Good use of test matrices to cover beforeLoad and loader throwers across internal relative redirects and external redirects. The tests properly validate:

  • URL navigation to /redirect/internal/destination
  • Visibility of redirect-destination test element
  • External redirect URL resolution

207-275: Parallel test coverage for getRouteApi().redirect() confirms API parity.

The symmetric test structure between Route.redirect() and getRouteApi().redirect() test blocks ensures both APIs behave consistently for internal relative and external redirects.

e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-beforeLoad.tsx (1)

1-17: LGTM! Clean demonstration of Route.redirect() in beforeLoad context.

The implementation correctly showcases the key feature: type-safe relative redirects without needing to specify from. The beforeLoad hook has direct access to search params, making loaderDeps unnecessary here (unlike the loader variant).

docs/router/framework/react/api/router/redirectFunction.md (2)

57-83: Excellent documentation for Route.redirect() with practical examples.

The examples clearly demonstrate both beforeLoad and loader usage with relative paths (../login, ./migrate), which is the key feature of this API. The inline comments explaining the redirect destinations are helpful.


105-111: Clear summary of route-bound redirect benefits.

The three-point benefits list effectively communicates the value proposition over the standalone redirect function.

e2e/react-router/basic-file-based/src/routes/redirect/$target/via-route-redirect-loader.tsx (1)

1-20: LGTM! Demonstrates Route.redirect() in loader context with loaderDeps.

The implementation correctly uses loaderDeps to pass externalHost to the loader (since loaders don't have direct search access like beforeLoad). This pairs well with the via-route-redirect-beforeLoad.tsx variant to demonstrate both hook contexts.

docs/router/framework/react/api/router/RouteType.md (1)

29-51: LGTM! Well-documented new API surface.

The documentation clearly explains the .redirect method's type-safe behavior, auto-binding of from to the route's fullPath, and includes a practical example demonstrating relative redirects in a beforeLoad guard. The internal documentation links correctly use relative paths as per coding guidelines.

e2e/react-router/basic-file-based/src/routes/redirect/$target/destination.tsx (1)

1-9: LGTM! Clean test destination route.

Simple and focused route module serving as the redirect target for the new Route.redirect and routeApi.redirect e2e tests. The data-testid attribute enables reliable test assertions.

e2e/react-router/basic-file-based/src/routes/redirect/$target/index.tsx (1)

63-116: LGTM! Consistent test navigation links.

The new Link elements follow the established pattern in this file and provide comprehensive coverage for both Route.redirect() and getRouteApi().redirect() scenarios across beforeLoad and loader hooks. The comments clearly delineate test groups.

e2e/react-router/basic-file-based/src/routes/redirect/$target/via-routeApi-redirect-beforeLoad.tsx (1)

1-21: LGTM! Well-structured test route for routeApi.redirect().

The implementation correctly demonstrates the getRouteApi().redirect() API with both internal (relative ../destination) and external redirect scenarios. The pattern is consistent with the sibling via-route-redirect-* routes that use Route.redirect() directly.

e2e/react-router/basic-file-based/src/routeTree.gen.ts (1)

1-9: Skipping review of autogenerated file.

This file is autogenerated by TanStack Router and should not be manually modified. Based on learnings, routeTree.gen.ts files are excluded from review.

Comment on lines +152 to +182

### `redirect` method

```tsx
redirect(opts?: RedirectOptions): Redirect
```

- A type-safe version of the [`redirect`](./redirectFunction.md) function that is pre-bound to the route ID that the `RouteApi` instance was created with.
- The `from` parameter is automatically set to the route ID, enabling type-safe relative redirects.
- Options
- All options from [`redirect`](./redirectFunction.md) except `from`, which is automatically provided.
- Returns
- A `Redirect` object that can be thrown from `beforeLoad` or `loader` callbacks.

#### Example

```tsx
import { getRouteApi } from '@tanstack/react-router'

const routeApi = getRouteApi('/dashboard/settings')

export const Route = createFileRoute('/dashboard/settings')({
beforeLoad: ({ context }) => {
if (!context.user) {
// Type-safe redirect - 'from' is automatically '/dashboard/settings'
throw routeApi.redirect({
to: '../login', // Relative path to sibling route
})
}
},
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Doc signature should reflect “options without from” (and likely shouldn’t be optional).
The section says RedirectOptions, but the described behavior is “all redirect options except from”. Consider updating the signature text accordingly to avoid confusion.

Proposed doc edit
 ```tsx
-  redirect(opts?: RedirectOptions): Redirect
+  redirect(opts: Omit<RedirectOptions, 'from'>): Redirect

@@
-- Options

    • All options from redirect except from, which is automatically provided.
      +- Options
    • All options from redirect except from, which is automatically provided.
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

In @docs/router/framework/react/api/router/RouteApiType.md around lines 152 -
182, The docs show RouteApi.redirect as redirect(opts?: RedirectOptions):
Redirect but the text says "all options except from" and implies from is
injected; update the signature to reflect that by changing it to redirect(opts:
Omit<RedirectOptions, 'from'>): Redirect (i.e., make the opts parameter required
and omit 'from' from RedirectOptions) and adjust the surrounding description to
match this signature; reference the RouteApi.redirect method, RedirectOptions
type, and Redirect return type when making the change.


</details>

<!-- This is an auto-generated comment by CodeRabbit -->

Comment on lines +778 to 786
/**
* Create a redirect with `from` automatically set to this route's path.
* Enables relative redirects like `Route.redirect({ to: './overview' })`.
* @param opts Redirect options (same as `redirect()` but without `from`)
* @returns A redirect Response that can be thrown from loaders/beforeLoad
* @link https://tanstack.com/router/latest/docs/framework/react/api/router/redirectFunction
*/
redirect: RedirectFnRoute<TFullPath>
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Route.redirect: RedirectFnRoute<TFullPath> matches the goal and reads well.
Small doc nit: the text says “route’s path”, but this is TFullPath (full path), so consider using “fullPath” terminology here too.

🤖 Prompt for AI Agents
In @packages/router-core/src/route.ts around lines 778 - 786, Update the doc
comment for Route.redirect: RedirectFnRoute<TFullPath> to consistently use "full
path" terminology instead of "route’s path" (e.g., change "this route's path" to
"this route's full path" or "this route's fullPath") and ensure the description
and examples (if any) reference TFullPath meaningfully so the docs align with
the type parameter.

Comment on lines +1939 to +1948
/**
* Create a redirect with `from` automatically set to this route's path.
* Enables relative redirects like `routeApi.redirect({ to: './overview' })`.
* @param opts Redirect options (same as `redirect()` but without `from`)
* @returns A redirect Response that can be thrown from loaders/beforeLoad
* @link https://tanstack.com/router/latest/docs/framework/react/api/router/redirectFunction
*/
redirect: RedirectFnRoute<RouteTypesById<TRouter, TId>['fullPath']> = (
opts,
) => redirect({ from: this.id as string, ...opts } as any)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, let's find the NavigateOptions definition and understand what 'from' represents
echo "=== Searching for NavigateOptions type ==="
rg -n "export type NavigateOptions|interface NavigateOptions" packages/router-core/src -A 15 | head -100

echo -e "\n=== Searching for 'from' property in NavigateOptions ==="
rg -n "from\s*\??:\s*" packages/router-core/src -B 2 -A 2 | grep -A 5 -B 5 "NavigateOptions\|RouteId\|fullPath" | head -100

Repository: TanStack/router

Length of output: 4203


🏁 Script executed:

#!/bin/bash
# Check redirect resolution and how 'from' is processed
echo "=== Searching for redirect resolution logic ==="
rg -n "resolveRedirect|buildLocation" packages/router-core/src --type=ts -B 2 -A 5 | head -150

echo -e "\n=== Searching for how 'from' is used in routing ==="
rg -n "options\.from|\.from\s*\)" packages/router-core/src --type=ts -B 2 -A 2 | head -100

Repository: TanStack/router

Length of output: 10658


🏁 Script executed:

#!/bin/bash
# Look at the actual redirect type and how it processes 'from'
echo "=== Finding redirect function definition ==="
rg -n "export.*redirect\s*=" packages/router-core/src --type=ts -A 10 | head -150

echo -e "\n=== Searching for relative path resolution with 'from' ==="
rg -n "resolveFromPath|resolvePath|ResolveRelativePath" packages/router-core/src --type=ts -B 2 -A 5 | head -100

Repository: TanStack/router

Length of output: 6403


🏁 Script executed:

#!/bin/bash
# Check how RouteTypesById works and what 'fullPath' represents
echo "=== Understanding RouteTypesById and fullPath ==="
rg -n "RouteTypesById|type.*fullPath" packages/router-core/src --type=ts -B 1 -A 3 | head -150

Repository: TanStack/router

Length of output: 2232


🏁 Script executed:

#!/bin/bash
# Check if opts can contain 'from' and whether spread order matters
echo "=== Checking RedirectOptions type definition ==="
rg -n "interface RedirectOptions|type RedirectOptions" packages/router-core/src --type=ts -A 15 | head -100

echo -e "\n=== Check RouteApi redirect method context ==="
sed -n '1910,1950p' packages/router-core/src/route.ts

echo -e "\n=== Verify if from is ever passed in opts to redirect ==="
rg -n "redirect\s*\(\s*\{[^}]*from" packages/router-core/src --type=ts | head -20

Repository: TanStack/router

Length of output: 4286


🏁 Script executed:

#!/bin/bash
# Check the redirect function signature to understand what happens with duplicate 'from'
echo "=== Finding redirect function definition ==="
rg -n "^export.*function redirect|^export const redirect" packages/router-core/src --type=ts -A 20 | head -150

Repository: TanStack/router

Length of output: 1762


🏁 Script executed:

#!/bin/bash
# Verify what 'from' actually represents in buildLocation and path resolution
echo "=== Check how from is used in buildLocation ==="
sed -n '1631,1680p' packages/router-core/src/router.ts

echo -e "\n=== Check getMatchedRoutes to understand if from is route id ==="
rg -n "getMatchedRoutes" packages/router-core/src/router.ts -A 8 | head -80

Repository: TanStack/router

Length of output: 3467


🏁 Script executed:

#!/bin/bash
# Clarify what the type parameter in RedirectFnRoute means
echo "=== Check RedirectFnRoute interface ==="
sed -n '72,100p' packages/router-core/src/redirect.ts

Repository: TanStack/router

Length of output: 1475


🏁 Script executed:

#!/bin/bash
# Determine if route ids can be used as paths or if fullPath is needed
echo "=== Check if Route and BaseRouteApi have different implementations ==="
rg -n "class Route\b|class BaseRouteApi" packages/router-core/src/route.ts -A 50 | grep -A 40 "redirect:"

echo -e "\n=== Search for usage examples of BaseRouteApi.redirect or RouteApi.redirect ==="
rg -n "routeApi\.redirect|\.redirect\(" packages/router-core/src --type=ts | grep -i "routeapi\|baseRouteApi" | head -20

Repository: TanStack/router

Length of output: 1411


🏁 Script executed:

#!/bin/bash
# Check if route id and fullPath are ever used interchangeably
echo "=== Verify RouteApi vs Route context ==="
sed -n '1900,1950p' packages/router-core/src/route.ts

echo -e "\n=== Check if id and fullPath are same in some cases ==="
rg -n "this\.id.*===.*this\.fullPath|this\.fullPath.*===.*this\.id" packages/router-core/src --type=ts

Repository: TanStack/router

Length of output: 1789


🏁 Script executed:

#!/bin/bash
# Final verification: is Route.redirect using fullPath the correct pattern?
echo "=== Check Route implementation context ==="
sed -n '1600,1630p' packages/router-core/src/route.ts

echo -e "\n=== Confirm Route.redirect uses fullPath ==="
sed -n '1918,1926p' packages/router-core/src/route.ts

echo -e "\n=== Understand RouteTypesById to verify type semantics ==="
rg -n "type RouteTypesById" packages/router-core/src/route.ts -A 5

Repository: TanStack/router

Length of output: 1481


Fix JSDoc and update from parameter in BaseRouteApi.redirect from route id to fullPath.

The JSDoc says from is set to "this route's path", but the implementation uses this.id (a route id), creating a semantic mismatch with the type parameter RouteTypesById<TRouter, TId>['fullPath']. In buildLocation (router.ts:1644), from is compared to fullPath and used as a pathname, not as a route id. This means the implementation should either use the route's fullPath or clarify that from accepts route ids. For consistency with Route.redirect (line 1925, which uses from: this.fullPath) and how from is actually consumed, BaseRouteApi.redirect should pass the fullPath.

Adjust the spread order defensively: { ...opts, from: this.id } prevents accidental override (though RedirectOptionsRoute omits 'from' anyway).

function checkAuth() {
if (!user) {
// Type-safe redirect with automatic 'from' parameter
throw routeApi.redirect({

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this produce a confusing navigation history? Via getRouteApi, you can produce a redirect where from points to a different route where you've actually issued the redirect. This example is fine, but the API itself has this footgun.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this API just allows you to use relative notation for building redirect targets. has nothing to do with navigation history

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad, misread the intention then. Excited for this one to land!

@schiller-manuel schiller-manuel merged commit 5299f0b into main Jan 14, 2026
6 checks passed
@schiller-manuel schiller-manuel deleted the route-redirect branch January 14, 2026 20:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Everything documentation related package: router-core

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants