apps/api/src/routes/ and are registered in the main application entry point.
Elysia Route Anatomy
Every route in BunShip follows the same structure: an HTTP method, a path, a handler function, and an options object for validation and documentation.Handler Context
Elysia injects context into every handler. The available properties depend on which middleware is applied:| Property | Source | Description |
|---|---|---|
body | Request body | Parsed and validated request body |
query | Query string | Parsed query parameters |
params | URL path | Path parameters (e.g., :orgId) |
set | Elysia | Response control (status, headers, redirect) |
request | Elysia | Raw Request object |
user | authMiddleware | Authenticated user with id, email, sessionId |
organization | organizationMiddleware | Current organization record |
membership | organizationMiddleware | User’s membership in the org |
Adding a New Resource
This walkthrough creates a complete CRUD resource: widgets scoped to an organization. By the end, you will have list, create, get, update, and delete endpoints.Step 1: Create Validation Schemas
Define your request and response schemas in a separate file. BunShip uses TypeBox (Elysia’s built-in validation) for compile-time type safety and automatic OpenAPI documentation.Step 2: Create the Route File
Step 3: Register the Route
Add your route module to the main application inapps/api/src/index.ts:
GET /api/v1/organizations/:orgId/widgetsPOST /api/v1/organizations/:orgId/widgetsGET /api/v1/organizations/:orgId/widgets/:widgetIdPATCH /api/v1/organizations/:orgId/widgets/:widgetIdDELETE /api/v1/organizations/:orgId/widgets/:widgetId
Route Groups and Prefixes
Elysia supports nesting routes with prefixes. BunShip uses this pattern for organization-scoped resources.Top-Level Routes
Routes that do not belong to an organization (like auth or user profile):Organization-Scoped Routes
Resources that belong to an organization use the:orgId parameter:
Nested Sub-Routes
Mount related routes as sub-routes using.use():
Middleware
BunShip provides three middleware layers that you apply to routes as needed.Authentication Middleware
Verifies the JWT access token and injectsuser into the handler context:
Organization Middleware
Loads the organization from the:orgId parameter and verifies the user is a member. Injects organization and membership into context:
Permission Middleware
Checks that the user’s role grants a specific permission:Middleware order matters. Always apply
authMiddleware before organizationMiddleware, and
organizationMiddleware before permission checks.OpenAPI Documentation
Elysia generates OpenAPI (Swagger) documentation automatically from your route definitions. BunShip serves this at/docs by default.
Adding Documentation to Routes
Use thedetail property to describe your endpoints:
Tags
Tags group related endpoints in the Swagger UI. Use consistent tag names across your route files:TypeBox Validation Schemas
Elysia uses TypeBox for request validation and OpenAPI type generation. Here are the patterns used throughout BunShip.Common Schema Patterns
Adding Examples for API Docs
TypeBoxexamples show up in the Swagger UI as sample values:

