Skip to content

sonicname/modules-page-routing

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

10 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

modules-page-routing

Utility library for React Router v7 - Automatically build routes from file-system with support for modules and API handlers.

Features

  • 🎯 Type-safe - Full TypeScript support with comprehensive type definitions
  • πŸ“ File-based routing - Automatically build routes from directory structure
  • 🧩 Module-based - Organize code by independent modules
  • πŸ”Œ API routes - Support for building API handlers
  • πŸ“¦ ESM & CommonJS - Dual module support for maximum compatibility
  • ⚑ Zero dependencies - Only peer dependencies on React and React Router v7

Installation

npm install modules-page-routing

Peer Dependencies:

npm install react react-router

Usage

1. Directory Structure

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/
β”‚       └── 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

2. routes.ts File

import {
  index,
  layout,
  prefix,
  type RouteConfig,
} from '@react-router/dev/routes';
import { flatRoutes } from '@react-router/fs-routes';
import { buildApiRouteConfig } from 'modules-page-routing';
import { buildGlobRouteConfig, type GlobModules } from 'modules-page-routing';

// Import all files in modules/*/pages/* and api/**/*
const globTree = import.meta.glob('./modules/**/pages/**/*.{tsx,ts}');
const apiTree = import.meta.glob('./api/**/*.ts');

// Build React Router v7 RouteConfig from glob
const moduleRoutes = buildGlobRouteConfig(globTree as GlobModules);
const apiRoutes = buildApiRouteConfig(apiTree);

const routes = [
  // All module pages are nested under a shared layout
  layout('modules/__root.tsx', [
    index('modules/__homepage.tsx'),
    ...moduleRoutes,
  ]),

  // API routes with /api prefix
  ...prefix('api', apiRoutes),

  // Routes from app/routes/** (optional - if you still want traditional file-based routing)
  ...(await flatRoutes({
    rootDirectory: 'routes',
  })),
];

export default routes satisfies RouteConfig;

3. File Naming Conventions

Module Pages

  • index.tsx β†’ Index route of the module/folder

    • modules/admin/pages/index.tsx β†’ /admin
    • modules/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/:id
    • modules/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/*

API Routes

API routes use a different convention:

  • filename.ts β†’ Single segment

    • api/v1/users.ts β†’ /api/v1/users
  • filename.segment.ts β†’ Multiple segments (using .)

    • api/v1/products.search.ts β†’ /api/v1/products/search
    • api/v1/orders.export.csv.ts β†’ /api/v1/orders/export/csv
  • filename.$param.ts β†’ Dynamic parameter (using $ prefix)

    • api/v1/users.$id.ts β†’ /api/v1/users/:id
    • api/v1/posts.$slug.comments.ts β†’ /api/v1/posts/:slug/comments

4. Component Examples

Module Layout (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>
  );
}

Module Page (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 Handler (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 });
}

API Reference

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:

  • Files in 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

buildApiRouteConfig(globModules: Record<string, unknown>): RouteConfigNode[]

Builds API route config from Vite import.meta.glob().

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/users
  • api/v1/users.$id.ts β†’ /api/v1/users/:id
  • api/v1/products.search.ts β†’ /api/v1/products/search
  • . in filename β†’ additional path segment
  • $ prefix β†’ dynamic parameter

TypeScript Support

This library is written entirely in TypeScript with full type definitions:

import type { GlobModules, RouteConfigNode } from 'modules-page-routing';

Benefits

βœ… 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

Real-world Example

See complete examples at: https://github.com/sonicname/modules-page-routing/tree/development/example

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request or create an Issue on GitHub.

Repository

https://github.com/sonicname/modules-page-routing

If you encounter any issues or have questions, please create an issue on the GitHub repository.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published