Channels
A channel is a named publish/subscribe topic. The server publishes with channel.broadcast(name, payload); browsers subscribe via the SSE endpoint at /__rat__/channels?name=<name>. There's one broker per server; topics are created lazily on first publish or subscribe.
Broadcast from a handler
Push to every subscriber
channel.broadcast is a global — available anywhere Rat code runs server-side. The payload is serialized as JSON, so pass plain objects, arrays, strings, or numbers.
> page
name: ''
msg: ''
<input value[name] on_input[name << event.target.value]>
<input value[msg] on_input[msg << event.target.value]>
<button on_click[channel.broadcast('chat', {from: name, text: msg})]>
send Subscribe from the browser
Native EventSource
Browsers consume the channel as a standard SSE stream. Open an EventSource against the topic URL and decode each message as JSON. No client library — the browser already speaks SSE.
# in a lang/js/chat.js (inverse tail)
export function listen(onMessage) { const es = new EventSource('/__rat__/channels?name=chat'); es.onmessage = (ev) => onMessage(JSON.parse(ev.data)); }
# then on a page:
> page
<script on_load[chat.listen(handle_message)]> Channel from a Tail worker
Python can broadcast too
Anything that runs in-process with the server can broadcast. A Python Tail worker that finishes a long-running job hands its result back to Rat, and the Rat handler relays the result to subscribers. One topic, many producers.
# main.rat
> finish_job[job_id]
[result] << ml.run(job_id)
channel.broadcast('job_done', {id: job_id, result: result}) Next section: Dev workflow — the rat CLI, settings, and what hot reload covers.