npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

next-modular

v1.0.3

Published

A modular architecture system for Next.js applications that enables building reusable, self-contained modules with their own routes, API endpoints, and middleware.

Downloads

18

Readme

Next Modular

A modular architecture system for Next.js applications that enables building reusable, self-contained modules with their own routes, API endpoints, and middleware.

Features

  • Route Modules: Define page routes within modules
  • API Endpoints: Create module-specific API routes with dynamic parameters
  • Middleware: Add module-level middleware logic
  • Type-Safe: Full TypeScript support
  • CLI Tools: Initialize, add, and create modules with interactive CLI
  • Easy Integration: Simple configuration in Next.js apps

Quick Start

Using the CLI (Recommended)

# Initialize a Next.js app for Next Modular
npx next-modular init

# Add modules from registry
npx next-modular add @next-modular/auth-module

# Create custom modules
npx next-modular create --name my-module

# Start your app
npm run dev

Manual Setup

# 1. Install dependencies
npm install next-modular

# 2. Initialize your Next.js app
npx next-modular init

# 3. Start developing
npm run dev

CLI Commands

next-modular init

Initialize a Next.js app to use Next Modular. Creates all necessary files:

  • Catch-all routes (app/[...module]/page.tsx)
  • Catch-all API routes (app/api/[...module]/route.ts)
  • Middleware/proxy file (proxy.ts)
  • Configuration files (modules.config.ts, next-modular.runtime.ts)
npx next-modular init
npx next-modular init --directory ./my-app

next-modular add [module]

Add modules from the registry or npm:

# Interactive - shows list of available modules
npx next-modular add

# Add specific module
npx next-modular add @next-modular/auth-module

# Add custom npm package
npx next-modular add @your-org/custom-module

# Skip confirmation
npx next-modular add @next-modular/auth-module --yes

Available Modules:

  • @next-modular/auth-module - Authentication with login, register, password reset
  • @next-modular/test-module - Example module with routes, API, and middleware
  • Custom npm packages

next-modular create

Create a new local module with interactive setup:

# Interactive mode
npx next-modular create

# With options
npx next-modular create --name my-module --path modules

Features:

  • Interactive module name validation
  • Customizable path (default: modules/)
  • Choose features: Routes, API endpoints, Middleware, TypeScript
  • Auto-updates modules.config.ts
  • Generates complete module structure with examples

Project Structure

your-app/
├── app/
│   ├── [...module]/
│   │   └── page.tsx           # Catch-all route for module pages
│   ├── api/
│   │   └── [...module]/
│   │       └── route.ts       # Catch-all API route
│   └── page.tsx
├── modules/                   # Your local modules (created with 'create')
│   └── my-module/
│       └── src/
│           ├── routes/        # Module pages
│           ├── server/        # Server-side logic
│           │   ├── api/       # API handlers
│           │   └── middleware.ts
│           └── index.ts       # Module definition
├── modules.config.ts          # Centralized module configuration
├── next-modular.runtime.ts    # Runtime initialization
├── proxy.ts                   # Middleware
└── next.config.ts

How It Works

Module Definition

Modules are defined using defineModule:

import { defineModule } from 'next-modular';
import HomePage from './routes/home';
import { handleApi } from './server/api';
import { middleware } from './server/middleware';

export const myModule = defineModule({
  name: 'my-module',
  basePath: '/my-module',
  routes: [
    { path: '/home', component: HomePage },
    { path: '/about', component: AboutPage },
    { path: '/users/[id]', component: UserDetailPage }, // Dynamic routes
  ],
  apiRoutes: [
    { path: '/hello', handler: handleApi },
    { path: '/users/[id]', handler: getUserHandler }, // Dynamic API routes
  ],
  middleware: {
    handler: middleware,
  },
});

Module Configuration

Create a centralized modules.config.ts:

import { authModule } from '@next-modular/auth-module';
import { myModule } from './modules/my-module/src';

