Lucerna is a lightweight, explicit ASGI web framework for Python inspired by Hono and Koa. It features an Onion Model Middleware Pipeline and centralizes request/response handling around a single Context (c) object.
- Context-Driven Architecture (
c): A single object encapsulating request inspection, response building, application state, and per-request scope. - Onion Model Middleware Pipeline: Flexible middleware execution order using
next_fn()chaining without hidden side effects. - Zero Decorator Magic: Explicit route and middleware pipeline declarations for clear code flow and straightforward debugging.
- Built-in Type Validation: Higher-order
validate(BaseModel)middleware powered by Pydantic for request body validation. - Rich Helper Methods: Built-in support for query parameters, path parameters, duplicate headers, HTML responses, redirects, and error handling.
- Standard ASGI Compliant: Fully compatible with standard ASGI servers such as Uvicorn, Hypercorn, or Granian.
- Python 3.10+
pydantic>=2.13.4uvicorn>=0.52.0
pip install pydantic uvicorn
# or using uv
uv add pydantic uvicornfrom lucerna import Lucerna, Context, logger_middleware, auth_guard
app = Lucerna()
async def public_hello(c: Context):
return c.text("Hello World")
async def secret_dashboard(c: Context):
return c.json({"message": "Welcome to Secret Dashboard!"})
# 1. Apply Logger middleware to root endpoint
app.get("/", logger_middleware, public_hello)
# 2. Chain Logger and Auth Guard middleware before reaching the admin handler
app.get("/admin", logger_middleware, auth_guard("my-secret-key"), secret_dashboard)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)python main.py
# or using uv
uv run main.py| Method / Attribute | Description |
|---|---|
c.req.header(key, default) |
Case-insensitive request header lookup |
c.req.headers_all(key) |
Returns all matching header values (e.g., duplicate Set-Cookie) |
c.req.param(key, default) |
Retrieves path parameter from dynamic routes (e.g., /users/{id}) |
c.req.query(key, default) |
Retrieves query parameter from URL query string |
c.req.json() |
Async method reading and parsing request JSON payload |
c.get(key, default) |
Retrieves state value from request scope or global app state |
c.set(key, val) |
Stores key-value pair in per-request state scope |
c.valid_json() |
Returns validated Pydantic model instance set by validate() |
c.json(data, status=200) |
Returns JSON response |
c.text(data, status=200) |
Returns plain text response |
c.html(data, status=200) |
Returns HTML response |
c.redirect(url, status=302) |
Returns HTTP redirect response |
c.no_content() |
Returns 204 No Content response |
c.error(msg, status=400, details=None) |
Returns structured error response |
logger_middleware: Built-in logger printing method, path, status code, and execution latency.auth_guard(token): Built-in Bearer token authentication guard middleware factory.validate(Schema): Higher-order middleware performing Pydantic schema validation on request body.
app.get(path, *handlers)/app.post(path, *handlers): Registers direct HTTP routes and pipelines.app.mount(prefix, router): Mounts a sub-router instance under the specified path prefix.app.on_error(handler): Registers a global error handler for uncaught pipeline exceptions.