Rendering#

Rendering pages and fragments.

Page renders a full HTML document and Fragment renders one template into a JSON Envelope for a client slot. Both take a dict, (key, value) pairs, or any object as their params.

Pages

Page(route, params) maps the route to a template under pages/:

  • / is pages/home.html; /about and /about/ are pages/about.html; /docs/intro is pages/docs/intro.html.

  • When that page does not exist, pages/index.html is the catch-all.

  • Otherwise, or for a malformed route (.., \, NUL), Page.run() raises AnzaError with code NOT_FOUND and the message Page not found.

The page markup is inserted as is (no wrapper element) into layout/shell.html as {{content}}; the shell is bound with params plus content. Without a shell the page goes into a minimal default document with a <dock-main> open shadow root (Declarative Shadow DOM).

Fragments

Fragment(template, slot, params) renders any loaded template (limited by the fragments allowlist of Setup) and returns an Envelope with the slot, a Unix timestamp, the HTML and, when the engine signs, a signature (see Signing & verification). Send Envelope.to_json() as the response body.

Data binding

from dataclasses import dataclass
from anza import Page

@dataclass
class UserProfile:
    user_id: str
    user_name: str
    role: str

profile = UserProfile(user_id="usr_102", user_name="Alice", role="Admin")
doc = Page("/profile", profile).run(engine)

{{user_name}} reads profile.user_name. Only public, non-callable attributes are read: names starting with _ and methods render as empty. Missing values and None render as empty, booleans as true / false, integral floats without .0, and dicts, lists and tuples as compact JSON ({"a":1}). See string() for the exact rules.

Escaping

By default values are inserted as is, without HTML escaping. Escape user input with escape_html() before passing it in, or turn on the escape option:

from anza import Setup, escape_html

escape_html('<a href="x">Tom & Jerry's</a>')
# '&lt;a href=&quot;x&quot;&gt;Tom &amp; Jerry&#39;s&lt;/a&gt;'

engine = Setup(root="./templates", escape=True).run()

With escape=True, {{name}} is HTML-escaped and {{{name}}} stays raw. Use {{{content}}} in layout/shell.html so the rendered page is not escaped twice.