Brew templates
Brew renders HTML through Crema. Each component must produce a single root element. Brew stamps wire:snapshot, wire:effects, wire:id, and wire:name onto that root.
Rendering paths
Section titled “Rendering paths”template()— inline Crema on the classrender()→view("brew.todos", data)orinline(source, data)- Convention file
src/main/resources/views/brew/<name>.crema.htmlwhen both are absent
Inside templates, public properties and @Computed methods are in scope as Crema data.
Tags and directives
Section titled “Tags and directives”| Surface | Example |
|---|---|
| Tag | <brew:counter :start="1" /> |
| Directive | @brew('counter', ['start' => 1]) |
| Styles placeholder | @brewStyles |
| Scripts | @brewScripts |
| Script config only | @brewScriptConfig (for manual ESM bundling) |
| JS encode | @js($value) |
When brew.inject_assets is true, responses that look like full HTML documents get styles + scripts injected automatically if those directives are missing.
Assets and routes
Section titled “Assets and routes”| URL | Content |
|---|---|
/brew/brew.js |
Readable bundle |
/brew/brew.min.js |
Minified (+ source map) |
Script tags include a cache-busting ?id= hash, data-csrf, and data-update-uri="/brew/update". Override paths with Brew.setUpdateRoute / Brew.setScriptRoute when you need a custom mount point (brew.path still names the default).
From Kotlin/Java:
Brew.styles()Brew.scripts()Brew.scriptConfig()Morph markers
Section titled “Morph markers”With brew.inject_morph_markers (default true), Crema wraps conditionals and loops in HTML comment markers so the keyed morph can add/remove blocks without tearing sibling DOM. Prefer wire:key on list items:
@foreach(items as item) <li wire:key="item-{{ item.id }}">{{ item.title }}</li>@endforeachLayout tips
Section titled “Layout tips”- Keep interactive UI inside the component root; Brew morphs that subtree.
- Use
wire:ignore(.self/.children) for islands Brew must not touch (third-party widgets). wire:replaceforces a full replace instead of a morph when needed.
Example page
Section titled “Example page”<!DOCTYPE html><html lang="en"><head> <meta charset="utf-8"> <title>{{ title }}</title> @brewStyles</head><body> <h1>{{ title }}</h1> <brew:counter :start="3" /> <brew:todos /> @brew('search') @brewScripts</body></html>- Components — class vs view authoring
- JavaScript — how the morph and
$wirebehave - Lifecycle —
rendering/renderedhooks