react-router-fs-routes
v0.3.0
Published
A vite plugin for react router to generate routes from filesystem structure.
Maintainers
Readme
React Router FS Routes Plugin
A Vite plugin that automatically generates React Router v7 route configurations based on your filesystem structure, with TypeScript support, error handling, and performance optimizations.
Features
- 🚀 Automatic Route Generation: Creates React Router v7 configurations from your file structure
- 📁 File-based Routing: Supports pages, layouts, and nested routes
- 🔄 Hot Reload: Automatically regenerates routes during development
- 🎯 TypeScript Support: Full TypeScript integration with proper types
- 🛡️ Error Handling: Comprehensive error reporting and recovery
- ⚡ Performance: Debounced file watching and caching for optimal performance
- 🔧 Configurable: Customizable naming conventions and output paths
Installation
npm install --save-dev react-router-fs-routes
# or
yarn add -D react-router-fs-routes
# or
pnpm add -D react-router-fs-routesBasic Setup
1. Configure Vite Plugin
// vite.config.ts
import { defineConfig } from 'vite';
import { reactRouterFsRoutes } from 'react-router-fs-routes';
export default defineConfig({
plugins: [
reactRouterFsRoutes({
routesDir: 'src/pages',
outputPath: 'src/lib/app-routes.tsx'
})
]
});2. Create Route Files
Create your page structure in the routes directory:
src/pages/
├── page.tsx # / route
├── about/
│ └── page.tsx # /about route
├── blog/
│ ├── layout.tsx # /blog layout
│ ├── page.tsx # /blog route (index)
│ └── [id]/
│ └── page.tsx # /blog/:id route
└── (admin)/ # Route group (no URL segment)
├── layout.tsx # Admin layout
├── users/
│ └── page.tsx # /users route
└── settings/
└── page.tsx # /settings route3. Use Generated Routes
// src/main.tsx
import { createBrowserRouter, RouterProvider } from 'react-router';
import { routes } from './lib/app-routes';
const router = createBrowserRouter(routes);
function App() {
return <RouterProvider router={router} />;
}
export default App;Configuration Options
interface ReactRouterFsRoutesOptions {
/** Root directory for route files (default: "src/pages") */
routesDir?: string;
/** Filename for page components (default: "page") */
pageFilename?: string;
/** Filename for layout components (default: "layout") */
layoutFilename?: string;
/** Output path for generated routes configuration (default: "src/lib/app-routes.tsx") */
outputPath?: string;
/** Enable debug logging (default: false) */
debug?: boolean;
}Example Configurations
Custom File Names
reactRouterFsRoutes({
routesDir: 'app/routes',
pageFilename: 'component', // component.tsx instead of page.tsx
layoutFilename: 'wrapper', // wrapper.tsx instead of layout.tsx
outputPath: 'app/generated/routes.tsx'
})Debug Mode
reactRouterFsRoutes({
debug: true // Enables detailed logging
})File Naming Conventions
Pages
- File:
page.tsx(or custom viapageFilename) - Purpose: Defines a route that renders content
- Example:
src/pages/about/page.tsx→/about
Layouts
- File:
layout.tsx(or custom vialayoutFilename) - Purpose: Wraps child routes with shared UI
- Example:
src/pages/dashboard/layout.tsx→ Layout for/dashboard/*
Dynamic Routes
- Syntax:
[param]folder name - Example:
src/pages/blog/[id]/page.tsx→/blog/:id - Access: Use
useParams()to access theidparameter
Optional Routes
- Syntax:
[param?]folder name - Example:
src/pages/blog/[slug?]/page.tsx→/blogand/blog/:slug
Route Groups
- Syntax:
(group)folder name - Purpose: Organize routes without affecting URL structure
- Example:
src/pages/(admin)/users/page.tsx→/users(not/admin/users)
Catch-all Routes
- File:
$.tsxor similar pattern - Purpose: Handle unmatched routes (404 pages)
Generated Route Structure
The plugin generates a TypeScript file with properly typed route configurations:
// Generated: src/lib/app-routes.tsx
import type { RouteObject } from 'react-router';
import RootPage from '../pages/page';
import AboutPage from '../pages/about/page';
import BlogLayout from '../pages/blog/layout';
import BlogPage from '../pages/blog/page';
import BlogDetailsPage from '../pages/blog/[id]/page';
export const routes: RouteObject[] = [
{
path: "/",
Component: RootPage,
},
{
path: "about",
Component: AboutPage,
},
{
path: "blog",
Component: BlogLayout,
children: [
{
index: true,
Component: BlogPage,
},
{
path: ":id",
Component: BlogDetailsPage,
},
],
},
];
export default routes;Component Templates
When you create empty route files, the plugin automatically generates starter templates:
Page Template
// Auto-generated page.tsx
export default function PageName() {
return (
<div>
<h1>PageName</h1>
<p>This page was auto-generated by react-router-fs-routes.</p>
</div>
);
}Layout Template
// Auto-generated layout.tsx
import { Outlet } from 'react-router';
export default function LayoutName() {
return (
<div>
<header>
<h1>LayoutName</h1>
</header>
<main>
<Outlet />
</main>
</div>
);
}Advanced Usage
Nested Layouts
Create complex nested layouts by organizing your files:
src/pages/
├── (marketing)/
│ ├── layout.tsx # Marketing layout
│ ├── page.tsx # /
│ └── about/
│ └── page.tsx # /about
└── (app)/
├── layout.tsx # App layout
├── dashboard/
│ ├── layout.tsx # Dashboard layout
│ ├── page.tsx # /dashboard
│ └── settings/
│ └── page.tsx # /dashboard/settings
└── profile/
└── page.tsx # /profileThis creates:
/and/aboutwith marketing layout/dashboardand/dashboard/settingswith app + dashboard layouts/profilewith app layout only
Route Groups for Organization
Use route groups to organize related routes:
src/pages/
├── (auth)/
│ ├── login/
│ │ └── page.tsx # /login
│ └── register/
│ └── page.tsx # /register
├── (admin)/
│ ├── layout.tsx # Admin layout for all admin routes
│ ├── users/
│ │ └── page.tsx # /users
│ └── settings/
│ └── page.tsx # /settings
└── page.tsx # /Performance Features
Debounced File Watching
- File changes are batched and processed together
- Prevents excessive regeneration during rapid file changes
- Configurable delay (default: 100ms)
Caching
- Route nodes are cached to prevent unnecessary processing
- File hashes track content changes
- Only regenerates when actual content changes
Error Recovery
- Comprehensive error handling with detailed messages
- Graceful degradation when files are temporarily unavailable
- Debug mode for detailed troubleshooting
Error Handling
The plugin includes robust error handling:
// Custom error types with context
class RouteGenerationError extends Error {
constructor(message: string, filePath?: string, cause?: Error);
}
// Safe file operations
function safeFileOperation<T>(
operation: () => T,
errorMessage: string,
filePath?: string
): T;Enable debug mode to see detailed error information:
reactRouterFsRoutes({
debug: true // Shows detailed error messages and file paths
})Migration from Other Routing Solutions
From React Router with manual routes
- Install the plugin and configure it
- Move your components to the file-based structure
- Replace your route configuration with the generated routes
- Update imports to use the generated route file
From Next.js App Router
The file structure is similar to Next.js App Router:
| Next.js | React Router FS Routes |
|---------|------------------------|
| page.tsx | page.tsx |
| layout.tsx | layout.tsx |
| [param] | [param] |
| (group) | (group) |
Main differences:
- Use
<Outlet />instead ofchildrenprop in layouts - Route files export default component instead of named exports
- No automatic error boundaries (add manually if needed)
Troubleshooting
Common Issues
Routes not generating
- Check that
routesDirpath is correct - Ensure files have
.tsxor.jsxextensions - Verify file names match
pageFilenameandlayoutFilenameoptions
Import errors in generated routes
- Check that all route files export a default component
- Verify file paths and extensions are correct
- Enable debug mode to see detailed import paths
Performance issues
- Disable debug mode in production
- Check for excessive file watching (large node_modules, etc.)
- Consider adjusting debounce delay for your use case
Debug Mode
Enable detailed logging:
reactRouterFsRoutes({
debug: true
})This will show:
- File change events
- Route generation timing
- Import path resolution
- Error details with file paths
Best Practices
- Organize by feature: Group related routes using route groups
(feature) - Use descriptive names: Make component names clear and searchable
- Leverage layouts: Share common UI elements across route groups
- Handle errors: Consider adding error boundaries manually when needed
- Type safety: Use React Router v7's type generation for full TypeScript support
Contributing
This plugin follows Vite plugin conventions and React Router v7 best practices. When contributing:
- Maintain backwards compatibility
- Add comprehensive tests for new features
- Update documentation for any API changes
- Follow the established error handling patterns
License
MIT - See LICENSE file for details.
