This is `canary` version of documentation. It's still under construction and review.
ZANREAL logoNEMO

Configuration

Learn how to configure NEMO middleware

Configuration

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.

proxy.ts
import { type  } from "@rescale/nemo";

const  = {
  "/:path*": async (, ) => {
    .("There is NEMO", ..);
  },
} satisfies ;
middleware.ts
import { type  } from "@rescale/nemo";

const  = {
  "/:path*": async (, ) => {
    .("There is NEMO", ..);
  },
} satisfies ;

Simple Middleware

The simplest form is a direct function assignment to a route pattern:

import { createNEMO } from "@rescale/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 "@rescale/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 "@rescale/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 "@rescale/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.

proxy.ts
import { type  } from "@rescale/nemo";

const  = {
  : async (, ) => {
    .("Before any route middleware");
  },
  : async (, ) => {
    .("After all route middleware");
  },
} satisfies ;
middleware.ts
import { type  } from "@rescale/nemo";

const  = {
  : async (, ) => {
    .("Before any route middleware");
  },
  : async (, ) => {
    .("After all route middleware");
  },
} satisfies ;

Before

Type: MiddlewareFunction | MiddlewareFunction[]

The before middleware executes before any route-specific middleware:

proxy.ts
const globalMiddlewares = {
  before: async (request, event) => {
    console.log("Before route middleware");
    event.storage.set("startTime", Date.now());
  }
};
proxy.ts
const globalMiddlewares = {
  before: [
    async (request, event) => {
      event.storage.set("startTime", Date.now());
    },
    async (request, event) => {
      // Another before middleware
    }
  ]
};
middleware.ts
const globalMiddlewares = {
  before: async (request, event) => {
    console.log("Before route middleware");
    event.storage.set("startTime", Date.now());
  }
};
middleware.ts
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:

proxy.ts
const globalMiddlewares = {
  after: async (request, event) => {
    const startTime = event.storage.get("startTime");
    console.log(`Request took: ${Date.now() - startTime}ms`);
  },
};
proxy.ts
const globalMiddlewares = {
  after: [
    async (request, event) => {
      // First after middleware
    },
    async (request, event) => {
      // Second after middleware
    }
  ]
};
middleware.ts
const globalMiddlewares = {
  after: async (request, event) => {
    const startTime = event.storage.get("startTime");
    console.log(`Request took: ${Date.now() - startTime}ms`);
  },
};
middleware.ts
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

proxy.ts
import { type NemoConfig } from "@rescale/nemo";

const  = {
  : true,
  : true,
  : true,
  : (, ) => {
    .(, );
  },
} satisfies NemoConfig;
middleware.ts
import { type NemoConfig } from "@rescale/nemo";

const  = {
  : true,
  : true,
  : true,
  : (, ) => {
    .(, );
  },
} 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.

proxy.ts
import {
  ,
  type ,
  type ,
  type NemoConfig,
} from "@rescale/nemo";

const  = {
  "/:path*": async () => {
    // middleware functions for /api route
  },
} satisfies ;

const  = {
  : async () => {
    // global middleware function that will be executed before any route middleware
  },
  : async () => {
    // global middleware function that will be executed after any route middleware
  },
} satisfies ;

const  = {
  : true, // default is false
  : true, // default is false
  : true, // default is false
  : (, ) => {
    // custom error handler
  },
} satisfies NemoConfig;

export const  = (
  ,
  ,
  ,
);

export const  = {
  : ["/((?!_next/|_static|_vercel|[\\w-]+\\.\\w+).*)"],
};
middleware.ts
import {
  ,
  type ,
  type ,
  type NemoConfig,
} from "@rescale/nemo";

const  = {
  "/:path*": async () => {
    // middleware functions for /api route
  },
} satisfies ;

const  = {
  : async () => {
    // global middleware function that will be executed before any route middleware
  },
  : async () => {
    // global middleware function that will be executed after any route middleware
  },
} satisfies ;

const  = {
  : true, // default is false
  : true, // default is false
  : true, // default is false
  : (, ) => {
    // custom error handler
  },
} satisfies NemoConfig;

export const  = (
  ,
  ,
  ,
);

export const  = {
  : ["/((?!_next/|_static|_vercel|[\\w-]+\\.\\w+).*)"],
};