Loading the Kaya editor…
// A face the program writes: this program builds its page while it runs,
// saves it, and mounts it with the contract the page needs. Because the
// program supplied the bytes, the viewer asks you to approve exactly this
// face, its digest, and its contract before anything loads, and remembers
// your answer.

let page = save(content: `<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
  body { margin: 0; min-height: 100vh; display: grid; place-items: center; font: 16px system-ui, sans-serif; background: #f8fafc; color: #0f172a; }
  main { text-align: center; }
  h1 { margin: 0 0 16px; font-size: 64px; }
  button { padding: 10px 20px; border: 1px solid #4f46e5; border-radius: 8px; background: #4f46e5; color: #fff; font: inherit; cursor: pointer; }
  button:disabled { opacity: 0.5; cursor: default; }
  p { color: #475569; }
</style>
</head>
<body>
<main>
  <h1 data-testid="count">0</h1>
  <button data-testid="add" disabled>Add one</button>
  <p data-testid="note">Connecting</p>
</main>
<script>
  (function () {
    var count = document.querySelector('[data-testid="count"]');
    var add = document.querySelector('[data-testid="add"]');
    var note = document.querySelector('[data-testid="note"]');
    kaya.onEvent(function (event) {
      if (event.eventType !== "counter.state") return;
      count.textContent = String(event.data.count);
      add.disabled = event.data.done;
      note.textContent = event.data.done ? "Done" : "Press Add one until the count reaches 3";
    });
    add.addEventListener("click", function () {
      add.disabled = true;
      kaya.send("counter.add", {}).catch(function (error) {
        note.textContent = error.message;
        add.disabled = false;
      });
    });
    kaya.ready();
  })();
</script>
</body>
</html>
`, filename: "counter.html")

mount(
  component: "counter",
  face: page,
  reads: ["counter.state"],
  sends: {"counter.add": {zodTypeName: "Object", shape: {}}}
)

"Approve the counter in Preview, then press Add one until it reaches 3."

let count = 0
let done = false
emitEvent(eventType: "counter.state", data: {count: count, done: done})
while !done {
  awaitEvent(eventType: "counter.add")
  count = count + 1
  done = count >= 3
  emitEvent(eventType: "counter.state", data: {count: count, done: done})
}

"Counted to {{count}}."