export const modules = [
  authModule,
  myModule,
];

Update next.config.ts:

import { withNextModular } from "next-modular/config";
import { modules } from "./modules.config";

const nextConfig = {
  /* your config */
};

export default withNextModular({
  modules,
})(nextConfig);

Update next-modular.runtime.ts:

import { configureModules } from 'next-modular';
import { modules } from './modules.config';

configureModules({ modules });
export { modules };

Module Configuration Options

Modules support custom configuration:

// Define config interface
export interface MyModuleConfig {
  apiKey?: string;
  timeout?: number;
  enableFeature?: boolean;
}

// Create module with config support
export const myModule = defineModule<MyModuleConfig>({
  name: 'my-module',
  basePath: '/my-module',
  config: {
    // Default configuration
    apiKey: '',
    timeout: 5000,
    enableFeature: true,
  },
  routes: [/* ... */],
  apiRoutes: [/* ... */],
});

Use with custom configuration:

// modules.config.ts
export const modules = [
  myModule({
    apiKey: process.env.MY_API_KEY,
    timeout: 10000,
    enableFeature: false,
  }),
];

Access config in handlers:

import { getModuleConfig } from 'next-modular';
import { MyModuleConfig } from '../index';

export async function handler(req: Request) {
  const config = getModuleConfig<MyModuleConfig>('my-module');
  
  if (config?.enableFeature) {
    // Do something
  }
  
  return new Response(JSON.stringify({ config }));
}

Request Flow

  1. Page Request → Catch-all route [...module]/page.tsxhandleRoute() → Module component
  2. API Request → Catch-all API route api/[...module]/route.tshandleApiRoute() → Module handler
  3. Middlewareproxy.tshandleMiddleware() → Module middleware

Creating Modules

Using CLI (Recommended)

npx next-modular create --name blog

This creates a complete module structure with starter files.

Manual Creation

1. Create Module Structure

mkdir -p modules/blog/src/{routes,server/api}
cd modules/blog
npm init -y

2. Add Dependencies

{
  "name": "@your-org/blog",
  "peerDependencies": {
    "next": ">=14.0.0",
    "react": ">=18.0.0",
    "next-modular": "*"
  }
}

3. Create Components

modules/blog/src/routes/home.tsx:

export default function BlogHome() {
  return (
    <div>
      <h1>Blog</h1>
      <p>Welcome to the blog!</p>
    </div>
  );
}

4. Create API Handlers

modules/blog/src/server/api/posts.ts:

export async function handlePosts(req: Request) {
  const posts = [
    { id: 1, title: 'First Post' },
    { id: 2, title: 'Second Post' },
  ];
  
  return new Response(JSON.stringify(posts), {
    headers: { 'Content-Type': 'application/json' },
  });
}

5. Define Module

modules/blog/src/index.ts:

import { defineModule } from 'next-modular';
import BlogHome from './routes/home';
import { handlePosts } from './server/api/posts';

export const blogModule = defineModule({
  name: 'blog',
  basePath: '/blog',
  routes: [
    { path: '/home', component: BlogHome },
  ],
  apiRoutes: [
    { path: '/posts', handler: handlePosts },
  ],
});

6. Register Module

Add to modules.config.ts:

import { blogModule } from './modules/blog/src';

export const modules = [
  authModule,
  blogModule, // Add your new module
];

Dynamic Routes

Modules support dynamic route parameters:

// Route with dynamic segment
{ path: '/products/[id]', component: ProductDetail }

// API with dynamic segment
{ path: '/api/products/[id]', handler: getProduct }

// Access parameters in component
export default function ProductDetail({ params }: { params?: Record<string, string> }) {
  const productId = params?.id;
  return <div>Product: {productId}</div>;
}

// Access parameters in API handler
export async function getProduct(req: Request, context: any) {
  const productId = context.params?.id;
  return new Response(JSON.stringify({ id: productId }));
}

Example Modules

Auth Module

