Skip to content

Conversation

@nlynzaad
Copy link
Contributor

@nlynzaad nlynzaad commented Dec 20, 2025

This PR addresses issues raised in #5200 and #5202.

It correctly sets the href using the rewrite url path and adds additional logic in the output section of the rewrite to check for paths that is already prefixed with the base path.

We also add an e2e test on router to test for redirects without reloadDocument = true.

This PR replaces #5202 and resolves #5200

Summary by CodeRabbit

  • New Features

    • Added a "/redirect" route and a UI button that navigates to it; visiting "/redirect" immediately redirects to the About page.
  • Bug Fixes

    • Programmatic redirects now respect the app basepath; location construction aligned with rewritten paths.
  • Refactor

    • Centralized basepath handling to improve consistency.
  • Tests

    • Added and updated end-to-end tests covering basepath, redirect behavior, and navigation assertions.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 20, 2025

Walkthrough

Adds a file-based "/redirect" route that performs a beforeLoad redirect to "/about", updates route tree and UI to trigger it, adds an e2e test asserting redirects respect the basepath, and refactors router-core rewrite/buildLocation logic to centralize basepath handling and unify rewritten hrefs.

Changes

Cohort / File(s) Summary
Generated route tree
e2e/react-router/basepath-file-based/src/routeTree.gen.ts
Adds a new RedirectRoute entry and integrates it into the root route children and all route collections (by fullPath, to, id, path typings).
File-based redirect route
e2e/react-router/basepath-file-based/src/routes/redirect.tsx
New file route createFileRoute('/redirect') with a beforeLoad that throws a redirect to /about, and a simple render component; exports Route.
UI trigger for redirect
e2e/react-router/basepath-file-based/src/routes/index.tsx
Adds a "Navigate to /redirect" button that calls navigate({ to: '/redirect' }).
E2E test for basepath-aware redirect
e2e/react-router/basepath-file-based/tests/reload-document.test.ts
New test "redirect respects basepath" that clicks the redirect button and asserts the URL and target view update under the configured basepath.
Client navigation test tweak
e2e/react-start/custom-basepath/tests/navigation.spec.ts
Replaces network-idle/visibility syncs with explicit URL match and viewport visibility checks for client-side navigation to /posts/1.
Rewrite helper refactor
packages/router-core/src/rewrite.ts
Introduces removeBasePath helper to centralize stripping/handling of basepath and uses it for input/output rewrite logic.
Location construction update
packages/router-core/src/router.ts
RouterCore.buildLocation now computes rewrittenFullPath and derives both publicHref and href from it (rewritten pathname + search + hash).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay special attention to:
    • packages/router-core/src/rewrite.ts: correctness of basepath matching, edge cases for exact basepath vs. prefix with slash, and no-regression of existing rewrite behavior.
    • packages/router-core/src/router.ts: ensure rewrittenFullPath composition (pathname/search/hash) is correct and consistent for both href and publicHref.
    • e2e/react-router/basepath-file-based/src/routes/redirect.tsx and the new test: validate redirect semantics (beforeLoad throw) and that tests correctly simulate basepath contexts.

Possibly related PRs

Suggested labels

package: react-router

Suggested reviewers

  • schiller-manuel
  • Sheraff

Poem

🐰 I hopped a path that once went astray,
Found a redirect to brighten the day,
Basepath trimmed and routes aligned,
URLs behave — no more to find! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(router-core): enhance basePath handling' clearly and concisely describes the main change, focusing on improving basePath functionality in router-core.
Linked Issues check ✅ Passed The PR successfully addresses the objectives from #5200 by fixing basPath handling in rewrite logic, ensuring browser URLs are correctly prefixed, and adding test coverage for redirect scenarios.
Out of Scope Changes check ✅ Passed All changes directly support basPath handling improvements: core refactoring (rewrite.ts, router.ts), test infrastructure updates, and e2e tests validating the fix.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch basepath-redirect

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 715c881 and 9ea0f93.

📒 Files selected for processing (3)
  • e2e/react-router/basepath-file-based/src/routes/index.tsx (1 hunks)
  • packages/router-core/src/rewrite.ts (1 hunks)
  • packages/router-core/src/router.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/router-core/src/rewrite.ts
  • packages/router-core/src/router.ts
  • e2e/react-router/basepath-file-based/src/routes/index.tsx
⏰ 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

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

@nx-cloud
Copy link

nx-cloud bot commented Dec 20, 2025

View your CI Pipeline Execution ↗ for commit 9ea0f93

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

☁️ Nx Cloud last updated this comment at 2025-12-20 16:18:44 UTC

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: 2

🧹 Nitpick comments (1)
packages/router-core/src/rewrite.ts (1)

4-5: Duplicate comment lines.

