A middleware composition library for Next.js applications that allows you to organize and chain middleware functions based on URL patterns.
npm install @rescale/nemo
pnpm add @rescale/nemo
bun add @rescale/nemo
- 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
Can be either a legacy Next.js middleware (NextMiddleware
) or the new middleware format (NewMiddleware
).
Record<string, MiddlewareFunction | MiddlewareFunction[]>
interface MiddlewareFunctionProps {
request: NextRequest;
context: MiddlewareContext;
event: NextFetchEvent;
forward: (response: MiddlewareReturn) => void;
}
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
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.
import { createMiddleware } from '@rescale/nemo';
export default createMiddleware({
'/api/:path': async ({ request }) => {
// Handle API routes
},
'/protected/:path': async ({ request, context }) => {
// Handle protected routes
}
});
import { createMiddleware } from '@rescale/nemo';
export default createMiddleware({
'/api/:path': apiMiddleware,
},
{
before: [loggerMiddleware, authMiddleware],
after: cleanupMiddleware,
});
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
}
]
});
- 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
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!