Quickstart

1. Install

gleam add radiant
gleam add mist gleam_erlang  # for the HTTP server

2. Build a router

import gleam/bytes_tree
import gleam/erlang/process
import gleam/http/response
import gleam/int
import mist
import radiant

pub const user_path = "/users/<id:int>"
pub const user_id = radiant.int("id")

pub fn router() -> radiant.Router {
  radiant.new()
  |> radiant.get("/", fn(_req) { radiant.ok("hello") })
  |> radiant.get1(user_path, user_id, fn(_req, id) {
    radiant.json("{\"id\":" <> int.to_string(id) <> "}")
  })
}

pub fn main() {
  let router = router()

  let assert Ok(_) =
    mist.new(fn(req) {
      let resp = radiant.handle(router, req)
      response.set_body(resp, mist.Bytes(bytes_tree.from_bit_array(resp.body)))
    })
    |> mist.port(8080)
    |> mist.start()

  process.sleep_forever()
}

3. Start it with Mist

gleam dev
# → listening on :8080

curl localhost:8080/users/42
# → {"id":42}

curl localhost:8080/users/abc
# → 404  (non-integer segment doesn't match <id:int>)

Runnable examples

The repository includes smaller examples that can be started independently:

gleam run --module basic_example
gleam run --module typed_routes_example
gleam run --module middleware_example
gleam run --module query_example

gleam dev starts the full radiant_dev example. gleam run --module selects one of the focused examples. Each uses a different port (40014004).

Key concepts

get1 / get2 / … get6 — typed routes. Declare a Param(a) constant once; the handler receives the parsed value directly as the correct type. No let assert, no int.parse.

Param constants — define at module level and reuse for routing, URL building, and testing:

pub const org_id  = radiant.int("org_id")
pub const proj_id = radiant.int("proj_id")

router
|> radiant.get2("/orgs/<org_id:int>/projects/<proj_id:int>", org_id, proj_id,
  fn(_req, oid, pid) { ... })

// Build the URL later — same constants, no raw strings
radiant.path_for2("/orgs/<org_id:int>/projects/<proj_id:int>", org_id, 7, proj_id, 3)
// → Ok("/orgs/7/projects/3")

Middleware — use middleware for cross-cutting concerns:

radiant.new()
|> radiant.middleware(radiant.cors(radiant.default_cors()))
|> radiant.middleware(radiant.log(io.println))
|> radiant.get("/", handler)

Use radiant.wrap(middleware, handler) when only one route needs it.

Next: Basic usage | Routing reference | Errors and migration

Search Document