Skip to content
Brew

Your first component

This walkthrough assumes Brew is installed and session + CSRF middleware are on the web stack.

Terminal window
./grind make:brew counter
# or: ./grind make:brew counter --lang=java

Put classes in app.brew (or configure brew.class_namespace).

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()
}

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))

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.

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");
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