Open source & MIT licensed

The micro webframework
for Donna.

Toucan is a micro webframework for Donna. Chain handlers with |>, match routes, send responses. No magic — just functions.

# add toucan to donna.toml
$ donna new my-app && cd my-app

# write a handler and serve
$ donna run
Toucan listening on:  http://localhost:8080

Everything a handler needs.
Nothing it doesn't.

Toucan stays small so your code stays clear.

Pipeline routing

Compose routes with |>. Method filters, path matchers, and responses are all plain functions.

Zero magic

Handlers are fn(Ctx) -> Ctx. No decorators, no macros, no hidden wiring anywhere.

WebSocket ready

Use serve_ws for echo servers or serve_chat to broadcast to every connected client.

URL parameters

Define :name segments in your path pattern. Read captures with toucan.param(c, "name").

Security defaults

CORS, CSP, X-Frame-Options, and Referrer-Policy added with a single function call.

Native speed

Compiles to a native binary with Donna. Zero runtime overhead, zero garbage collector pauses.

A route is just a function chain.

Filter by method, match a path, capture parameters, send a response. Every step is composable and testable on its own.

Read the docs →
import toucan

fn handler(c: toucan.Ctx) -> toucan.Ctx:
  c
  |> toucan.try(home)
  |> toucan.try(show_user)
  |> toucan.landing_page
  |> toucan.not_found

fn home(c: toucan.Ctx) -> toucan.Ctx:
  c
  |> toucan.get
  |> toucan.path("/hello")
  |> toucan.html("<h1>Hello!</h1>")

fn show_user(c: toucan.Ctx) -> toucan.Ctx:
  c
  |> toucan.get
  |> toucan.path("/users/:id")
  |> render_user

pub fn main() -> Nil:
  toucan.serve(handler, 8080)