Getting Started

Quick Start

Build your first IOServer application in minutes.

Quick Start

This guide walks you through creating a minimal IOServer application with one service (WebSocket), one controller (HTTP), one manager (shared state), and one watcher (background task).

The full source lives at examples/simple.ts in the repository.

1. Create the entry point

// src/index.ts
import {
  IOServer,
  BaseService,
  BaseController,
  BaseManager,
  BaseWatcher,
} from "ioserver";

// ─── Manager ─────────────────────────────────────────────────────────────────

class CounterManager extends BaseManager {
  private counter: number = 0;

  increment(): number {
    return ++this.counter;
  }

  getCount(): number {
    return this.counter;
  }
}

// ─── Watcher ──────────────────────────────────────────────────────────────────

class HealthWatcher extends BaseWatcher {
  private intervalId: ReturnType<typeof setInterval> | null = null;

  async watch(): Promise<void> {
    this.intervalId = setInterval(() => {
      this.appHandle.log(6, "Health watcher tick");
    }, 30_000);
  }

  stop(): void {
    if (this.intervalId !== null) {
      clearInterval(this.intervalId);
      this.intervalId = null;
    }
  }
}

// ─── Service (WebSocket) ──────────────────────────────────────────────────────

class HelloService extends BaseService {
  async hello(socket: any, data: any, callback?: Function): Promise<void> {
    // Access the manager via AppHandle
    const count = this.appHandle.counterManager.increment();
    this.appHandle.log(6, `Hello #${count} received`);

    socket.emit("hello_response", {
      message: "Hello from IOServer!",
      count,
      timestamp: Date.now(),
    });

    if (callback) {
      callback({ status: "success" });
    }
  }
}

// ─── Controller (HTTP) ────────────────────────────────────────────────────────

class ApiController extends BaseController {
  async getStatus(request: any, reply: any): Promise<void> {
    reply.send({
      status: "OK",
      count: this.appHandle.counterManager.getCount(),
      timestamp: new Date().toISOString(),
    });
  }
}

// ─── Bootstrap ────────────────────────────────────────────────────────────────

const server = new IOServer({
  host: "localhost",
  port: 8080,
  verbose: "DEBUG",
  routes: "./routes",
  cors: {
    origin: ["http://localhost:8080"],
    methods: ["GET", "POST"],
  },
});

// Managers must be registered first — they are immediately available
// in appHandle for all components registered afterwards.
server.addManager({ name: "counterManager", manager: CounterManager });
server.addWatcher({ name: "healthWatcher", watcher: HealthWatcher });
server.addService({ name: "hello", service: HelloService });
server.addController({ name: "api", controller: ApiController });

server.start().then(() => {
  console.log("Server started on http://localhost:8080");
});

2. Create the route file

HTTP routes for controllers are declared in JSON files inside the routes/ directory. The file name must match the controller name:

// routes/api.json
[
  { "method": "GET", "url": "/status", "handler": "getStatus" }
]

With the default prefix logic, GET /status in api.json is registered as GET /api/status.

3. Run it

npx ts-node src/index.ts

4. Connect

HTTP endpoint:

curl http://localhost:8080/api/status
# → { "status": "OK", "count": 0, "timestamp": "..." }

WebSocket (browser console):

const socket = io("http://localhost:8080/hello");

socket.emit("hello", { name: "world" }, (response) => {
  console.log(response); // { status: "success" }
});

socket.on("hello_response", (data) => {
  console.log(data); // { message: "Hello from IOServer!", count: 1, ... }
});

What just happened?

StepWhat IOServer did
addManager(counterManager)Instantiated CounterManager, added it to appHandle.counterManager
addWatcher(healthWatcher)Registered the watcher; watch() is called at server.start()
addService(hello)Registered the service on namespace /hello; all public methods auto-become Socket.IO event handlers
addController(api)Read routes/api.json, bound getStatus to GET /api/status in Fastify

Next steps

Copyright © 2026