-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
Which project does this relate to?
Router
Describe the bug
When using virtual routes configuration (routes.config.ts), TanStack Router automatically nests routes based on path matching, even when they are explicitly configured as siblings within the same layout. Current Behavior: Routes like /posts and /posts/$id are automatically nested (detail route becomes child of list route) based on path prefix matching, despite being explicitly defined as siblings in the virtual routes config:
// routes.config.ts
layout('_main', 'domains/main/layout.tsx', [
route('/posts', 'domains/main/features/posts/pages/PostsPage.tsx'),
route('/posts/$id', 'domains/main/features/posts/pages/PostDetailPage.tsx'), // Should be sibling, not child
])
Generated Route Tree:
// routeTree.gen.ts
const domainsMainFeaturesPostsPagesPostDetailPageRoute =
domainsMainFeaturesPostsPagesPostDetailPageRouteImport.update({
id: '/$id',
path: '/$id',
getParentRoute: () => domainsMainFeaturesPostsPagesPostsPageRoute, // ❌ Nested under /posts
} as any)
Expected Behavior: Routes should respect the explicit parent-child relationships defined in the virtual routes config. When two routes are siblings in the config array, they should remain siblings in the generated route tree, regardless of path matching:
// Expected generated code
const domainsMainFeaturesPostsPagesPostDetailPageRoute =
domainsMainFeaturesPostsPagesPostDetailPageRouteImport.update({
id: '/posts/$id',
path: '/posts/$id',
getParentRoute: () => domainsMainLayoutRoute, // ✅ Sibling under layout
} as any)
Use Case: A common pattern is having a layout that wraps multiple related pages:
/posts - List view with table/grid
/posts/$id - Detail view with form/content
/posts/user/$userId - Filtered list by user
Environment:
@tanstack/react-router: ^1.135.2
@tanstack/router-plugin: ^1.135.2
Suggested Fix:
The route generator should track which routes were explicitly provided as children in the virtual config and skip path-based parent inference for those routes. The explicit parent from the config should always take precedence over path-based matching.
Your Example Website or App
no need
Steps to Reproduce the Bug or Issue
export const routes = rootRoute('root.tsx', [
layout('_main', 'domains/main/layout.tsx', [
route('/todos', '...'),
route('/todos/$id', '...'),
]),
])
Expected behavior
The route generator should track which routes were explicitly provided as children in the virtual config and skip path-based parent inference for those routes. The explicit parent from the config should always take precedence over path-based matching.
Screenshots or Videos
No response
Platform
Environment:
@tanstack/react-router: ^1.135.2
@tanstack/router-plugin: ^1.135.2
Additional context
No response