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 legonodenpm install legonodeThen 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:
router/— Route files androuter/**/middleware.tslive 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:
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:
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 devnpm run devlegonode devBy default the server runs at http://localhost:3000.
- Open http://localhost:3000 — you should see
{"message":"Hello from Legonode!"}. - Open http://localhost:3000/api/hello — you should see
{"hello":"world"}.
Use -p to change the port and -H to change the host:
legonode dev -p 4000 -H 0.0.0.0Add Validation
with Legonode
Validate the request body and get type-safe input:
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
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 startAdd scripts to 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, andstartoptions.
Use the sidebar or search (⌘K) to find these topics.