A comprehensive CLI tool for generating type-safe navigation helpers in modern web frameworks. Generate type-safe route helpers, catch routing errors at compile time, analyze route performance, and audit your routing architecture with full IDE autocompletion support.
npm install type-safe-router-gen
npx router-gen generate --analytics --generate-apiNEW in v0.2: Next.js App Router support, Route Analytics, API helpers, Performance analysis, and Route auditing.
# Install globally
npm install -g type-safe-router-gen
# Or use npx (recommended)
npx router-gen --help# Generate routes from your pages directory
npx router-gen generate --input ./pages --output ./src/routes.ts
# Or use the default paths (looks for pages/ or app/ directories)
npx router-gen generateimport { Routes } from './src/routes';
// Type-safe navigation
const blogUrl = Routes.blog.slug({ slug: 'my-post' }); // "/blog/my-post"
const searchUrl = Routes.search({ q: 'typescript', page: 2 }); // "/search?q=typescript&page=2"
// TypeScript catches errors at compile time
Routes.blog.slug(); // Error: missing required 'slug'
Routes.blog.slug({ id: 123 }); // Error: 'id' is not assignable to 'slug'
Routes.search({ invalid: 'param' }); // Error: 'invalid' is not a valid query param# Pages Router
pages/
├── index.tsx → Routes.home()
├── about.tsx → Routes.about()
├── blog/
│ ├── [slug].tsx → Routes.blog.slug({ slug: string })
│ └── index.tsx → Routes.blog.index()
└── docs/
└── [[...slug]].tsx → Routes.docs.slug({ slug?: string[] })
# App Router (NEW)
app/
├── page.tsx → Routes.home()
├── about/
│ └── page.tsx → Routes.about()
├── blog/
│ ├── [slug]/
│ │ └── page.tsx → Routes.blog.slug({ slug: string })
│ └── page.tsx → Routes.blog.index()
└── (dashboard)/ # Route groups supported
└── analytics/
└── page.tsx → Routes.analytics()
app/routes/
├── _index.tsx → Routes.home()
├── about.tsx → Routes.about()
├── blog.$slug.tsx → Routes.blog.slug({ slug: string })
└── docs.$.tsx → Routes.docs.catchAll({ '*': string })
src/pages/ # Astro
src/routes/ # SvelteKit
├── index.astro → Routes.home()
├── about.astro → Routes.about()
├── blog/
│ └── [slug].astro → Routes.blog.slug({ slug: string })
# Basic generation
npx router-gen generate
# With custom paths and Next.js App Router
npx router-gen generate --input ./app --framework nextjs-app
# Generate with analytics and API helpers
npx router-gen generate --analytics --generate-api --generate-tests
# For different frameworks
npx router-gen generate --framework remix
npx router-gen generate --framework astro
npx router-gen generate --framework sveltekit
# NEW: Dry-run mode (preview without writing files)
npx router-gen generate --dry-run
# NEW: Verbose mode (show detailed configuration)
npx router-gen generate --verbose
# NEW: Combine both for testing
npx router-gen generate --dry-run --verbose# Analyze route usage and generate insights
npx router-gen audit --source ./src
# Performance analysis for route optimization
npx router-gen performance
# Watch mode with analytics
npx router-gen watch --analytics --generate-api# Watch for file changes and auto-regenerate
npx router-gen watch
# Watch with all features enabled
npx router-gen watch --analytics --generate-api --generate-tests# Find unused routes and potential issues
npx router-gen audit
# Audit with custom source directory
npx router-gen audit --source ./components --input ./pages
# Auto-fix mode (experimental)
npx router-gen audit --fix# Create a router-gen.config.json file
npx router-gen initCreate a router-gen.config.json file in your project root:
{
"input": "./pages",
"output": "./src/generated-routes.ts",
"framework": "nextjs",
"excludePatterns": ["**/api/**", "**/_*"],
"includeQueryParams": true,
"generateTests": false
}| Option | Type | Default | Description |
|---|---|---|---|
input |
string |
"./pages" |
Directory containing your route files |
output |
string |
"./src/generated-routes.ts" |
Output file for generated routes |
framework |
string |
"nextjs" |
Framework type (nextjs, nextjs-app, remix, astro, sveltekit) |
excludePatterns |
string[] |
["**/api/**", "**/_*"] |
Glob patterns to exclude |
includeQueryParams |
boolean |
true |
Extract query parameters from route files |
generateTests |
boolean |
false |
Generate test files alongside routes |
generateApiRoutes |
boolean |
false |
Generate API route helpers with fetch utilities |
routeAnalytics |
boolean |
false |
Generate route analytics and usage reports |
The CLI now features beautiful, colorized output with emojis and clear visual hierarchy:
- Visual Separators: Clean section dividers for better readability
- Emoji Indicators: 🚀 for actions, ✓ for success, ❌ for errors, 💡 for suggestions
- Color Coding: Green for success, red for errors, yellow for warnings, cyan for info
- Progress Tracking: Real-time feedback on what's happening
Preview what would be generated without writing any files:
npx router-gen generate --dry-runPerfect for:
- Testing configuration changes
- Verifying route discovery
- CI/CD validation
- Documentation generation
See detailed information about the generation process:
npx router-gen generate --verboseShows:
- Full configuration being used
- All discovered routes with details
- File paths and sizes
- Framework-specific settings
Get helpful suggestions when things go wrong:
npx router-gen generate --input ./wrong-path
# Output:
# ❌ Error: Input directory does not exist!
# Path: /path/to/wrong-path
#
# 💡 Suggestions:
# 1. Check if the path is correct
# 2. For Next.js, try: --input ./pages or --input ./app
# 3. For Remix, try: --input ./app/routes
# 4. For SvelteKit, try: --input ./src/routes
# 5. For Astro, try: --input ./src/pagesAfter generation, get a detailed summary:
═══════════════════════════════════════════════════
✓ Route Generation Complete!
═══════════════════════════════════════════════════
Summary:
Total Routes: 47
Static Routes: 35
Dynamic Routes: 12
Routes with Query Params: 8
Output:
src/generated-routes.ts (15.2 KB)
═══════════════════════════════════════════════════
Define query parameters in your route files using a QueryParams interface:
// pages/search.tsx
export interface QueryParams {
q: string; // Required query param
page?: number; // Optional query param
category?: string[]; // Optional array query param
}
export default function SearchPage() {
return <div>Search Page</div>;
}Generated route:
Routes.search({
q: 'typescript', // Required
page: 2, // Optional
category: ['tutorial'] // Optional array
});
// → "/search?q=typescript&page=2&category=tutorial"Get comprehensive insights about your routing architecture:
npx router-gen generate --analyticsGenerates route-analytics.json with:
- Total route count and distribution
- Dynamic vs static route analysis
- Route depth and complexity metrics
- Parameter usage patterns
- Performance recommendations
{
"totalRoutes": 47,
"dynamicRoutes": 12,
"staticRoutes": 35,
"nestedRoutes": 23,
"routeDepthDistribution": { "1": 15, "2": 20, "3": 12 },
"parameterUsage": { "id": 8, "slug": 5, "category": 3 }
}Find unused routes, potential issues, and optimization opportunities:
npx router-gen auditWhat it detects:
- Unused routes that can be removed
- Magic string usage (potential broken links)
- Route usage patterns across your codebase
- Most and least used routes
Sample output:
Route Usage Report:
Total Routes: 47
Used Routes: 42
Unused Routes: 5
Potential Issues: 3
Unused Routes:
/admin/legacy -> pages/admin/legacy.tsx
/temp/debug -> pages/temp/debug.tsx
Potential Issues:
Potential broken link in src/components/Nav.tsx: "/old-path"
Analyze route performance and get optimization suggestions:
npx router-gen performanceAnalyzes:
- File size and bundle impact
- Code complexity metrics
- Dependency analysis
- Performance anti-patterns
Sample output:
Performance Analysis Results:
Total Routes: 47
Total Size: 892.3 KB
Average Complexity: 6.2
Routes with Issues: 8
Routes Needing Attention:
pages/dashboard/analytics.tsx
Size: 45.2 KB, Complexity: 15, Lines: 387
• Large file size - consider code splitting
• High complexity - consider refactoring
Generate type-safe API helpers with built-in fetch utilities:
npx router-gen generate --generate-apiFor API routes like:
pages/api/
├── users/
│ ├── [id].ts # GET /api/users/:id
│ └── index.ts # GET /api/users
└── posts/
└── [slug].ts # GET /api/posts/:slug
Generates generated-routes-api.ts:
export const ApiRoutes = {
users: {
index: () => '/api/users',
id: (params: { id: string }) => `/api/users/${params.id}`
},
posts: {
slug: (params: { slug: string }) => `/api/posts/${params.slug}`
}
};
// Type-safe fetch helpers
export const api = {
get: async <T>(url: string, options?: RequestInit): Promise<T> => { /* ... */ },
post: async <T>(url: string, data?: any, options?: RequestInit): Promise<T> => { /* ... */ },
// ... put, delete
};
// Usage
const user = await api.get<User>(ApiRoutes.users.id({ id: '123' }));
const users = await api.post<User[]>(ApiRoutes.users.index(), { name: 'John' });pages/
├── index.tsx → Routes.home()
├── products/
│ ├── index.tsx → Routes.products.index()
│ ├── [id].tsx → Routes.products.id({ id: string })
│ └── category/
│ └── [slug].tsx → Routes.products.category.slug({ slug: string })
├── user/
│ ├── profile.tsx → Routes.user.profile()
│ └── orders/
│ ├── index.tsx → Routes.user.orders.index()
│ └── [orderId].tsx → Routes.user.orders.orderId({ orderId: string })
└── search.tsx → Routes.search({ q: string, filters?: string[] })
Usage in components:
import { Routes } from '../generated-routes';
import Link from 'next/link';
function ProductCard({ product }) {
return (
<Link href={Routes.products.id({ id: product.id })}>
{product.name}
</Link>
);
}
function SearchForm() {
const handleSearch = (query: string) => {
router.push(Routes.search({ q: query }));
};
}app/routes/
├── _index.tsx → Routes.home()
├── blog._index.tsx → Routes.blog.index()
├── blog.$slug.tsx → Routes.blog.slug({ slug: string })
├── blog.admin.tsx → Routes.blog.admin()
└── blog.admin.new.tsx → Routes.blog.admin.new()
import { useNavigate } from '@remix-run/react';
import { Routes } from '~/generated-routes';
function MyComponent() {
const navigate = useNavigate();
const goToBlog = (slug: string) => {
navigate(Routes.blog.slug({ slug }));
};
}import { useRouter } from 'next/router';
import { Routes } from '../generated-routes';
function MyComponent() {
const router = useRouter();
const goToProduct = (id: string) => {
router.push(Routes.products.id({ id }));
};
}---
import { Routes } from '../generated-routes';
const blogUrl = Routes.blog.slug({ slug: 'my-post' });
---
<a href={blogUrl}>Read my blog post</a># Terminal 1: Watch for route changes
npx router-gen watch
# Terminal 2: Run your dev server
npm run dev- Create a new route file (e.g.,
pages/blog/[slug].tsx) - Routes are automatically regenerated
- Import and use the new route:
Routes.blog.slug({ slug: 'new-post' })
When you rename or move route files:
- Routes are automatically regenerated
- TypeScript will show errors where old routes are used
- Update your code using IDE autocompletion
// Good: Consistent interface across similar routes
export interface SearchParams {
q: string;
page?: number;
sort?: 'asc' | 'desc';
}// Good: Clear hierarchy
pages/
├── dashboard/
│ ├── analytics/
│ │ └── [timeframe].tsx → Routes.dashboard.analytics.timeframe()
│ └── settings/
│ └── profile.tsx → Routes.dashboard.settings.profile()
// Avoid: Flat structure
pages/
├── dashboard-analytics-timeframe.tsx
└── dashboard-settings-profile.tsx
// Good: Type-safe redirects
const redirectToLogin = () => {
return Response.redirect(Routes.auth.login());
};
// Avoid: Magic strings
const redirectToLogin = () => {
return Response.redirect('/auth/login');
};{
"input": "./pages",
"output": "./src/routes.ts",
"framework": "nextjs",
"excludePatterns": [
"**/api/**",
"**/_*",
"**/components/**"
],
"includeQueryParams": true,
"generateTests": true
}Generate routes for different parts of your app:
# Admin routes
npx router-gen generate --input ./pages/admin --output ./src/admin-routes.ts
# Public routes
npx router-gen generate --input ./pages/public --output ./src/public-routes.tsnpm install type-safe-router-gen
npx router-gen generateyarn add type-safe-router-gen
yarn router-gen generatepnpm add type-safe-router-gen
pnpm router-gen generatebun add type-safe-router-gen
bunx router-gen generate- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Inspired by the type-safety patterns in modern web frameworks
- Built for the developer community who values type safety and great DX
- Special thanks to all contributors and users providing feedback
Built with care for the TypeScript community