Skip to content

Conversation

@schiller-manuel
Copy link
Contributor

@schiller-manuel schiller-manuel commented Dec 17, 2025

fixes #3843

Summary by CodeRabbit

  • New Features

    • Added a new /pathless-layout subtree with layout, index and child routes and a new navigation link.
  • Improvements

    • Flattened and reorganized several route groups and nested layouts to simplify parent-child relationships.
    • Optimized route lookup and path resolution for more consistent routing behavior.
  • Breaking / Public API Changes

    • Several public route identifiers and exported route entries were renamed, removed, or consolidated.
  • Tests

    • Added end-to-end tests covering the new pathless layout and navigation scenarios.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 17, 2025

Walkthrough

This PR changes router generation to add a path→RouteNode map (routeNodesByPath), simplify parent/anchor resolution, make route-piece keys dynamic, and adjust pathless-layout handling so pathless layouts with a cleaned path resolve to a real ancestor; numerous generated snapshots and e2e routes updated accordingly.

Changes

Cohort / File(s) Summary
Core generator logic
packages/router-generator/src/generator.ts
Add routeNodesByPath: Map<string, RouteNode> to accumulator; populate it when processing nodes; replace multi-step virtual-parent resolution with hasParentRoute-based logic; switch anchor lookups to map lookups; use dynamic pieceKey from _fsRouteType; special-case pathless_layout with cleaned paths to resolve real ancestors.
Types
packages/router-generator/src/types.ts
Remove isVirtualParentRequired from RouteNode; add routeNodesByPath: Map<string, RouteNode> to HandleNodeAccumulator public type.
Utilities
packages/router-generator/src/utils.ts
Simplify findParent to always return ${node.parent.variableName}Route when a parent exists (remove isVirtualParentRequired branching).
Generator tests / snapshots (nested-layouts)
packages/router-generator/tests/generator/nested-layouts/...routeTree*.snapshot.ts
Update generated route exports and maps: remove intermediate FooRoute/NestedRoute constructs, introduce FooLayoutB5RouteRoute, FooBarRoute, NestedLayoutB1Route, NestedLayoutB2Route, and reparent many routes to rootRouteImport; adjust FileRoutesBy* maps.
Generator tests / snapshots (no-duplicate-route-segment)
packages/router-generator/tests/generator/no-duplicate-route-segment/...routeTree*.snapshot.ts
Replace intermediate FooRoute with FooLayoutRouteRoute as /foo representation (id /foo/_layout), remove /foo from public ID/path unions, update RootRouteChildren and related type augmentations.
Generator tests / snapshots (route-groups)
packages/router-generator/tests/generator/route-groups/...routeTree*.snapshot.ts
Remove top-level /(foo)/asdf grouping; promote its contained routes to RootRouteChildren, reparent to rootRouteImport, and update FileRoutesBy* mappings and IDs/paths accordingly.
E2E: add pathless-layout subtree
e2e/react-router/basic-file-based/src/routeTree.gen.ts, e2e/react-router/basic-file-based/src/routes/pathless-layout/**, e2e/react-router/basic-file-based/tests/app.spec.ts, e2e/.../__root.tsx
Add /pathless-layout route subtree (pathless layout, layout index, child, components, test updates and root Link), update generated routeTree and public typings to expose new PathlessLayout routes.
E2E: remove TransitionCountQuery route
e2e/react-router/basic-react-query-file-based/src/routeTree.gen.ts
Remove TransitionCountQueryRoute import and entries from route tree and public type maps.
E2E: consolidate FooBarQux route naming
e2e/react-start/basic/src/routeTree.gen.ts
Replace FooBarQuxRoute with FooBarQuxHereRoute as the authoritative route for /foo/$bar/$qux, update parents, mappings, and public typings.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Areas needing attention:
    • packages/router-generator/src/generator.ts — pathless-layout detection, ancestor resolution, and use of routeNodesByPath.
    • packages/router-generator/src/types.ts — public type change to HandleNodeAccumulator.
    • Snapshot diffs across multiple test suites to ensure consistent reparenting and ID/path updates.

Possibly related PRs

Suggested reviewers

  • SeanCassiere

Poem

🐰
I hopped through maps of route and path,
Found where layout logic felt the wrath.
I planted keys by type and name,
Now pathless layouts find their frame.
Root now greets each child with cheer — hooray!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Out of Scope Changes check ❓ Inconclusive While most changes align with fixing pathless layout handling, significant test fixture updates (routeTree snapshots) appear to reflect broader refactoring beyond the stated scope of preventing virtual routes for pathless layouts. Clarify whether the extensive routeTree snapshot changes are necessary consequences of the pathless layout fix or represent separate refactoring that should be decoupled.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'fix: don't create virtual routes for pathless layouts' directly addresses the core issue—preventing virtual route creation for pathless layout files, which is the primary objective of the pull request.
Linked Issues check ✅ Passed The PR successfully addresses issue #3843 by preventing virtual routes from being created for pathless layout files, which prevents the empty HTML page rendering at folder paths like /app.
✨ 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 fix-3843

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

@nx-cloud
Copy link

nx-cloud bot commented Dec 17, 2025

View your CI Pipeline Execution ↗ for commit 8d9efba

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

☁️ Nx Cloud last updated this comment at 2025-12-17 02:12:48 UTC

@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 17, 2025

More templates

@tanstack/arktype-adapter

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

@tanstack/directive-functions-plugin

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

@tanstack/eslint-plugin-router

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

@tanstack/history

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

@tanstack/nitro-v2-vite-plugin

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

@tanstack/react-router

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

@tanstack/react-router-devtools

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

@tanstack/react-router-ssr-query

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

@tanstack/react-start

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

@tanstack/react-start-client

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

@tanstack/react-start-server

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

@tanstack/router-cli

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

@tanstack/router-core

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

@tanstack/router-devtools

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

@tanstack/router-devtools-core

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

@tanstack/router-generator

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

@tanstack/router-plugin

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

@tanstack/router-ssr-query-core

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

@tanstack/router-utils

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

@tanstack/router-vite-plugin

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

@tanstack/server-functions-plugin

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

@tanstack/solid-router

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

@tanstack/solid-router-devtools

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

@tanstack/solid-router-ssr-query

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

@tanstack/solid-start

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

@tanstack/solid-start-client

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

@tanstack/solid-start-server

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

@tanstack/start-client-core

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

@tanstack/start-plugin-core

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

@tanstack/start-server-core

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

@tanstack/start-static-server-functions

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

@tanstack/start-storage-context

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

@tanstack/valibot-adapter

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

@tanstack/virtual-file-routes

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

@tanstack/vue-router

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

@tanstack/vue-router-devtools

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

@tanstack/vue-router-ssr-query

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

@tanstack/vue-start

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

@tanstack/vue-start-client

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

@tanstack/vue-start-server

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

@tanstack/zod-adapter

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

commit: 8d9efba

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

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1cab73e and 8d9efba.

📒 Files selected for processing (10)
  • e2e/react-router/basic-file-based/src/routeTree.gen.ts (32 hunks)
  • e2e/react-router/basic-file-based/src/routes/__root.tsx (1 hunks)
  • e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/child.tsx (1 hunks)
  • e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/index.tsx (1 hunks)
  • e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/route.tsx (1 hunks)
  • e2e/react-router/basic-file-based/src/routes/pathless-layout/route.tsx (1 hunks)
  • e2e/react-router/basic-file-based/tests/app.spec.ts (1 hunks)
  • e2e/react-router/basic-react-query-file-based/src/routeTree.gen.ts (1 hunks)
  • e2e/react-start/basic/src/routeTree.gen.ts (6 hunks)
  • packages/router-generator/src/generator.ts (5 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/basic-file-based/src/routes/pathless-layout/_layout/route.tsx
  • e2e/react-router/basic-file-based/src/routes/pathless-layout/route.tsx
  • e2e/react-router/basic-react-query-file-based/src/routeTree.gen.ts
  • packages/router-generator/src/generator.ts
  • e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/child.tsx
  • e2e/react-router/basic-file-based/src/routes/__root.tsx
  • e2e/react-router/basic-file-based/src/routeTree.gen.ts
  • e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/index.tsx
  • e2e/react-router/basic-file-based/tests/app.spec.ts
  • e2e/react-start/basic/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/pathless-layout/_layout/route.tsx
  • e2e/react-router/basic-file-based/src/routes/pathless-layout/route.tsx
  • e2e/react-router/basic-react-query-file-based/src/routeTree.gen.ts
  • packages/router-generator/src/generator.ts
  • e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/child.tsx
  • e2e/react-router/basic-file-based/src/routes/__root.tsx
  • e2e/react-router/basic-file-based/src/routeTree.gen.ts
  • e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/index.tsx
  • e2e/react-router/basic-file-based/tests/app.spec.ts
  • e2e/react-start/basic/src/routeTree.gen.ts
🧠 Learnings (11)
📓 Common learnings
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.
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.
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.
📚 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-router/basic-file-based/src/routes/pathless-layout/_layout/route.tsx
  • e2e/react-router/basic-file-based/src/routes/pathless-layout/route.tsx
  • e2e/react-router/basic-react-query-file-based/src/routeTree.gen.ts
  • packages/router-generator/src/generator.ts
  • e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/child.tsx
  • e2e/react-router/basic-file-based/src/routeTree.gen.ts
  • e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/index.tsx
  • e2e/react-router/basic-file-based/tests/app.spec.ts
  • e2e/react-start/basic/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/basic-file-based/src/routes/pathless-layout/route.tsx
  • e2e/react-router/basic-react-query-file-based/src/routeTree.gen.ts
  • e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/child.tsx
  • e2e/react-router/basic-file-based/src/routeTree.gen.ts
  • e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/index.tsx
  • e2e/react-start/basic/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/basic-file-based/src/routes/pathless-layout/route.tsx
  • e2e/react-router/basic-react-query-file-based/src/routeTree.gen.ts
  • e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/child.tsx
  • e2e/react-router/basic-file-based/src/routeTree.gen.ts
  • e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/index.tsx
  • e2e/react-router/basic-file-based/tests/app.spec.ts
  • e2e/react-start/basic/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/basic-file-based/src/routes/pathless-layout/route.tsx
  • e2e/react-router/basic-react-query-file-based/src/routeTree.gen.ts
  • e2e/react-router/basic-file-based/src/routeTree.gen.ts
  • e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/index.tsx
  • e2e/react-start/basic/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
  • e2e/react-start/basic/src/routeTree.gen.ts
📚 Learning: 2025-10-14T18:59:33.990Z
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.

Applied to files:

  • 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: Implement type-safe routing with search params and path params

Applied to files:

  • e2e/react-router/basic-file-based/src/routeTree.gen.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-router/basic-file-based/tests/app.spec.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:

  • e2e/react-start/basic/src/routeTree.gen.ts
📚 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-start/basic/src/routeTree.gen.ts
🧬 Code graph analysis (6)
e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/route.tsx (4)
e2e/react-router/basic-file-based/src/routes/__root.tsx (1)
  • Route (12-22)
e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/child.tsx (1)
  • Route (3-7)
e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/index.tsx (1)
  • Route (3-7)
e2e/react-router/basic-file-based/src/routes/pathless-layout/route.tsx (1)
  • Route (3-15)
e2e/react-router/basic-file-based/src/routes/pathless-layout/route.tsx (4)
e2e/react-router/basic-file-based/src/routes/__root.tsx (1)
  • Route (12-22)
e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/child.tsx (1)
  • Route (3-7)
e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/index.tsx (1)
  • Route (3-7)
e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/route.tsx (1)
  • Route (3-15)
packages/router-generator/src/generator.ts (1)
packages/router-generator/src/utils.ts (5)
  • hasParentRoute (364-444)
  • removeLastSegmentFromPath (358-362)
  • removeGroups (320-322)
  • removeUnderscores (192-194)
  • removeLayoutSegments (332-336)
e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/child.tsx (4)
e2e/react-router/basic-file-based/src/routes/__root.tsx (1)
  • Route (12-22)
e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/index.tsx (1)
  • Route (3-7)
e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/route.tsx (1)
  • Route (3-15)
e2e/react-router/basic-file-based/src/routes/pathless-layout/route.tsx (1)
  • Route (3-15)
e2e/react-router/basic-file-based/src/routes/__root.tsx (1)
packages/react-router/src/link.tsx (1)
  • Link (569-600)
e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/index.tsx (4)
e2e/react-router/basic-file-based/src/routes/__root.tsx (1)
  • Route (12-22)
e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/child.tsx (1)
  • Route (3-7)
e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/route.tsx (1)
  • Route (3-15)
e2e/react-router/basic-file-based/src/routes/pathless-layout/route.tsx (1)
  • Route (3-15)
⏰ 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 (14)
e2e/react-router/basic-react-query-file-based/src/routeTree.gen.ts (1)

1-220: Skipping review of autogenerated file.

This routeTree.gen.ts file is automatically generated by TanStack Router and should not be manually modified. The file header confirms this with directives like @ts-nocheck and eslint-disable. Based on learnings, autogenerated route tree files in this repository are excluded from review.

e2e/react-start/basic/src/routeTree.gen.ts (1)

1-999: Skipping review of autogenerated file.

This file is automatically generated by TanStack Router and should not be manually modified. The changes reflect the fix for pathless layout routes (issue #3843) being correctly applied by the router generator.

Based on learnings, routeTree.gen.ts files in TanStack Router repositories are excluded from review.

e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/index.tsx (1)

1-7: LGTM!

The index route is correctly defined under the pathless layout with proper test ID for e2e validation.

e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/route.tsx (1)

1-15: LGTM!

The pathless layout route is well-structured with proper navigation, Outlet for nested content, and test IDs for e2e validation.

e2e/react-router/basic-file-based/src/routes/__root.tsx (1)

158-167: LGTM!

The new navigation link follows the established pattern and includes proper test ID for e2e validation.

e2e/react-router/basic-file-based/tests/app.spec.ts (1)

329-395: Comprehensive test coverage for the pathless layout fix.

The tests effectively validate the core scenarios for issue #3843:

  • Direct and client-side navigation render layout sections correctly.
  • Layout preservation during child navigation.
  • Not-found behavior for non-existent routes under the pathless layout (the key fix).
e2e/react-router/basic-file-based/src/routes/pathless-layout/_layout/child.tsx (1)

1-7: LGTM!

The child route is correctly nested under the pathless layout with proper test ID.

e2e/react-router/basic-file-based/src/routes/pathless-layout/route.tsx (1)

1-15: Well-structured parent route with proper not-found handling.

The notFoundComponent is essential for the fix - it ensures non-existent routes under /pathless-layout display the not-found message instead of empty HTML, directly addressing issue #3843.

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

1-10: Skipping review of autogenerated file.

This file is automatically generated by TanStack Router and should not be manually modified. Based on learnings.

packages/router-generator/src/generator.ts (5)

411-411: LGTM: Performance improvement.

Adding routeNodesByPath Map improves route node lookups from O(n) to O(1).


411-417: LGTM: Improved flexibility and performance.

The dynamic pieceKey approach and Map-based anchorRoute lookup are solid improvements. The type assertion on line 414 assumes node._fsRouteType matches the expected key type for route pieces.


1461-1472: LGTM: Correct map population logic.

The guard !node.isVirtual on line 1470 correctly prevents virtual routes from being added to routeNodesByPath, ensuring only real route nodes are available for path-based lookups.


357-364: LGTM: Simplified parent resolution.

Delegating parent route resolution to the hasParentRoute utility simplifies the code and centralizes the parent-finding logic, which handles various edge cases including non-nested routes and nesting exclusions.


434-459: The special handling for pathless layouts with a cleanedPath introduces unusual path assignments that require verification:

  1. Line 450: node.path = node.routePath assigns the raw route path with underscores. Verify whether pathless layouts should use the unprocessed route path for identification.

  2. Lines 451-453: node.cleanedPath is computed from immediateParentPath rather than the node's own path, potentially causing pathless layouts to inherit their parent's cleaned path instead of having their own. Confirm this is correct for pathless layout routing semantics.

  3. Line 448: candidate.path !== '/' prevents root routes from being selected as parents. Verify whether top-level pathless layouts should be able to use root as their parent.

Comment on lines +654 to +657
!node.isNonPath ||
(node._fsRouteType === 'pathless_layout' && node.cleanedPath)
? `path: '${node.cleanedPath}'`
: undefined,
Copy link
Contributor

@coderabbitai coderabbitai bot Dec 17, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cd /tmp && git clone https://github.com/TanStack/router.git --depth 1 2>/dev/null && cd router && find . -name "generator.ts" -path "*/router-generator/*"

Repository: TanStack/router

Length of output: 103


🏁 Script executed:

find . -name "generator.ts" 2>/dev/null | head -20

Repository: TanStack/router

Length of output: 103


🏁 Script executed:

cat packages/router-generator/src/generator.ts | sed -n '440,470p; 640,670p'

Repository: TanStack/router

Length of output: 2251


Remove pathless layouts from path property generation.

The condition at lines 654-657 incorrectly includes path: '${node.cleanedPath}' for pathless_layout routes. This causes pathless layouts to be treated as routes with a path property, resulting in empty HTML pages instead of proper 404 responses (Issue #3843).

The current logic:

!node.isNonPath || (node._fsRouteType === 'pathless_layout' && node.cleanedPath)
  ? `path: '${node.cleanedPath}'`
  : undefined,

should exclude pathless layouts entirely, ensuring they never receive a path property. Pathless layout routes do not require a matching path in the URL by design.

🤖 Prompt for AI Agents
packages/router-generator/src/generator.ts around lines 654 to 657: the current
ternary erroneously assigns a path for pathless_layout nodes; change the
condition so the path string is only generated for nodes that are not non-path
and are NOT pathless_layouts (i.e., require both that node.isNonPath is false
and node._fsRouteType !== 'pathless_layout'); update the ternary accordingly so
pathless_layout routes are excluded and never receive a path property.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

wrong, they need to get the path here so that child routes, the ones that are matched atruntime, have the correct and full path by inheriting its parent path

Copy link
Contributor

Choose a reason for hiding this comment

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

@schiller-manuel, thank you for the clarification! You're absolutely right—pathless layouts need the path property so their child routes can inherit and construct the correct full path at runtime. I appreciate you explaining the inheritance mechanism.


✏️ Learnings added
Learnt from: schiller-manuel
Repo: TanStack/router PR: 6120
File: packages/router-generator/src/generator.ts:654-657
Timestamp: 2025-12-17T02:17:47.423Z
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.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
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.

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

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

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.

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.

Pathless Layout Route Renders Empty HTML

2 participants