Skip to content

Conversation

@schiller-manuel
Copy link
Contributor

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

fixes #6403
fixes #2675
fixes #4892
fixes #4804
fixes #3005

Summary by CodeRabbit

  • Bug Fixes

    • Fixed fullPath for pathless layouts to be "/" and normalized trailing-slash handling across routes.
  • New Features

    • Added a new "Settings" path under a pathless layout and a "FullPath Test" section with index and param pages.
  • Tests

    • Added/expanded type-level and end-to-end tests to verify fullPath and trailing-slash behavior.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 17, 2026

📝 Walkthrough

Walkthrough

This PR normalizes route path handling (trailing-slash semantics), fixes pathless-layout fullPath inference (root becomes '/'), enforces uniqueness/validation for empty route paths, updates route map construction with index-route precedence, adjusts route initialization to trim _to, and adds tests and snapshots covering the changes.

Changes

Cohort / File(s) Summary
Core path inference & map construction
packages/router-generator/src/utils.ts
Reworked inferPath/inferFullPath (root -> '/', preserve index trailing slash, strip otherwise), added shouldPreferIndexRoute, replaced map builds with explicit loops applying index-route precedence, and added upfront empty-root-path validation.
Route init trimming
packages/router-core/src/route.ts
Route _to now computed via trimPathRight(fullPath) during initialization.
Type & unit tests
packages/react-router/tests/routeApi.test-d.tsx, packages/router-generator/tests/utils.test.ts, packages/router-generator/tests/generator/*.test-d.ts
New/updated type-level tests asserting fullPath correctness for pathless layouts and index routes; inferFullPath unit test added.
Pathless layout fixtures & snapshots
packages/router-generator/tests/generator/nested-verboseFileRoutes-{false,true}/routes/_pathlessLayout*.tsx, .../routeTree.snapshot.ts, .../tests.test-d.ts
Added pathless layout route files and wired snapshots/types for PathlessLayout and its settings child; updated many snapshots to reflect trailing-slash normalization.
Generated route tree snapshots (trailing-slash normalization)
Multiple: packages/router-generator/tests/generator/{nested-layouts,virtual-config-file-*,virtual,custom-tokens,flat,no-formatted-route-tree,numbers-in-path,path-above-route-in-group,virtual-*}/routeTree.snapshot.ts and many e2e/example routeTree.gen.ts files
Normalized FileRoutesByFullPath / FileRoutesByTo / FileRouteTypes / module augmentations to use trailing slashes for index and dynamic routes (e.g., '/hello' → '/hello/').
E2E & example route files and tests
e2e/react-router/basic-file-based/src/routes/fullpath-test/*, e2e/react-router/basic-file-based/tests/fullpath-types.spec.ts, various examples & e2e route files under react/solid/vue`
Added fullpath-test routes and Playwright tests to assert runtime fullPath behavior; updated Link/from usages in examples/tests to match trailing-slash convention.

Sequence Diagram(s)

sequenceDiagram
    participant Gen as Generator
    participant Infer as inferPath / inferFullPath
    participant Map as createRouteNodesByFullPath/To
    participant Check as checkRouteFullPathUniqueness
    participant Route as Route Init

    Gen->>Infer: compute cleanedPath(route.path)
    Infer-->>Gen: cleanedPath ('' or '/...' normalized)
    Gen->>Map: iterate nodes
    Map->>Infer: inferFullPath(node)
    Infer-->>Map: fullPath ('' → '/', index retains trailing '/')
    Map->>Map: if fullPath '/' and exists -> shouldPreferIndexRoute?
    alt prefer existing index
        Map-->>Map: skip or replace based on precedence
    else
        Map-->>Map: insert route
    end
    Map-->>Gen: built route map
    Gen->>Check: validate route paths
    Check->>Check: if routePath === '' -> throw detailed error
    Check-->>Gen: validated or error
    Gen->>Route: create Route(fullPath)
    Route->>Route: _to = trimPathRight(fullPath)
    Route-->>Gen: route instance
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • nlynzaad

Poem

🐰
Hopping through routes, I tidy each track,
Trailing slashes curl neatly at back.
Pathless layouts no longer feel small—
Root wears '/', proud, standing tall.
Types and runtime now leap in one pack!

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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: fullpath handling' is a concise summary closely related to the changeset, which makes comprehensive fixes to fullPath logic across router packages.
Linked Issues check ✅ Passed All linked issues (#6403, #2675, #4892, #4804, #3005) have coding requirements that are met: fullPath now returns '/' for pathless layouts instead of empty string, trailing slash normalization for index routes is consistent between types and runtime values, empty string is removed from fullPath type unions, and Route.to is made consistent with TypeScript types.
Out of Scope Changes check ✅ Passed All changes are directly related to fullPath handling improvements. The modifications to inferPath, inferFullPath, route validation, test snapshots, and e2e tests are all in scope for addressing the linked issues about fullPath consistency.

✏️ 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 17, 2026

🤖 Nx Cloud AI Fix Eligible

An automatically generated fix could have helped fix failing tasks for this run, but Self-healing CI is disabled for this workspace. Visit workspace settings to enable it and get automatic fixes in future runs.

To disable these notifications, a workspace admin can disable them in workspace settings.


View your CI Pipeline Execution ↗ for commit 053efe5

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

☁️ Nx Cloud last updated this comment at 2026-01-17 16:15:49 UTC

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 17, 2026

More templates

@tanstack/arktype-adapter

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

@tanstack/eslint-plugin-router

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

@tanstack/history

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

@tanstack/nitro-v2-vite-plugin

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

@tanstack/react-router

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

@tanstack/react-router-devtools

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

@tanstack/react-router-ssr-query

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

@tanstack/react-start

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

@tanstack/react-start-client

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

@tanstack/react-start-server

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

@tanstack/router-cli

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

@tanstack/router-core

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

@tanstack/router-devtools

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

@tanstack/router-devtools-core

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

@tanstack/router-generator

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

@tanstack/router-plugin

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

@tanstack/router-ssr-query-core

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

@tanstack/router-utils

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

@tanstack/router-vite-plugin

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

@tanstack/solid-router

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

@tanstack/solid-router-devtools

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

@tanstack/solid-router-ssr-query

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

@tanstack/solid-start

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

@tanstack/solid-start-client

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

@tanstack/solid-start-server

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

@tanstack/start-client-core

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

@tanstack/start-fn-stubs

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

@tanstack/start-plugin-core

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

@tanstack/start-server-core

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

@tanstack/start-static-server-functions

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

@tanstack/start-storage-context

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

@tanstack/valibot-adapter

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

@tanstack/virtual-file-routes

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

@tanstack/vue-router

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

@tanstack/vue-router-devtools

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

@tanstack/vue-router-ssr-query

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

@tanstack/vue-start

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

@tanstack/vue-start-client

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

@tanstack/vue-start-server

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

@tanstack/zod-adapter

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

commit: 053efe5

Copy link
Member

@SeanCassiere SeanCassiere left a comment

Choose a reason for hiding this comment

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

It always comes back to the generator 😩

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

🤖 Fix all issues with AI agents
In
`@packages/router-generator/tests/generator/nested-verboseFileRoutes-false/routes/_pathlessLayout.tsx`:
- Around line 1-4: The file defines Route using createFileRoute but never
imports it; add the missing import for createFileRoute from
'@tanstack/react-router' alongside the existing Outlet import so the
createFileRoute symbol is available when constructing the Route component
(ensure the import statement includes createFileRoute and retains Outlet to
avoid the runtime error in the Route definition).

In
`@packages/router-generator/tests/generator/nested-verboseFileRoutes-true/tests.test-d.ts`:
- Around line 13-16: Reorder the imports in tests.test-d.ts so the type-only
import from '@tanstack/react-router' comes after the generated module import;
specifically, move "import type { FileRoutesByPath, MakeRouteMatch } from
'@tanstack/react-router'" to below "import { routeTree } from './routeTree.gen'"
(keeping "import type { FileRouteTypes } from './routeTree.gen'" where
appropriate) so ESLint's import ordering rule is satisfied while preserving the
existing references to FileRoutesByPath, MakeRouteMatch, FileRouteTypes,
expectTypeOf, and test.
🧹 Nitpick comments (1)
packages/router-generator/tests/generator/nested-verboseFileRoutes-false/tests.test-d.ts (1)

13-16: Import order: move type import after value imports.

ESLint flags that the type import from @tanstack/react-router should occur after the import from ./routeTree.gen.

♻️ Proposed fix
 import {
   Link,
   createRouter,
   redirect,
   useLoaderData,
   useLoaderDeps,
   useMatch,
   useNavigate,
   useParams,
   useRouteContext,
   useSearch,
 } from '@tanstack/react-router'
-import type { FileRoutesByPath, MakeRouteMatch } from '@tanstack/react-router'
 import { expectTypeOf, test } from 'vitest'
 import { routeTree } from './routeTree.gen'
 import type { FileRouteTypes } from './routeTree.gen'
+import type { FileRoutesByPath, MakeRouteMatch } from '@tanstack/react-router'

Comment on lines +1 to +4
import { Outlet } from '@tanstack/react-router'
export const Route = createFileRoute({
component: () => <Outlet />,
})
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 | 🔴 Critical

Missing createFileRoute import.

The file uses createFileRoute on line 2 but only imports Outlet from @tanstack/react-router. This will cause a runtime error.

🐛 Proposed fix
-import { Outlet } from '@tanstack/react-router'
+import { createFileRoute, Outlet } from '@tanstack/react-router'
 export const Route = createFileRoute({
   component: () => <Outlet />,
 })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { Outlet } from '@tanstack/react-router'
export const Route = createFileRoute({
component: () => <Outlet />,
})
import { createFileRoute, Outlet } from '@tanstack/react-router'
export const Route = createFileRoute({
component: () => <Outlet />,
})
🤖 Prompt for AI Agents
In
`@packages/router-generator/tests/generator/nested-verboseFileRoutes-false/routes/_pathlessLayout.tsx`
around lines 1 - 4, The file defines Route using createFileRoute but never
imports it; add the missing import for createFileRoute from
'@tanstack/react-router' alongside the existing Outlet import so the
createFileRoute symbol is available when constructing the Route component
(ensure the import statement includes createFileRoute and retains Outlet to
avoid the runtime error in the Route definition).

Comment on lines +13 to +16
import type { FileRoutesByPath, MakeRouteMatch } from '@tanstack/react-router'
import { expectTypeOf, test } from 'vitest'
import { routeTree } from './routeTree.gen'
import type { MakeRouteMatch } from '@tanstack/react-router'
import type { FileRouteTypes } from './routeTree.gen'
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

Fix import ordering flagged by ESLint.

The static analysis tool indicates the type import from @tanstack/react-router should occur after the import of ./routeTree.gen.

Proposed fix
-import type { FileRoutesByPath, MakeRouteMatch } from '@tanstack/react-router'
 import { expectTypeOf, test } from 'vitest'
 import { routeTree } from './routeTree.gen'
 import type { FileRouteTypes } from './routeTree.gen'
+import type { FileRoutesByPath, MakeRouteMatch } from '@tanstack/react-router'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import type { FileRoutesByPath, MakeRouteMatch } from '@tanstack/react-router'
import { expectTypeOf, test } from 'vitest'
import { routeTree } from './routeTree.gen'
import type { MakeRouteMatch } from '@tanstack/react-router'
import type { FileRouteTypes } from './routeTree.gen'
import { expectTypeOf, test } from 'vitest'
import { routeTree } from './routeTree.gen'
import type { FileRouteTypes } from './routeTree.gen'
import type { FileRoutesByPath, MakeRouteMatch } from '@tanstack/react-router'
🧰 Tools
🪛 ESLint

[error] 13-13: @tanstack/react-router type import should occur after import of ./routeTree.gen

(import/order)

🤖 Prompt for AI Agents
In
`@packages/router-generator/tests/generator/nested-verboseFileRoutes-true/tests.test-d.ts`
around lines 13 - 16, Reorder the imports in tests.test-d.ts so the type-only
import from '@tanstack/react-router' comes after the generated module import;
specifically, move "import type { FileRoutesByPath, MakeRouteMatch } from
'@tanstack/react-router'" to below "import { routeTree } from './routeTree.gen'"
(keeping "import type { FileRouteTypes } from './routeTree.gen'" where
appropriate) so ESLint's import ordering rule is satisfied while preserving the
existing references to FileRoutesByPath, MakeRouteMatch, FileRouteTypes,
expectTypeOf, and test.

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

🤖 Fix all issues with AI agents
In
`@packages/router-generator/tests/generator/nested-verboseFileRoutes-false/tests.test-d.ts`:
- Around line 13-16: The import ordering violates the import/order rule; reorder
imports so the local module import "routeTree" and its type "FileRouteTypes"
(from './routeTree.gen') come before external library imports, and ensure
type-only imports use "import type" for FileRouteTypes, FileRoutesByPath, and
MakeRouteMatch; specifically move the line importing FileRouteTypes to directly
after "import { routeTree } from './routeTree.gen'" and place the external
imports (e.g., from '@tanstack/react-router' and 'vitest') after the local
imports to satisfy linting.
♻️ Duplicate comments (1)
packages/router-generator/tests/generator/nested-verboseFileRoutes-true/tests.test-d.ts (1)

13-16: Fix import ordering flagged by ESLint.

The static analysis tool indicates the type import from @tanstack/react-router should occur after the import of ./routeTree.gen.

Proposed fix
-import type { FileRoutesByPath, MakeRouteMatch } from '@tanstack/react-router'
 import { expectTypeOf, test } from 'vitest'
 import { routeTree } from './routeTree.gen'
 import type { FileRouteTypes } from './routeTree.gen'
+import type { FileRoutesByPath, MakeRouteMatch } from '@tanstack/react-router'

Comment on lines +13 to +16
import type { FileRoutesByPath, MakeRouteMatch } from '@tanstack/react-router'
import { expectTypeOf, test } from 'vitest'
import { routeTree } from './routeTree.gen'
import type { MakeRouteMatch } from '@tanstack/react-router'
import type { FileRouteTypes } from './routeTree.gen'
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

Fix import ordering to satisfy import/order.
Static analysis reports a lint error; move the type-only import after the local routeTree.gen import.

Proposed fix
-import type { FileRoutesByPath, MakeRouteMatch } from '@tanstack/react-router'
 import { expectTypeOf, test } from 'vitest'
 import { routeTree } from './routeTree.gen'
 import type { FileRouteTypes } from './routeTree.gen'
+import type { FileRoutesByPath, MakeRouteMatch } from '@tanstack/react-router'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import type { FileRoutesByPath, MakeRouteMatch } from '@tanstack/react-router'
import { expectTypeOf, test } from 'vitest'
import { routeTree } from './routeTree.gen'
import type { MakeRouteMatch } from '@tanstack/react-router'
import type { FileRouteTypes } from './routeTree.gen'
import { expectTypeOf, test } from 'vitest'
import { routeTree } from './routeTree.gen'
import type { FileRouteTypes } from './routeTree.gen'
import type { FileRoutesByPath, MakeRouteMatch } from '@tanstack/react-router'
🧰 Tools
🪛 ESLint

[error] 13-13: @tanstack/react-router type import should occur after import of ./routeTree.gen

(import/order)

🤖 Prompt for AI Agents
In
`@packages/router-generator/tests/generator/nested-verboseFileRoutes-false/tests.test-d.ts`
around lines 13 - 16, The import ordering violates the import/order rule;
reorder imports so the local module import "routeTree" and its type
"FileRouteTypes" (from './routeTree.gen') come before external library imports,
and ensure type-only imports use "import type" for FileRouteTypes,
FileRoutesByPath, and MakeRouteMatch; specifically move the line importing
FileRouteTypes to directly after "import { routeTree } from './routeTree.gen'"
and place the external imports (e.g., from '@tanstack/react-router' and
'vitest') after the local imports to satisfy linting.

@schiller-manuel schiller-manuel merged commit b42f84a into main Jan 17, 2026
5 of 6 checks passed
@schiller-manuel schiller-manuel deleted the fix-fullpath branch January 17, 2026 16:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

3 participants