The included @next-modular/auth-module demonstrates:

  • Routes: Login (/auth/login), register (/auth/register), forgot password (/auth/forgot-password)
  • API Endpoints:
    • POST /api/auth/login - User login
    • POST /api/auth/register - User registration
    • POST /api/auth/logout - User logout
    • GET /api/auth/session - Get current session
  • Middleware: Request logging and authentication checking
  • Mock Implementation: Ready-to-customize authentication logic

Test Module

The @next-modular/test-module showcases:

  • Static Routes: /test, /test/about
  • Dynamic Routes: /test/products/[id], /test/users/[username]
  • API Endpoints: Hello, status, products CRUD, users
  • Middleware: Request logging and custom headers

Testing Your Module

# Start the development server
cd apps/test-app
npm run dev

Visit your module routes:

  • http://localhost:3010/your-module/home
  • http://localhost:3010/api/your-module/endpoint

Test API endpoints:

curl http://localhost:3010/api/your-module/hello

Development

Watch Mode

For development with hot reload:

# Terminal 1 - Watch module changes
cd modules/my-module && npm run dev

# Terminal 2 - Run Next.js app
cd apps/your-app && npm run dev

Building

# Build specific module
cd modules/my-module && npm run build

# Build all packages (in monorepo)
npm run build

Architecture Benefits

  • Modularity: Self-contained modules with their own routes, API, and logic
  • Reusability: Share modules across multiple Next.js applications
  • Type Safety: Full TypeScript support throughout
  • Scalability: Easy to add, remove, or update modules
  • Separation of Concerns: Each module manages its own functionality
  • Maintainability: Clear structure and boundaries between modules
  • Configuration: Per-module configuration with type safety
  • Dynamic Routing: Support for dynamic route parameters

Advanced Features

Environment-Based Configuration

const isDevelopment = process.env.NODE_ENV === 'development';

export const modules = [
  myModule({
    enableLogging: isDevelopment,
    apiRateLimit: isDevelopment ? 1000 : 100,
  }),
];

Feature Flags

export const modules = [
  myModule({
    features: {
      newFeature: process.env.ENABLE_NEW_FEATURE === 'true',
    },
  }),
];

Module-Level Middleware

import { NextRequest } from 'next/server';

export async function middleware(req: NextRequest) {
  console.log(`[My Module] ${req.method} ${req.url}`);
  
  // Add custom headers
  const response = NextResponse.next();
  response.headers.set('X-Module', 'my-module');
  return response;
}

API Reference

defineModule<TConfig>(definition: ModuleDefinition)

Defines a new module with routes, API endpoints, and middleware.

Parameters:

  • name - Unique module identifier
  • basePath - Base URL path for the module
  • config - Default configuration (optional)
  • routes - Array of page routes
  • apiRoutes - Array of API endpoints
  • middleware - Middleware handler (optional)

handleRoute(pathname: string)

Matches a pathname to a module route and returns the component.

handleApiRoute(req: Request, pathname: string, context?: any)

Handles API route requests and returns a Response.

handleMiddleware(req: NextRequest)

Executes middleware for matching modules.

withNextModular(config: NextModularConfig)

Next.js config plugin that registers modules.

getModuleConfig<T>(moduleName: string)

Retrieves module configuration at runtime.

Package Documentation

Troubleshooting

Module not found

Make sure you:

  1. Built the module (npm run build in the module directory)
  2. Installed dependencies (npm install)
  3. Registered the module in modules.config.ts
  4. Imported the module configuration in next.config.ts and next-modular.runtime.ts

Route not working

Check that:

  1. The module is registered
  2. The basePath and path are correct
  3. The component is exported as default
  4. You've restarted the dev server

API endpoint not working

Verify:

  1. The API route handler is properly defined
  2. The path pattern matches your request
  3. The HTTP method is supported in the catch-all route
  4. Check server console for errors

TypeScript errors

Run:

npm run build

Check for linting errors and fix them.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT