Getting Started with Bun
This guide walks you through building a Zelt application on Bun from scratch.
Prerequisites
Installation
bun add @zeltjs/core @zeltjs/adapter-bun
Project Structure
my-app/
├── src/
│ ├── entry/
│ │ ├── controllers/ # HTTP endpoints
│ │ └── commands/ # CLI commands
│ ├── services/ # Business logic
│ ├── configs/ # Configuration classes
│ ├── app.ts # Application definition
│ ├── cli.ts # CLI entry point
│ └── main.ts # HTTP server entry point
├── package.json
└── tsconfig.json
| Directory | Purpose |
|---|---|
entry/ | External entry points (HTTP, CLI) |
services/ | Business logic, injected via DI |
configs/ | Environment variables and settings |
Hello World
Step 1: Create the Controller
Create src/entry/controllers/hello.controller.ts:
@Controller('/hello')
export class HelloController {
@Get('/:name')
greet(name = pathParam('name')) {
return { message: `Hello, ${name}!` };
}
}
Step 2: Create the Application
Create src/app.ts:
export const app = createApp([http({
controllers: [HelloController],
})]);
Step 3: Create the Entry Point
Create src/index.ts:
const bunApp = await onBun(app);
const server = bunApp.serve({ port: 3000 });
console.log(`Server running at http://${server.address.hostname}:${server.address.port}`);
The onBun() function prepares your app for the Bun runtime. It returns an object with:
serve(options?)— Starts an HTTP server usingBun.serve()shutdown()— Gracefully shuts down the applicationget<T>(Class)— Resolves a service from the DI containerargs— Command-line arguments (Bun.argv.slice(2))
Step 4: Run the Server
bun run src/index.ts
Visit http://localhost:3000/hello/world to see:
{ "message": "Hello, world!" }
Server Options
The serve() method accepts options for port and hostname:
const server = bunApp.serve({
port: 8080,
hostname: '127.0.0.1',
});
| Option | Default | Description |
|---|---|---|
port | 3000 | Port to listen on |
hostname | '0.0.0.0' | Hostname to bind to |
Command Support
If your app includes commands, onBun() keeps command capabilities under the commands namespace for CLI execution:
const bunApp = await onBun(app);
const result = await bunApp.commands.execCommand(['greet', 'world']);
console.log(result.exitCode); // 0 or 1
Warmup Option
By default, onBun() uses eager initialization (warmup: true) — all controllers are resolved at startup.
For lazy initialization (controllers resolved on first request):
const bunApp = await onBun(app, { warmup: false });
| Option | Behavior | Use Case |
|---|---|---|
warmup: true (default) | All controllers resolved at startup | Long-running servers |
warmup: false | Controllers resolved on first request | Optimized cold starts |
What's Next?
- Controllers — Route handling and HTTP methods
- Services — Business logic and dependency injection
- Commands — CLI commands