Skip to main content

Quick Start

Get up and running with Balda.js in minutes. This guide will walk you through creating a simple REST API.

Create Your First Server

Create a new file called server.ts:

import { Server, controller, get, post } from 'balda-js';

// Create a new server instance
const server = new Server({
port: 3000,
host: 'localhost',
plugins: {
cors: { origin: '*' },
json: { sizeLimit: '1mb' }
}
});

// Define a controller
@controller('/users')
export class UsersController {
private users = [
{ id: 1, name: 'John Doe', email: 'john@example.com' },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com' }
];

@get('/')
async getAllUsers(req, res) {
res.json(this.users);
}

@get('/:id')
async getUserById(req, res) {
const id = parseInt(req.params.id);
const user = this.users.find(u => u.id === id);

if (!user) {
return res.notFound({ error: 'User not found' });
}

res.json(user);
}

@post('/')
async createUser(req, res) {
const newUser = {
id: this.users.length + 1,
...req.body
};

this.users.push(newUser);
res.created(newUser);
}
}

// Start the server
server.listen(({ port, host }) => {
console.log(`Server running on http://${host}:${port}`);
});

Run Your Server

# Node.js
npx tsx server.ts

# Bun
bun run server.ts

# Deno
deno run --allow-net server.ts

Test Your API

Use curl or any HTTP client to test your endpoints:

# Get all users
curl http://localhost:3000/users

# Get user by ID
curl http://localhost:3000/users/1

# Create a new user
curl -X POST http://localhost:3000/users \
-H "Content-Type: application/json" \
-d '{"name": "Bob Wilson", "email": "bob@example.com"}'

Add Validation

Enhance your API with request validation:

import { Server, controller, get, post, validate } from 'balda-js';
import z from 'zod';

const CreateUserSchema = z.object({
name: z.string().min(1),
email: z.string().email()
});

@controller('/users')
export class UsersController {
// ... existing code ...

@post('/')
@validate.body(CreateUserSchema)
async createUser(req: Request, res: Response, body: z.infer<typeof CreateUserSchema>) {
const newUser = {
id: this.users.length + 1,
...body
};

this.users.push(newUser);
res.created(newUser);
}
}

Add Response Serialization

Define response schemas for better API documentation:

import { serialize } from 'balda-js';
import z from 'zod';

const UserSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string()
});

@controller('/users')
export class UsersController {
@get('/')
@serialize(z.array(UserSchema))
async getAllUsers(req, res) {
res.json(this.users);
}

@get('/:id')
@serialize(UserSchema)
async getUserById(req, res) {
// ... existing code ...
}
}

Add Middleware

Use middleware for cross-cutting concerns:

import { middleware, Request, Response } from 'balda-js';

// Custom middleware
const logger = (req: Request, res: Response, next: () => void) => {
console.log(`${req.method} ${req.url} - ${new Date().toISOString()}`);
await next();
console.log(`${res} ${req.url} - ${new Date().toISOString()}`);
};

@controller('/users')
@middleware(logger)
export class UsersController {
// All routes in this controller will use the logger middleware
}

Complete Example

Here's a complete example with all the features:

import {
Server,
controller,
get,
post,
validate,
serialize,
middleware
} from 'balda-js';
import z from 'zod';

const server = new Server({
port: 3000,
plugins: {
cors: { origin: '*' },
json: { sizeLimit: '1mb' },
log: { logResponse: true }
}
});

const UserSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string()
});

const CreateUserSchema = z.object({
name: z.string().min(1),
email: z.string().email()
});

const logger = (req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
};

@controller('/users')
@middleware(logger)
export class UsersController {
private users = [
{ id: 1, name: 'John Doe', email: 'john@example.com' },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com' }
];

@get('/')
@serialize(z.array(UserSchema))
async getAllUsers(req, res) {
res.json(this.users);
}

@get('/:id')
@serialize(UserSchema)
async getUserById(req, res) {
const id = parseInt(req.params.id);
const user = this.users.find(u => u.id === id);

if (!user) {
return res.notFound({ error: 'User not found' });
}

res.json(user);
}

@post('/')
@validate.body(CreateUserSchema)
@serialize(UserSchema)
async createUser(req, res, body) {
const newUser = {
id: this.users.length + 1,
...body
};

this.users.push(newUser);
res.created(newUser);
}
}

server.listen(({ port, host }) => {
console.log(`🚀 Server running on http://${host}:${port}`);
console.log(`📚 API Documentation: http://${host}:${port}/docs`);
});

What's Next?