
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
modules-page-routing
Advanced tools
Utility library for React Router v7 - helpers for routing, navigation, and page management
Utility library for React Router v7 - Automatically build routes from file-system with support for modules and API handlers.
npm install modules-page-routing
Peer Dependencies:
npm install react react-router
Organize your code using a module-based structure:
app/
├── modules/
│ ├── __root.tsx # Shared layout for all modules
│ ├── __homepage.tsx # Homepage (index route)
│ ├── auth/
│ │ └── pages/
│ │ ├── _layout.tsx # Layout for auth module
│ │ ├── sign-in.tsx # /auth/sign-in
│ │ ├── sign-up.tsx # /auth/sign-up
│ │ └── forgot-password.tsx
│ ├── admin/
│ │ └── pages/
│ │ ├── _layout.tsx # Layout for admin module
│ │ ├── index.tsx # /admin (index route)
│ │ ├── users/
│ │ │ ├── index.tsx # /admin/users
│ │ │ └── [id].tsx # /admin/users/:id
│ │ └── settings.tsx # /admin/settings
│ └── shop/
│ ├── api/
│ │ ├── products.ts # API: /api/shop/products
│ │ └── products.$id.ts # API: /api/shop/products/:id
│ └── pages/
│ ├── index.tsx # /shop
│ ├── products/
│ │ ├── index.tsx # /shop/products
│ │ └── [id].tsx # /shop/products/:id
│ └── cart.tsx # /shop/cart
├── api/
│ └── v1/
│ ├── users.ts # API: /api/v1/users
│ ├── users.$id.ts # API: /api/v1/users/:id
│ └── products.search.ts # API: /api/v1/products/search
└── routes.ts
routes.ts Fileimport {
index,
layout,
prefix,
type RouteConfig,
} from '@react-router/dev/routes';
import { flatRoutes } from '@react-router/fs-routes';
import {
buildApiRouteConfig,
buildApiModuleRouteConfig,
buildGlobRouteConfig,
type GlobModules,
} from 'modules-page-routing';
// Import all files in modules/*/pages/*, modules/*/api/*, and api/**/*
const globTree = import.meta.glob('./modules/**/pages/**/*.{tsx,ts}');
const apiTree = import.meta.glob('./api/**/*.ts');
const apiModuleTree = import.meta.glob('./modules/**/api/**/*.ts');
// Build React Router v7 RouteConfig from glob
const moduleRoutes = buildGlobRouteConfig(globTree as GlobModules);
const apiRoutes = buildApiRouteConfig(apiTree);
const apiModuleRoutes = buildApiModuleRouteConfig(apiModuleTree);
const routes = [
// All module pages are nested under a shared layout
layout('modules/__root.tsx', [
index('modules/__homepage.tsx'),
...moduleRoutes,
]),
// API routes: global (/api/v1/...) + module-scoped (/api/<module>/...)
...prefix('api', [...apiRoutes, ...apiModuleRoutes]),
// Routes from app/routes/** (optional - if you still want traditional file-based routing)
...(await flatRoutes({
rootDirectory: 'routes',
})),
];
export default routes satisfies RouteConfig;
index.tsx → Index route of the module/folder
modules/admin/pages/index.tsx → /adminmodules/admin/pages/users/index.tsx → /admin/users_layout.tsx → Layout wrapper for child routes
modules/admin/pages/_layout.tsx → Layout for all routes in /admin/*modules/admin/pages/users/_layout.tsx → Layout for /admin/users/*[param].tsx → Dynamic route parameter
modules/admin/pages/users/[id].tsx → /admin/users/:idmodules/shop/pages/products/[slug].tsx → /shop/products/:slug[...rest].tsx → Catch-all/splat route
modules/docs/pages/[...path].tsx → /docs/*_not-found.tsx → 404 page for the module
modules/admin/pages/_not-found.tsx → 404 for /admin/*_error.tsx → Error boundary for the module (used by buildGlobRoutes runtime)
modules/admin/pages/_error.tsx → Error boundary for /admin/*modules/admin/pages/users/_error.tsx → Error boundary for /admin/users/*_loading.tsx → Loading fallback for the module (replaces default Suspense fallback)
modules/admin/pages/_loading.tsx → Loading UI for /admin/*modules/admin/pages/users/_loading.tsx → Loading UI for /admin/users/*_<folder> or _<file>.tsx → Parentless route (escapes parent layout)
modules/auth/pages/_login/index.tsx → /auth/login (without auth layout)modules/admin/pages/_fullscreen-editor.tsx → /admin/fullscreen-editor (without admin layout)(group) → Route group (organizational only, no URL segment)
modules/admin/pages/(dashboard)/overview.tsx → /admin/overviewmodules/admin/pages/(settings)/profile.tsx → /admin/profile_layout.tsx inside route groups for shared layouts within the groupadmin/pages/
├── (dashboard)/
│ ├── _layout.tsx # Layout for dashboard group
│ ├── index.tsx # /admin
│ └── analytics.tsx # /admin/analytics
└── (settings)/
├── _layout.tsx # Layout for settings group
├── profile.tsx # /admin/profile
└── security.tsx # /admin/security
API routes use a different convention:
filename.ts → Single segment
api/v1/users.ts → /api/v1/usersfilename.segment.ts → Multiple segments (using .)
api/v1/products.search.ts → /api/v1/products/searchapi/v1/orders.export.csv.ts → /api/v1/orders/export/csvfilename.$param.ts → Dynamic parameter (using $ prefix)
api/v1/users.$id.ts → /api/v1/users/:idapi/v1/posts.$slug.comments.ts → /api/v1/posts/:slug/commentsAPI handlers can also live inside each module's api/ directory, co-located with pages:
modules/auth/api/login.ts → /api/auth/loginmodules/shop/api/products.ts → /api/shop/productsmodules/shop/api/products.$id.ts → /api/shop/products/:idmodules/admin/api/v1/users.ts → /api/admin/v1/usersSame naming conventions apply (. for segments, $ for params, _ for parentless, (group) for groups).
modules/admin/pages/_layout.tsx)import { Outlet } from 'react-router';
export default function AdminLayout() {
return (
<div className='admin-layout'>
<aside>
<nav>
<a href='/admin'>Dashboard</a>
<a href='/admin/users'>Users</a>
<a href='/admin/settings'>Settings</a>
</nav>
</aside>
<main>
<Outlet /> {/* Render nested routes */}
</main>
</div>
);
}
modules/admin/pages/users/[id].tsx)import { useParams } from 'react-router';
export default function UserDetail() {
const { id } = useParams();
return (
<div>
<h1>User Detail: {id}</h1>
{/* Your component code */}
</div>
);
}
api/v1/users.$id.ts)import type { LoaderFunctionArgs } from 'react-router';
export async function loader({ params }: LoaderFunctionArgs) {
const userId = params.id;
// Fetch user data
const user = await fetchUser(userId);
return Response.json(user);
}
export async function action({ request, params }: LoaderFunctionArgs) {
const userId = params.id;
const data = await request.json();
// Update user
await updateUser(userId, data);
return Response.json({ success: true });
}
buildGlobRouteConfig(globModules: GlobModules): RouteConfigNode[]Builds React Router v7 RouteConfig from Vite import.meta.glob().
Parameters:
globModules: Object returned from import.meta.glob('./modules/**/pages/**/*.{tsx,ts}')Returns: Array of RouteConfigNode to use with React Router v7 config
Conventions:
modules/<module>/pages/**/* → URL /<module>/**/*_layout.tsx → Layout wrapper with <Outlet />index.tsx → Index route[param] → Dynamic parameter[...rest] → Catch-all route_not-found.tsx → 404 handler_<folder> or _<file>.tsx → Parentless route (escapes parent layout)buildApiRouteConfig(globModules: Record<string, unknown>): RouteConfigNode[]Builds API route config from a global api/ directory.
Parameters:
globModules: Object returned from import.meta.glob('./api/**/*.ts')Returns: Array of RouteConfigNode to use with prefix('api', ...)
Conventions:
api/v1/users.ts → /api/v1/usersapi/v1/users.$id.ts → /api/v1/users/:idapi/v1/products.search.ts → /api/v1/products/search. in filename → additional path segment$ prefix → dynamic parameter_ prefix in folder/filename → Parentless route (stripped from URL)buildApiModuleRouteConfig(globModules: Record<string, unknown>): RouteConfigNode[]Builds API route config from module-scoped api/ directories. Each module can co-locate its API handlers alongside its pages.
Parameters:
globModules: Object returned from import.meta.glob('./modules/**/api/**/*.ts')Returns: Array of RouteConfigNode to use with prefix('api', ...)
Mapping: modules/<module>/api/<rest> → /api/<module>/<rest>
Examples:
modules/auth/api/login.ts → /api/auth/loginmodules/admin/api/users.$id.ts → /api/admin/users/:idmodules/shop/api/orders.export.ts → /api/shop/orders/exportConventions: Same as buildApiRouteConfig — . for segments, $ for params, _ for parentless, (group) for route groups.
Visualize and validate your route tree from the terminal.
npx modules-page-routing routes --dir ./app
Page Routes
/admin modules/admin/pages/_layout.tsx
├── (index) modules/admin/pages/index.tsx
├── /users modules/admin/pages/users/index.tsx
├── /users/:id modules/admin/pages/users/[id].tsx
├── /settings modules/admin/pages/settings.tsx
└── /* modules/admin/pages/_not-found.tsx
/auth modules/auth/pages/_layout.tsx
├── /sign-in modules/auth/pages/sign-in.tsx
└── /sign-up modules/auth/pages/sign-up.tsx
API Routes
/api/shop/products modules/shop/api/products.ts
/api/shop/products/:id modules/shop/api/products.$id.ts
Use --json for machine-readable output.
npx modules-page-routing validate --dir ./app
Checks for:
| Rule | Severity | Description |
|---|---|---|
duplicate-path | error | Two files resolve to the same URL |
dynamic-conflict | error | [id].tsx and [slug].tsx in the same directory |
catchall-shadow | warn | Catch-all * route may shadow siblings |
orphan-special-file | warn | _error.tsx/_loading.tsx without _layout.tsx |
empty-module | warn | Module has no page files |
missing-index | warn | Has _layout.tsx but no index.tsx |
Exits with code 1 if any errors are found — useful in CI.
This library is written entirely in TypeScript with full type definitions:
import type { GlobModules, RouteConfigNode } from 'modules-page-routing';
✅ Automatic - No need to manually define routes, just create files following conventions
✅ Module-based - Organize code by features/modules, easy to scale
✅ Type-safe - Full TypeScript support
✅ Flexible - Can be combined with traditional file-based routing
✅ Nested layouts - Support for nested layouts with _layout.tsx
✅ API routes - Build both UI routes and API endpoints the same way
See complete examples at: https://github.com/sonicname/modules-page-routing/tree/development/example
MIT
Contributions are welcome! Please feel free to submit a Pull Request or create an Issue on GitHub.
https://github.com/sonicname/modules-page-routing
If you encounter any issues or have questions, please create an issue on the GitHub repository.
FAQs
Utility library for React Router v7 - helpers for routing, navigation, and page management
The npm package modules-page-routing receives a total of 0 weekly downloads. As such, modules-page-routing popularity was classified as not popular.
We found that modules-page-routing demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.