Migrate

From Express

Map Express req/res/next and app.use() patterns to NextRush's ctx and onion-model middleware.

Most of what you know from Express transfers directly — routes, middleware, and error handling all exist in NextRush. The biggest change is that req and res merge into a single ctx object, and middleware runs as an onion (before-and-after in one function) instead of a linear chain.

Concept Mapping

Express → NextRush

PropertyTypeDescription
req + res + nextctxA single context object carries everything — no third next() parameter to thread through.
app.get(path, handler)router.get(path, handler)Routes are registered on a Router, mounted onto the app.
app.use(middleware)app.use(middleware)Same call shape; the middleware signature changes.
req.paramsctx.paramsSame shape.
req.queryctx.querySame shape.
req.bodyctx.bodyPopulated by @nextrush/body-parser, not automatic.
res.json(data)ctx.json(data)Same behavior.
res.status(code)ctx.status = codeA property assignment, not a method call.
res.redirect(url)ctx.redirect(url)Same behavior.
next(err)throw new HttpError(...)Throw a typed error instead of calling next with one.

Before / After

import express from 'express';

const app = express();
app.use(express.json());

app.get('/users/:id', (req, res) => {
  const user = findUser(req.params.id);
  if (!user) {
    return res.status(404).json({ error: 'Not found' });
  }
  res.json(user);
});

app.listen(8080);
import { createApp, createRouter, listen } from 'nextrush';
import { bodyParser } from '@nextrush/body-parser';
import { NotFoundError } from 'nextrush';

const app = createApp();
app.use(bodyParser());

const users = createRouter();
users.get('/:id', (ctx) => {
  const user = findUser(ctx.params.id);
  if (!user) throw new NotFoundError('Not found');
  ctx.json(user);
});
app.route('/users', users);

listen(app, 8080);

createApp, createRouter, and listen all come from the nextrush meta package — see the Quick Start if you haven't installed it yet. bodyParser is a separate install (@nextrush/body-parser), same as Express's body-parser used to be before express.json() was folded in.

Middleware: linear chain vs. onion

Express middleware runs once, forward. NextRush middleware wraps the rest of the chain, so "before" and "after" logic live in the same function:

// Express — needs a 'finish' event to run code after the response
app.use((req, res, next) => {
  const start = Date.now();
  res.on('finish', () => {
    console.log(`${req.method} ${req.url} ${Date.now() - start}ms`);
  });
  next();
});
// NextRush — before and after in one function
app.use(async (ctx, next) => {
  const start = Date.now();
  await next();
  console.log(`${ctx.method} ${ctx.path} ${Date.now() - start}ms`);
});

NextRush's Middleware type accepts both the modern async (ctx) => { await ctx.next(); } form and this traditional async (ctx, next) => { await next(); } form — pick whichever reads more naturally for a given handler.

Error handling

Express error middleware must be last-registered and take exactly four parameters. NextRush throws typed error classes and reads the status code off the error itself:

import { NotFoundError, BadRequestError } from 'nextrush';

router.get('/users/:id', (ctx) => {
  const user = findUser(ctx.params.id);
  if (!user) throw new NotFoundError('User not found');
  ctx.json(user);
});

// Optional: a custom handler for anything not already an HttpError
app.setErrorHandler((error, ctx) => {
  ctx.status = 500;
  ctx.json({ error: 'Internal error' });
});

NotFoundError, BadRequestError, and the rest of the HTTP error hierarchy come from @nextrush/errors and are re-exported by nextrush — see the error handling reference for the full list.

Common middleware translation

Express package → NextRush package

PropertyTypeDescription
cors@nextrush/corsIncluded in the nextrush meta package.
helmet@nextrush/helmetIncluded in the nextrush meta package.
body-parser / express.json()@nextrush/body-parserSeparate install — not automatic.
express-rate-limit@nextrush/rate-limitSeparate install.
cookie-parser@nextrush/cookiesSeparate install.
compression@nextrush/compressionSeparate install.
serve-static@nextrush/staticSeparate install.

No built-in session middleware

NextRush has no equivalent to express-session. Use @nextrush/cookies plus your own session store, or a stateless approach (JWT) via a custom middleware.

Next steps

  • Middleware — the onion model, in depth.
  • Context — everything ctx carries.
  • Routing — routers, mounting, and route parameters.
Was this helpful?

On this page