Katal¶
A simple yet powerful web framework for Bun with TypeScript, inspired by Laravel and Express.
Why Katal?¶
Katal is built from the ground up for the Bun runtime. It embraces the controller-per-route pattern, brings first-class TypeScript support, and ships every feature you need in a modern HTTP API — without forcing you to install a dozen third-party packages.
Feature Overview¶
| Category | What you get |
|---|---|
| HTTP | Controller-per-route, route groups, path params, query/body parsing |
| Middleware | Global + named middleware, before / after hooks, short-circuit support |
| Validation | Schema-based field validation, nested objects, custom rules |
| Auth | JWT sign/verify, createAuthMiddleware, optional auth |
| Authorization | Policy-based gate middleware (can:<policy>) |
| Rate Limiting | Sliding-window limiter, pluggable store, response headers |
| Logging | Structured log levels, console + file destinations, custom sinks |
| Observability | Correlation IDs, W3C traceparent propagation, structured access logs |
| Cache | cacheGet/cacheSet/cacheRemember, pluggable CacheStore |
| Queue | In-memory by default, retry/backoff, delayed jobs, scheduler, BYO adapter |
| Events | Typed async/sync event bus (on, once, emit, emitSync) |
| Health Checks | /health, /health/ready, /health/live endpoints out of the box |
| OpenAPI | Auto-generate OpenAPI 3.1 from route + schema definitions |
| Config | Typed config from source objects or environment variables |
| DI Container | IoC container with singleton/transient/instance bindings |
| Plugins | Lifecycle hooks: onRegister, onBoot, onReady, onClose |
| Service Providers | Laravel-style register() / boot() composition |
| Testing Kit | AppFactory, RequestClient, FakeClock, createTestToken |
Installation¶
bun add katal
Katal requires Bun ≥ 1.0. It has no production dependencies beyond Bun itself.
Quick Start¶
import { Application, Controller } from "katal";
import type { RequestContext } from "katal";
// 1. Create the app
const app = new Application({ port: 3000 });
const router = app.getRouter();
// 2. Define a controller
class HelloController extends Controller {
async handle(ctx: RequestContext) {
return this.success({ message: `Hello, ${ctx.query.name ?? "world"}!` });
}
}
// 3. Register a route
router.get("/hello", HelloController);
// 4. Start the server
await app.listen();
Run it:
bun run app.ts
# Listening on http://localhost:3000
Documentation Map¶
| Topic | Guide |
|---|---|
| Application setup, routing, DI | Core |
| Controllers, helpers, Problem Details | HTTP |
| Global and named middleware | Middleware |
| Schema validation | Validation |
| JWT auth | Authentication |
| Policy-based gates | Authorization |
| Rate limiting | Rate Limiting |
| Structured logging | Logging |
| Correlation IDs + trace context | Observability |
| Cache abstraction | Cache |
| Queue, retry, scheduling | Queue |
| Event bus | Events |
| Health endpoints | Health Checks |
| OpenAPI generation | OpenAPI |
| Typed config from env | Config |
| Framework plugins | Plugins |
| Service providers | Service Providers |
| Test helpers | Testing |
Examples¶
Working examples:
- Simple App — minimal app with auth, CORS, and rate limiting
- Custom Base Controllers — shared base controller pattern
- Middleware Hooks —
before/aftermiddleware lifecycle