Skip to content

z4nr34l/nemo

Repository files navigation

@rescale/nemo

A middleware composition library for Next.js applications that allows you to organize and chain middleware functions based on URL patterns.

codecov

Installation

npm install @rescale/nemo
pnpm add @rescale/nemo
bun add @rescale/nemo

Key Features

  • Path-based middleware routing
  • Global middleware support (before/after)
  • Context sharing between middleware
  • Support for both legacy and modern middleware patterns
  • Request/Response header and cookie forwarding

API Reference

Types

MiddlewareFunction

Can be either a legacy Next.js middleware (NextMiddleware) or the new middleware format (NewMiddleware).

MiddlewareConfig

Record<string, MiddlewareFunction | MiddlewareFunction[]>

MiddlewareFunctionProps

interface MiddlewareFunctionProps {
  request: NextRequest;
  context: MiddlewareContext;
  event: NextFetchEvent;
  forward: (response: MiddlewareReturn) => void;
}

Main Functions

createMiddleware

function createMiddleware(
  pathMiddlewareMap: MiddlewareConfig,
  globalMiddleware?: {
    before?: MiddlewareFunction | MiddlewareFunction[];
    after?: MiddlewareFunction | MiddlewareFunction[];
  }
): NextMiddleware

Creates a composed middleware function that:

  • Executes global "before" middleware first
  • Matches URL patterns and executes corresponding middleware
  • Executes global "after" middleware last
  • Forwards headers and cookies between middleware functions

forward

function forward(response: MiddlewareReturn): void

Function that allows passing response from legacy middleware functions to the next middleware in the chain. This enables compatibility between legacy Next.js middleware and the new middleware format.

Usage Examples

Basic Path-Based Middleware

import { createMiddleware } from '@rescale/nemo';

export default createMiddleware({
  '/api/:path': async ({ request }) => {
    // Handle API routes
  },
  '/protected/:path': async ({ request, context }) => {
    // Handle protected routes
  }
});

Using Global Middleware

import { createMiddleware } from '@rescale/nemo';

export default createMiddleware({
  '/api/:path': apiMiddleware,
},
{
  before: [loggerMiddleware, authMiddleware],
  after: cleanupMiddleware,
});

Context Sharing

import { createMiddleware } from '@rescale/nemo';

export default createMiddleware({
  '/:path': [
    async ({ context }) => {
      context.set('user', { id: 1 });
    },
    async ({ context }) => {
      const user = context.get('user');
      // Use the user data
    }
  ]
});

Notes

  • Middleware functions are executed in order until a Response is returned
  • The context Map is shared between all middleware functions in the chain
  • Headers and cookies are automatically forwarded between middleware functions
  • Supports both Next.js legacy middleware pattern and the new props-based pattern

Motivation

I'm working with Next.js project for a few years now, after Vercel moved multiple /**/_middleware.ts files to a single /middleware.ts file, there was a unfilled gap - but just for now. After a 2023 retro I had found that there is no good solution for that problem, so I took matters into my own hands. I wanted to share that motivation with everyone here, as I think that we all need to remember how it all started.

Hope it will save you some time and would make your project DX better!