Skip to the demo
Demos

AI chat

A streaming chat page with zero client JavaScript. No /api/chat route, no EventSource, no client state library — the tokens are a server-side loop writing to this.answer, and @task streams the field. Cancel aborts the generation itself, not just the UI.

@expose prompt = "";
@expose answer = "";

@task async ask() {                       // streaming, cancellable, server-side
  this.answer = "";
  for await (const chunk of Ai.stream({
    prompt: this.prompt,
    system: "Answer in two or three sentences.",
    signal: this.signal,                  // $flow.cancel() aborts the generation
  })) {
    if (chunk.type === "text") this.answer += chunk.text;   // → streams to the browser
  }
}

<input bind={this.prompt} />
<button onClick={this.ask} loadingAttr="disabled">Ask</button>
<button onClick={() => $flow.cancel()} showOnLoading>Cancel</button>
<div text={this.answer} />