Configuration
The three arguments of createNEMO: the route map, global middleware that runs on every request, and the options that change how the chain behaves.
NEMO offers flexible configuration options to organize your middleware functions.
Middlewares
Type: MiddlewareConfig
Chain type: "main"
The middlewares object is a key-value pair where the key is the route path and the value is an array of middleware functions. Each middleware function is an async function that takes a single argument, request, which is an object containing the request details.
import { type MiddlewareConfig } from "@zanreal/nemo";
const middlewares = {
"/:path*": async (request, event) => {
console.log("There is NEMO", request.nextUrl.pathname);
},
} satisfies MiddlewareConfig;import { type MiddlewareConfig } from "@zanreal/nemo";
const middlewares = {
"/:path*": async (request, event) => {
console.log("There is NEMO", request.nextUrl.pathname);
},
} satisfies MiddlewareConfig;Simple Middleware
The simplest form is a direct function assignment to a route pattern:
import { createNEMO } from "@zanreal/nemo";
const middleware = createNEMO({
// Simple middleware for /api route
"/api": async (request, event) => {
console.log("API request:", request.nextUrl.pathname);
}
});Middleware Arrays
You can assign an array of middleware functions to execute in sequence:
import { createNEMO } from "@zanreal/nemo";
const middleware = createNEMO({
// Multiple middleware functions for /auth route
"/auth": [
// First function in chain
async (request, event) => {
event.storage.set("startTime", Date.now());
},
// Second function in chain
async (request, event) => {
const startTime = event.storage.get("startTime");
console.log(`Request processing time: ${Date.now() - startTime}ms`);
}
]
});Nested Routes
NEMO supports nested route definitions with their own middleware:
import { createNEMO } from "@zanreal/nemo";
const middleware = createNEMO({
"/admin": {
// Middleware for /admin route
middleware: async (request) => {
console.log("Admin section accessed");
},
// Nested routes under /admin
"/users": async (request) => {
console.log("Admin users section");
},
"/settings": async (request) => {
console.log("Admin settings section");
}
}
});When using nested routes, the parent route's middleware executes before any matching child route middleware.
Deep Nesting with Parameters
You can create deeply nested structures with URL parameters:
import { createNEMO } from "@zanreal/nemo";
const middleware = createNEMO({
"/shop": {
middleware: shopMiddleware,
"/categories": {
middleware: categoriesMiddleware,
"/:categoryId": {
middleware: categoryMiddleware,
"/products": {
middleware: productsMiddleware,
"/:productId": productMiddleware
}
}
}
}
});This structure handles routes like /shop/categories/electronics/products/laptop with parameters accessible via event.params.
Global Middlewares
Type: GlobalMiddlewareConfig
Global middleware functions are executed for all routes, regardless of the specific route configuration.
import { type GlobalMiddlewareConfig } from "@zanreal/nemo";
const globalMiddlewares = {
before: async (request, event) => {
console.log("Before any route middleware");
},
after: async (request, event) => {
console.log("After all route middleware");
},
} satisfies GlobalMiddlewareConfig;import { type GlobalMiddlewareConfig } from "@zanreal/nemo";
const globalMiddlewares = {
before: async (request, event) => {
console.log("Before any route middleware");
},
after: async (request, event) => {
console.log("After all route middleware");
},
} satisfies GlobalMiddlewareConfig;Before
Type: MiddlewareFunction | MiddlewareFunction[]
The before middleware executes before any route-specific middleware:
const globalMiddlewares = {
before: async (request, event) => {
console.log("Before route middleware");
event.storage.set("startTime", Date.now());
}
};const globalMiddlewares = {
before: [
async (request, event) => {
event.storage.set("startTime", Date.now());
},
async (request, event) => {
// Another before middleware
}
]
};const globalMiddlewares = {
before: async (request, event) => {
console.log("Before route middleware");
event.storage.set("startTime", Date.now());
}
};const globalMiddlewares = {
before: [
async (request, event) => {
event.storage.set("startTime", Date.now());
},
async (request, event) => {
// Another before middleware
}
]
};After
Type: MiddlewareFunction | MiddlewareFunction[]
The after middleware executes after all route-specific middleware:
const globalMiddlewares = {
after: async (request, event) => {
const startTime = event.storage.get("startTime");
console.log(`Request took: ${Date.now() - startTime}ms`);
},
};const globalMiddlewares = {
after: [
async (request, event) => {
// First after middleware
},
async (request, event) => {
// Second after middleware
}
]
};const globalMiddlewares = {
after: async (request, event) => {
const startTime = event.storage.get("startTime");
console.log(`Request took: ${Date.now() - startTime}ms`);
},
};const globalMiddlewares = {
after: [
async (request, event) => {
// First after middleware
},
async (request, event) => {
// Second after middleware
}
]
};Config object
Type: NemoConfig
The config object is a key-value pair where the key is the configuration option and the value is the configuration value. The available configuration options are:
Prop
Type
import { type NemoConfig } from "@zanreal/nemo";
const config = {
debug: true,
silent: true,
enableTiming: true,
errorHandler: (error, metadata) => {
console.error(error, metadata);
},
} satisfies NemoConfig;
import { type NemoConfig } from "@zanreal/nemo";
const config = {
debug: true,
silent: true,
enableTiming: true,
errorHandler: (error, metadata) => {
console.error(error, metadata);
},
} satisfies NemoConfig;
Example
Getting all of above information together makes for us NEMO's full configuration representing all usable properties.
The createNEMO() constructor is the entry point for the NEMO package. It allows you to create a middleware helper that can be used to define middleware functions for your Next.js application.
import {
createNEMO,
type MiddlewareConfig,
type GlobalMiddlewareConfig,
type NemoConfig,
} from "@zanreal/nemo";
const middlewares = {
"/:path*": async (request) => {
// middleware functions for /api route
},
} satisfies MiddlewareConfig;
const globalMiddlewares = {
before: async () => {
// global middleware function that will be executed before any route middleware
},
after: async () => {
// global middleware function that will be executed after any route middleware
},
} satisfies GlobalMiddlewareConfig;
const nemoConfig = {
debug: true, // default is false
silent: true, // default is false
enableTiming: true, // default is false
errorHandler: (error, metadata) => {
// custom error handler
},
} satisfies NemoConfig;
export const proxy = createNEMO(
middlewares,
globalMiddlewares,
nemoConfig,
);
export const config = {
matcher: ["/((?!_next/|_static|_vercel|[\\w-]+\\.\\w+).*)"],
};import {
createNEMO,
type MiddlewareConfig,
type GlobalMiddlewareConfig,
type NemoConfig,
} from "@zanreal/nemo";
const middlewares = {
"/:path*": async (request) => {
// middleware functions for /api route
},
} satisfies MiddlewareConfig;
const globalMiddlewares = {
before: async () => {
// global middleware function that will be executed before any route middleware
},
after: async () => {
// global middleware function that will be executed after any route middleware
},
} satisfies GlobalMiddlewareConfig;
const nemoConfig = {
debug: true, // default is false
silent: true, // default is false
enableTiming: true, // default is false
errorHandler: (error, metadata) => {
// custom error handler
},
} satisfies NemoConfig;
export const middleware = createNEMO(
middlewares,
globalMiddlewares,
nemoConfig,
);
export const config = {
matcher: ["/((?!_next/|_static|_vercel|[\\w-]+\\.\\w+).*)"],
};Was this helpful?
M↓supported.