-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
Which project does this relate to?
Router
Describe the bug
tldr: When mixing virtual routing and file based routing using the physical virtual route type, the root of the mounted folder cannot have both an index.tsx and a route.tsx. This setup is supported in file-based routing, and is useful for adding layout or context to all child routes.
I'm working on a project with many mostly independent features, each of with has its own set of routes. In my repository, I'd like to have the routes for each feature isolated into the subfolder scoped to to that feature. For example:
/src
├── app/
│ └── routes/ # global routes not related to a feature
└── features
├── feature-a
│ └── routes/ # routes for feature-a
└── feature-b
└── routes/ # routes for feature-b
Virtual file routes seem like a great fit for this:
export default rootRoute('app/routes/root.tsx', [
// ... global routes
physical('feature-a', 'features/feature-a/routes'),
physical('feature-b', 'features/feature-b/routes'),
]);However, when i do this, i can no longer have both a route.tsx and an index.tsx in the feature/*/routes folders. When I do, i get an error like:
Error: Conflicting configuration paths were found for the following routes: "feature", "feature".
Please ensure each Route has a unique full path.
Conflicting files:
/home/projects/tanstack-router-xuwk6tn2/src/routes/feature/index.tsx
/home/projects/tanstack-router-xuwk6tn2/src/routes/feature/route.tsx
This feels broken, when the exact same folder structure works with file based routing.
As a workaround, I can use a pathless route instead of a route.tsx. ie, _layout.tsx and _layout.index.tsx. But this feels like extra verbosity that shouldn't be needed. Adding a shared layout, loader, or context to all children seems like it should be easier.
Your Example Website or App
https://stackblitz.com/edit/tanstack-router-xuwk6tn2?file=src%2Froutes.ts
Steps to Reproduce the Bug or Issue
The attached stackblitz can be swapped between virtual file routes and file based routing by commenting out the virtualRouteConfig option in vite.config.js, and then restarting vite. Vite will automatically scroll the terminal past the router plugin errors, so it will look successful, but if you scroll up yo can see the conflicting path error.
In src/routes.ts, you can swap between mounting the feature folder using physical() and mounting the feature routes directly using route() and feature().
Note that when disabling file based routing, routeTree.gen.ts is identical (ignoring casing) to the generated version when using route()/index(). Also note that when using physical() and getting the error, routeTree.gen.ts is not actually updated, so the app still works (confusing).
Expected behavior
When mounting a directory into a virtual route tree using physical('path', 'folder'), and folder contains both an index.tsx and a route.tsx, the route tree should still generate correctly, with the route.tsx being treated as the parent route for index.tsx, and all other routes in the folder.
Screenshots or Videos
No response
Platform
- @tanstack/react-router: 1.132.47
- @tanstack/router-plugin: 1.132.51
- @tanstack/virtual-file-routes: 1.131.2
- OS: OSX 15.5 ARM
- Browser: Chrome
- Browser Version: 140.0.7339.209 ARM
- Bundler: Vite
- Bundler Version: 7.1.7
Additional context
No response