Your first component
This walkthrough assumes Brew is installed and session + CSRF middleware are on the web stack.
1. Scaffold or hand-write
Section titled “1. Scaffold or hand-write”./grind make:brew counter# or: ./grind make:brew counter --lang=javaPut classes in app.brew (or configure brew.class_namespace).
2. Component class
Section titled “2. Component class”package app.brew
import org.konaframework.brew.Component
class Counter : Component() { var count = 0
fun mount(start: Int = 0) { count = start }
fun increment() { count++ }
fun decrement() { count-- }
override fun template() = """ <div> <button type="button" wire:click="decrement">−</button> <span>{{ count }}</span> <button type="button" wire:click="increment">+</button> </div> """.trimIndent()}package app.brew;
import org.konaframework.brew.Component;
public class Counter extends Component { public int count = 0;
public void mount(int start) { count = start; }
public void increment() { count++; }
public void decrement() { count--; }
@Override public String template() { return """ <div> <button type="button" wire:click="decrement">−</button> <span>{{ count }}</span> <button type="button" wire:click="increment">+</button> </div> """; }}3. Embed in a page
Section titled “3. Embed in a page”Attributes become mount parameters / initial props (:start="3" → mount(start = 3)).
{{-- views/welcome.crema.html --}}<!DOCTYPE html><html lang="en"><head> <meta charset="utf-8"> <title>Welcome</title> @brewStyles</head><body> <h1>Welcome</h1> <brew:counter :start="3" /> {{-- or: @brew('counter', ['start' => 3]) --}} @brewScripts</body></html>You can also mount from code:
val html = Brew.mount("counter", mapOf("start" to 3))4. Route to the page
Section titled “4. Route to the page”Wire a normal Kona route that returns the Crema view (see Kona routing). On first paint you should see 3. Each click posts to /brew/update and morphs the new HTML.
5. Test without a browser
Section titled “5. Test without a browser”Brew.test(Counter::class.java) .set("count", 1) .call("increment") .assertSet("count", 2) .assertSee("2")Brew.test(Counter.class) .set("count", 1) .call("increment") .assertSet("count", 2) .assertSee("2");What you just used
Section titled “What you just used”| Piece | Role |
|---|---|
Public count |
Snapshot state |
increment / decrement |
Browser-callable actions |
wire:click |
Alpine-backed event → server call |
{{ count }} |
Crema interpolation on re-render |
Single root <div> |
Required for morph |
- Components — discovery, class + view, registration
- Forms & validation —
wire:modeland rules - Examples → Counter — polished sample walkthrough