Chronicles

Toucan v0.1.0

release

Toucan v0.1.0 is the first public release of the framework. The goal is small and practical: make Donna comfortable for building HTTP APIs, server-rendered pages, and real-time browser apps without hiding the request pipeline behind macros or a registration DSL.

Why Toucan exists

Toucan routes are just functions. A Ctx flows through method filters, path matchers, middleware, and response terminals with Donna's |> operator. A route that does not match returns Rejected; toucan.try restores the active request so the next route can attempt a match.

That keeps the model explicit:

code
fn router(c: toucan.Ctx) -> toucan.Ctx:
  c
  |> toucan.try(home)
  |> toucan.try(api)
  |> toucan.not_found

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

What's Included

Pipeline routing — Routes are function chains built with |>. Method filters, path matchers, and response terminals are all plain functions.

URL parameters — Define :name segments in path patterns. Read captures with toucan.param(c, "name").

Request dataform_field, query_param, header_of, content_type_of, and body_of cover common request handling.

Responseshtml, json, ok, created, no_content, redirect, and respond for full control over status and content type. Chain set_header to add arbitrary headers.

Static filesstatic_dir maps paths to a directory and returns Rejected on miss so subsequent handlers still run.

Securitycors, csp, and secure_headers add the standard defensive headers with a single call. Applied automatically on every response by serve.

Loggingserve_logged and serve_with_logged print coloured request lines. Pass logger.Silent for production.

WebSocketsserve_ws for echo and send-to-client use cases. serve_chat for broadcast — automatically sends each new client its connection ID, then broadcasts the handler's reply to all connected clients.

Shared stateserve_with, serve_with_logged, serve_with_chat, and try_with thread any state value through the handler pipeline without global variables.

Sessionstoucan/session provides a simple in-memory session store, cookie helpers, and the pieces needed for login flows and named chat users.

Examples

The release now ships with runnable examples under examples/. Every example uses port 8000 so you can start one, test it, stop it, and move to the next:

code
cd examples/basic
donna run

Included examples:

  • basic — a minimal route and form handler
  • todo_sqlite — server-rendered todos backed by SQLite
  • todo_json_api — REST-style JSON todos
  • auth_login — registration, login, protected pages, and sessions
  • file_upload — text uploads and image previews with binary image writes
  • url_shortener — random slugs, SQLite storage, and redirects
  • htmx_todos — partial HTML updates with htmx
  • chat_sessions — WebSocket chat with session-backed display names

These examples are intentionally small, but they exercise the framework surface: forms, static assets, template rendering, local state, sessions, SQLite, uploads, redirects, JSON responses, and WebSocket broadcasts.

Notes

Toucan is still a first release. The APIs are intentionally compact, and the examples favor clarity over production hardening. For example, auth_login uses a demo password hash, and file_upload keeps image uploads bounded so the current Donna string/runtime path stays stable.

Getting started

Add Toucan to your donna.toml:

code
toucan = { git = "https://github.com/NikolasSkyl/toucan", version = ">=0.1.0 and <1.0.0" }

Then read the Getting Started guide.