Brazier

Brazier is an alpha full-stack Gleam framework for building MVU web apps on the BEAM, published on Hex as brazier (gleam add brazier). It was named Beacon until 2026-11-04 and was renamed because another package holds that name on Hex; see CHANGELOG.md.

How a page works:

Minimal App

import brazier
import brazier/config
import brazier/element.{type Element}
import brazier/event
import brazier/html
import gleam/int

pub type Model {
  Model(count: Int)
}

pub type Msg {
  Increment
}

fn init(_ctx: brazier.Context) -> Result(Model, brazier.InitError) {
  Ok(Model(count: 0))
}

pub fn update(model: Model, msg: Msg) -> Model {
  case msg {
    Increment -> Model(count: model.count + 1)
  }
}

pub fn view(model: Model) -> Element(Msg) {
  html.button([event.on_click(Increment)], [
    html.text("Count: " <> int.to_string(model.count)),
  ])
}

pub fn main() {
  let assert Ok(secret_key) = config.secret_key()
    as "SECRET_KEY must be set to a private key of at least 32 bytes (config.secret_key logs why it was refused)"
  let assert Ok(Nil) =
    brazier.simple(init:, update:, view:)
    |> brazier.secret_key(secret_key)
    |> brazier.start(8080)
    as "brazier.start failed (it logs the error)"
}

Every app needs a secret key of at least 32 bytes. It signs session and join tokens and keys the cluster peer check. brazier.start refuses an app without one and names the setting, and there is no generated default. config.secret_key() reads it from SECRET_KEY.

An app needs two generated artifacts before it starts: the server codec (src/brazier_codec.gleam) and the client bundle (priv/static/). Generate them with gleam run -m brazier/build, then gleam run; or use gleam run -m brazier/dev, which builds, runs and rebuilds on change. brazier.start logs and returns an error when either artifact is missing, and main crashes on it, so gleam run exits with status 1 and says what to run. The examples do not track their generated files, so build one before its first run. To run the counter example from this repository:

cd examples/counter
export SECRET_KEY="$(openssl rand -base64 48)"   # once per shell
gleam run -m brazier/build   # first, and after every change
gleam run

Keep the same SECRET_KEY across restarts: a new key invalidates every signed token, so open tabs lose their session.

Getting Started walks through a full app.

Recommended APIs

Requirements

Development

In the repository root (the framework itself has no main; run an app from examples/):

gleam build                  # zero warnings
gleam format --check src test
gleam run -m brazier/lint     # 0 violations
gleam test
scripts/check_docs.sh        # doc samples compile, doc links resolve

All of them must pass before a change is done.

Project Docs

License

MIT; see LICENSE.

✨ Search Document