Lines 4-5, 23-24, 69-70, and 86-87 contain duplicated JSDoc comments. This appears to be an unintentional copy-paste artifact.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c906682 and 715c881.

📒 Files selected for processing (7)
  • e2e/react-router/basepath-file-based/src/routeTree.gen.ts (3 hunks)
  • e2e/react-router/basepath-file-based/src/routes/index.tsx (1 hunks)
  • e2e/react-router/basepath-file-based/src/routes/redirect.tsx (1 hunks)
  • e2e/react-router/basepath-file-based/tests/reload-document.test.ts (1 hunks)
  • e2e/react-start/custom-basepath/tests/navigation.spec.ts (1 hunks)
  • packages/router-core/src/rewrite.ts (1 hunks)
  • packages/router-core/src/router.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript strict mode with extensive type safety for all code

Files:

  • e2e/react-router/basepath-file-based/src/routes/redirect.tsx
  • e2e/react-router/basepath-file-based/tests/reload-document.test.ts
  • e2e/react-router/basepath-file-based/src/routes/index.tsx
  • packages/router-core/src/rewrite.ts
  • e2e/react-start/custom-basepath/tests/navigation.spec.ts
  • packages/router-core/src/router.ts
  • e2e/react-router/basepath-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/basepath-file-based/src/routes/redirect.tsx
  • e2e/react-router/basepath-file-based/tests/reload-document.test.ts
  • e2e/react-router/basepath-file-based/src/routes/index.tsx
  • packages/router-core/src/rewrite.ts
  • e2e/react-start/custom-basepath/tests/navigation.spec.ts
  • packages/router-core/src/router.ts
  • e2e/react-router/basepath-file-based/src/routeTree.gen.ts
🧠 Learnings (11)
📓 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.
Learnt from: nlynzaad
Repo: TanStack/router PR: 5182
File: e2e/react-router/basic-file-based/src/routes/non-nested/named/$baz_.bar.tsx:3-5
Timestamp: 2025-09-22T00:56:49.237Z
Learning: In TanStack Router, underscores are intentionally stripped from route segments (e.g., `$baz_` becomes `baz` in generated types) but should be preserved in base path segments. This is the correct behavior as of the fix in PR #5182.
Learnt from: nlynzaad
Repo: TanStack/router PR: 5182
File: e2e/react-router/basic-file-based/tests/non-nested-paths.spec.ts:167-172
Timestamp: 2025-09-22T00:56:53.426Z
Learning: In TanStack Router, underscores are intentionally stripped from route segments during path parsing, but preserved in base path segments. This is the expected behavior implemented in PR #5182.
Learnt from: FatahChan
Repo: TanStack/router PR: 5475
File: e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-beforeLoad.tsx:8-0
Timestamp: 2025-10-14T18:59:33.990Z
Learning: In TanStack Router e2e test files, when a route parameter is validated at the route level (e.g., using zod in validateSearch or param validation), switch statements on that parameter do not require a default case, as the validation ensures only expected values will reach the switch.
📚 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/basepath-file-based/src/routes/redirect.tsx
  • e2e/react-router/basepath-file-based/tests/reload-document.test.ts
  • e2e/react-router/basepath-file-based/src/routes/index.tsx
  • packages/router-core/src/rewrite.ts
  • packages/router-core/src/router.ts
  • e2e/react-router/basepath-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:

  • e2e/react-router/basepath-file-based/src/routes/redirect.tsx
  • e2e/react-router/basepath-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:

  • e2e/react-router/basepath-file-based/src/routes/redirect.tsx
  • e2e/react-router/basepath-file-based/src/routeTree.gen.ts
📚 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/basepath-file-based/src/routes/redirect.tsx
  • packages/router-core/src/rewrite.ts
  • packages/router-core/src/router.ts
  • e2e/react-router/basepath-file-based/src/routeTree.gen.ts
📚 Learning: 2025-09-22T00:56:49.237Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5182
File: e2e/react-router/basic-file-based/src/routes/non-nested/named/$baz_.bar.tsx:3-5
Timestamp: 2025-09-22T00:56:49.237Z
Learning: In TanStack Router, underscores are intentionally stripped from route segments (e.g., `$baz_` becomes `baz` in generated types) but should be preserved in base path segments. This is the correct behavior as of the fix in PR #5182.

Applied to files:

  • packages/router-core/src/rewrite.ts
📚 Learning: 2025-09-22T00:56:53.426Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5182
File: e2e/react-router/basic-file-based/tests/non-nested-paths.spec.ts:167-172
Timestamp: 2025-09-22T00:56:53.426Z
Learning: In TanStack Router, underscores are intentionally stripped from route segments during path parsing, but preserved in base path segments. This is the expected behavior implemented in PR #5182.

Applied to files:

  • packages/router-core/src/rewrite.ts
