Platforms

Node.js

Running mion APIs on Node.js using the http module.

Installing the Adapter

npm install @mionjs/platform-node @mionjs/router

Starting the Server

import {startNodeServer} from '@mionjs/platform-node';
import './node-routes.ts';

const server = await startNodeServer({port: 3000});

console.log('Server running at http://localhost:3000');

Adapter Options

Pass options such as maxBodySize to startNodeServer, and set router options like basePath once in createMionRouter. Each route has its own body limit: a content-length over it is refused before reading, and a body that grows past it is refused mid-stream with a 413.

import {startNodeServer} from '@mionjs/platform-node';
import './node-routes.ts';

await startNodeServer({port: 3000});
In production, consider a process manager like PM2 or a reverse proxy like nginx.

Mounting mion in Your Own Server

With asMiddleware, mion sets everything up but never calls listen(). Mount httpRequestHandler wherever you want, in an express/connect app or your own http.createServer. The Vite plugin sets this option to run an unchanged mion.initRoutes(routes); startNodeServer(); entry inside its dev server, without opening a port.

src/middleware.ts
import {createServer} from 'node:http';
import {httpRequestHandler, startNodeServer} from '@mionjs/platform-node';
import {createMionRouter, Routes} from '@mionjs/router';

// the router's basePath must match the prefix the host forwards
const mion = createMionRouter({basePath: 'api'});
const routes = {
  sayHello: mion.route((ctx, name: string): string => `Hello ${name}!`),
} satisfies Routes;
mion.initRoutes(routes);

// registers routes and options but opens no port: the host owns the socket
await startNodeServer({asMiddleware: true});

// here mion handles everything under /api
const host = createServer((req, res) => {
  if (req.url?.startsWith('/api')) return httpRequestHandler(req, res);
  res.statusCode = 404;
  res.end('not found');
});

host.listen(3000);
Copyright © 2026