Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Anza Engine: Rust Reference

The Rust engine (crate anza) renders server-templated UI (STUI) from plain .html files: full HTML pages for the first load, and JSON envelopes ({ v: 2, slot, ts, html, sig?, css? }) for fragments, fetches and SSE/WebSocket pushes. Envelopes can be signed with HMAC-SHA256 or Ed25519 over the v2 signature message, and checked with anza::verify_envelope. The behaviour is shared with the TypeScript and Python engines (see the Engine Contract).

┌─────────────────┐   Full page (HTML, open DSD)            ┌─────────────────┐
│   Rust server   ├────────────────────────────────────────►│     Browser     │
│  (crate `anza`) │   Envelopes over fetch / SSE / WS       │ (custom elements│
│                 ├────────────────────────────────────────►│  + your code)   │
└─────────────────┘   { v, slot, ts, html, sig? }           └─────────────────┘

The CLI is a different crate: anza-cli (its binary is anza). These docs cover only the engine crate anza.

Key points

  1. Small core. default = [] in Cargo.toml: no web framework and no async runtime unless you enable the axum, actix or watch features.
  2. Parse once. Setup::run() reads every .html file under the root and splits it into static byte chunks and {{name}} placeholders. Rendering only copies chunks and parameter values into one pre-sized buffer.
  3. Placeholders only. The syntax is {{name}} (value) and {{{name}}} (raw). There are no loops, conditionals, filters or includes. By default values are inserted without HTML escaping: escape anything that comes from users with anza::escape_html, or set setup.escape = true so that {{name}} is escaped (see Rendering Pipeline).
  4. Two outputs. Page returns a Document (full HTML). Fragment and Stream return an Envelope.
  5. Signing. SignMode::Hmac and SignMode::Ed25519 add a hex sig to every envelope. Keys are validated in Setup::run(). anza::verify_envelope checks received envelopes on a server or edge. The browser library does not verify signatures for you (see Cryptographic Verification).
  6. Errors. anza::Error has the variants Validation, NotFound, Template, Crypto and Internal. They display as [Anza:CODE] message, and Error::code() returns the code (NOT_FOUND, …).

Quick example

[dependencies]
anza = "0.6"
serde_json = "1"
use anza::{Fragment, Page, Setup};

fn main() -> Result<(), Box<dyn std::error::Error>> {
  // 1. Load and parse ./templates once.
  let mut setup = Setup::new("templates");
  setup.signing = Setup::hmac(b"super-secret-origin-key-32-bytes");
  let engine = setup.run()?;

  // 2. Full page: templates/pages/home.html inside templates/layout/shell.html.
  let doc = Page::new("/").param("title", "Home Page").run(&engine)?;
  println!("{}", doc.html);

  // 3. Signed fragment envelope from templates/feed/card.html.
  let env = Fragment::new("feed/card.html", "main")
    .param("title", "Real-Time Update")
    .param("author", "Alex")
    .run(&engine)?;
  println!("{}", serde_json::to_string_pretty(&env)?);

  Ok(())
}

Root exports

anza::{Setup, Page, Fragment, Stream, Engine, SignMode, Params, Data, escape_html, verify_envelope, VerifyKey, VerifyOptions, Document, Envelope, Manifest, Error, Result}. Everything else is reached through its module path (anza::crypto::…, anza::stream::…, anza::render::…, anza::engine::…, anza::adapters::…).