📚 Learning: 2025-10-09T12:59:02.129Z
Learnt from: hokkyss
Repo: TanStack/router PR: 5418
File: e2e/react-start/custom-identifier-prefix/src/styles/app.css:19-21
Timestamp: 2025-10-09T12:59:02.129Z
Learning: In e2e test directories (paths containing `e2e/`), accessibility concerns like outline suppression patterns are less critical since the code is for testing purposes, not production use.

Applied to files:

  • e2e/react-start/custom-basepath/tests/navigation.spec.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:

  • e2e/react-start/custom-basepath/tests/navigation.spec.ts
  • packages/router-core/src/router.ts
  • e2e/react-router/basepath-file-based/src/routeTree.gen.ts
📚 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/basepath-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/basepath-file-based/src/routeTree.gen.ts
🧬 Code graph analysis (2)
e2e/react-router/basepath-file-based/src/routes/redirect.tsx (1)
e2e/react-router/basepath-file-based/src/routes/index.tsx (1)
  • Route (3-5)
packages/router-core/src/rewrite.ts (1)
packages/router-core/src/path.ts (1)
  • joinPaths (12-20)
⏰ 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 (5)
e2e/react-start/custom-basepath/tests/navigation.spec.ts (1)

50-52: LGTM - improved test assertions.

Using waitForURL and toBeInViewport() is more reliable than waitForLoadState('networkidle') and manual isVisible() checks. These changes follow Playwright best practices for navigation testing.

e2e/react-router/basepath-file-based/src/routes/redirect.tsx (1)

1-12: LGTM - well-structured redirect route for testing.

The route correctly uses throw redirect() in beforeLoad to trigger a redirect to /about. This follows TanStack Router's recommended pattern for route-level redirects.

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

1761-1771: LGTM - correct basepath handling for href construction.

The change correctly derives both publicHref and href from the rewritten URL path (which includes the basepath). The internal pathname (line 1767) correctly remains the non-rewritten path for route matching purposes.

This aligns with the PR objective to fix href construction by using the rewritten URL path.

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

1-95: Autogenerated file - no review required.

This file is autogenerated by TanStack Router and should not be manually modified. The changes correctly reflect the addition of the new /redirect route to the route tree structure.

Based on learnings, routeTree.gen.ts files are not reviewed as they are automatically generated.

e2e/react-router/basepath-file-based/tests/reload-document.test.ts (1)

20-28: LGTM! Solid test coverage for basepath-aware redirects.

The new test case correctly verifies that programmatic redirects (via beforeLoad) respect the configured basepath. The test flow is clear: clicking the redirect button should navigate through /redirect (which redirects to /about) and end up at /app/about with the basepath intact.

This complements the existing test nicely by covering the redirect scenario alongside the reloadDocument=true navigation case.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 20, 2025

More templates

@tanstack/arktype-adapter

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

@tanstack/directive-functions-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/directive-functions-plugin@6157

@tanstack/eslint-plugin-router

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

@tanstack/history

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

@tanstack/nitro-v2-vite-plugin

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

@tanstack/react-router

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

@tanstack/react-router-devtools

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

@tanstack/react-router-ssr-query

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

@tanstack/react-start

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

@tanstack/react-start-client

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

@tanstack/react-start-server

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

@tanstack/router-cli

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

@tanstack/router-core

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

@tanstack/router-devtools

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

@tanstack/router-devtools-core

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

@tanstack/router-generator

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

@tanstack/router-plugin

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

@tanstack/router-ssr-query-core

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

@tanstack/router-utils

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

@tanstack/router-vite-plugin

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

@tanstack/server-functions-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/server-functions-plugin@6157

@tanstack/solid-router

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

@tanstack/solid-router-devtools

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

@tanstack/solid-router-ssr-query

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

@tanstack/solid-start

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

@tanstack/solid-start-client

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

@tanstack/solid-start-server

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

@tanstack/start-client-core

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

@tanstack/start-plugin-core

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

@tanstack/start-server-core

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

@tanstack/start-static-server-functions

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

@tanstack/start-storage-context

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

@tanstack/valibot-adapter

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

@tanstack/virtual-file-routes

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

@tanstack/vue-router

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

@tanstack/vue-router-devtools

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

@tanstack/vue-router-ssr-query

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

@tanstack/vue-start

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

@tanstack/vue-start-client

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

@tanstack/vue-start-server

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

@tanstack/zod-adapter

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

commit: 9ea0f93

@nlynzaad
Copy link
Contributor Author

#6201 resolved majority of the issues this PR addressed in a better way. the remining issue is regarding redirects combined with basepaths and reloadDocument=true.

Closing this as the remaining issue is dealt with in #6205 that replaces this PR

@nlynzaad nlynzaad closed this Dec 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

v1.132.2 basePath is not working for browser url

2 participants