Introduction

Manual Install

How to manually configure a mion app.

Installing the Router

npm i @mionjs/core @mionjs/router
npm i -D @mionjs/devtools

Installing a Platform

Install the package for where you run mion. For local development use Node or Bun.

npm install @mionjs/platform-node

Writing the API

Create the router once with createMionRouter (router options go there), declare the routes with its helpers and register them with initRoutes.

import {FatalError} from '@mionjs/core';
import {createMionRouter, Routes} from '@mionjs/router';

export type User = {id: string; name: string; surname: string};

// every helper below gets these options by type
const mion = createMionRouter({basePath: 'api/v1'});

// parameters are validated before each function runs
const routes = {
  // reads the HttpOnly session cookie the browser sends
  auth: mion.middleware((ctx): void | FatalError<'not-authorized'> => {
    const cookie = ctx.request.headers.get('cookie');
    // a FatalError ends the request: sayHello never runs, and the client gets it typed
    if (!cookie?.includes('session='))
      return new FatalError({
        publicMessage: 'Not Authorized',
        type: 'not-authorized',
      });
  }),
  users: {
    sayHello: mion.route(
      (ctx, user: User): string => `Hello ${user.name} ${user.surname}`
    ),
  },
  log: mion.middleware(
    (ctx): void => console.log(Date.now(), ctx.path, ctx.response.statusCode),
    {alwaysRun: true}
  ),
} satisfies Routes;

export const myApi = mion.initRoutes(routes);

// the client imports only this type
export type MyApi = typeof myApi;

Starting the Server

Write a start script for your platform.

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

const nodeOptions: Partial<NodeHttpOptions> = {port: 3000};
startNodeServer(nodeOptions);



Client Setup

npm install @mionjs/client

Import only the type of your API, so no server code is imported.

import {initClient} from '@mionjs/client';
import type {MyApi} from './myApi.routes.ts';

const john = {id: '123', name: 'John', surname: 'Doe'};
const {routes} = initClient<MyApi>({
  baseURL: 'http://localhost:3000',
});

const [hello] = await routes.users.sayHello(john).call();
console.log(hello); // Hello John Doe

// checks params locally, without calling the server
const [_, error] = await routes.users.sayHello(john).typeErrors();
console.log(error); // {hasErrors: false, totalErrors: 0, errors: []}
The mion Vite plugin compiles every route's validation and JSON round trip functions at build time, for faster startup. To deploy where runtime new Function() is blocked, set emitMode: 'both'.
Copyright © 2026