Get Started

Set up Legonode, create a project, and run your first API in minutes.

Get Started

This guide walks you through installing Legonode, creating a new project, and running your first API.


Prerequisites

  • Node.js 18+ or Bun 1.0+
  • TypeScript (recommended)
  • A terminal and editor

Add to an existing project

bun add legonode
npm install legonode

Then add an appDir (default ./src) directory with a router/ folder for routes and middleware (routes from appDir/router/**, middleware from appDir/router/**/middleware.ts).


Project structure

A minimal Legonode project looks like this:

legonode.config.ts
package.json
  • router/ — Route files and router/**/middleware.ts live here. File paths map to URL paths.
  • legonode.config.ts — Optional: port, host, CORS, logging, and plugins.

Your first route

Create src/router/route.ts:

src/router/route.ts
import type { Context } from "legonode";

export async function GET(ctx: Context) {
  ctx.res.status(200);
  return { message: "hello test" };
}

This handles GET / and returns JSON.

Add another route at src/router/api/hello/route.ts:

src/router/api/hello/route.ts
import type { Context } from "legonode";

export async function GET(ctx: Context) {
  ctx.res.status(200);
  return { hello: "world" };
}

This handles GET /api/hello.


Run the dev server

From the project root:

bun run dev
npm run dev
legonode dev

By default the server runs at http://localhost:3000.

Use -p to change the port and -H to change the host:

legonode dev -p 4000 -H 0.0.0.0

Add Validation

with Legonode

Validate the request body and get type-safe input:

src/router/api/users/route.ts
import type { Context, RouteSchema } from "legonode";
import { z } from "zod";

export const SCHEMA: RouteSchema = {
  body: { name: "string", email: "string", age: "number?" },
};

export default async function POST(ctx: Context) {
  const body = ctx.body;
  const user = { id: "1", ...body };

  ctx.emit("user.created.email", user);

  ctx.res.status(201).json(user);
}

with Zod

src/router/api/users/route.ts
import type { Context, RouteSchema } from "legonode";
import { z } from "zod";

export const SCHEMA: RouteSchema = {
  body: z.object({
    name: z.string(),
    email: z.string(),
    age: z.number().optional(),
  }),
};

export default async function POST(ctx: Context) {
  const body = ctx.body;
  const user = { id: "1", ...body };

  ctx.emit("user.created.email", user);

  ctx.res.status(201).json(user);
}

Invalid bodies are rejected with a 400 and validation errors.


Build for production

legonode build
legonode start

Add scripts to package.json:

package.json
{
  "scripts": {
    "dev": "legonode dev",
    "build": "legonode build",
    "start": "legonode start"
  }
}

Next steps

  • Routing — File-based routes, dynamic segments, and method handlers.
  • Middleware — CORS, logging, and custom middleware order.
  • Validation — Request/response schemas and error handling.
  • CLI reference — All legonode dev, build, and start options.

Use the sidebar or search (⌘K) to find these topics.