moonapi is a web framework for MoonBit. You describe an application from one object, and every route handler receives a typed context and returns a typed response. The same application generates an OpenAPI document automatically, and runs on a native server or in WebAssembly.
moon add moonbitstack/moonapi
let app = @moonapi.App::new()
app.get("/", _ctx =>
@moonapi.text(200, "Hello from moonapi"))
app.get("/users/{id}", ctx =>
@moonapi.text(200,
"user " + ctx.param("id").unwrap_or("")))
app.post("/users", _ctx =>
@moonapi.text(201, "created"))
// run a request in-process
let response = app.handle({
http_method: "GET", path: "/users/42",
query_string: b"", headers: [], body: b"",
})
response.status // 200
GET /users/42
200 OK
user 42
POST /users
201 Created
created
GET /users/abc/orders
404 Not Found
{"detail":"Not Found"}
DELETE /
405 Method Not Allowed
{"detail":"Method Not Allowed"}
Everything below is part of the public API. The guide walks through each, and the API reference documents every function, method and parameter.
Declare routes with {id} placeholders. The framework matches the path, binds the parameter, and returns the right status when nothing matches — no separate router config.
Read the path, query string, headers and typed JSON body from a single context. Each extractor returns an option you handle inline.
Register shared services once by name and list them on a route with dependencies=[...]. The container resolves each once per request and tears them down in reverse order.
Each route carries a summary and tags. Call one method to emit an OpenAPI 3.1 document you can serve at /openapi.json or hand to a documentation UI.
Declare API keys, bearer tokens, OAuth2 and other schemes. Attach an enforcer per scheme and the framework verifies each request before your handler runs.
Return server-sent events or hold a WebSocket connection alongside ordinary request handling in the same application.
Render HTML templates and serve static assets, mounting them at their own prefixes without leaving the application object.
Compile the same application to a native server or to WebAssembly. The request and response types are identical across both.
The root @moonapi package is where you start. The others are imported by name when you need them.