Skip to main content

useRealtime

Receive the messages a handler of this install pushes with ctx.realtime.push(topic, payload). Server functions (query() / mutation() / action()) and bot-module handlers can push. Every rendered surface of the install receives the message: the editor panel in the dashboard and every overlay or widget that shows the extension.

Signature​

useRealtime<T = unknown>(topic: string, cb: (payload: T) => void): void;

Parameters​

ParameterTypeRequiredDescription
topicstringYesThe topic to listen to. Messages on other topics are ignored.
cb(payload: T) => voidYesCalled with the payload of each message on topic. It may change between renders without re-subscribing.

Example​

A poll overlay that updates when a chat vote comes in:

// server/handler.ts - a viewer types "!vote 2" in chat
import { command } from "@zaflun/lumio-sdk/server";

export const vote = command("vote", async (ctx, args) => {
await ctx.db.insert("votes", { choice: args[0] });
const votes = await ctx.db.list("votes");
ctx.realtime.push("poll:votes", { total: votes.length });
return null;
});
// layer.tsx
import { useState } from "react";
import { Text, useRealtime } from "@zaflun/lumio-sdk";

export default function PollLayer() {
const [total, setTotal] = useState(0);
useRealtime<{ total: number }>("poll:votes", (payload) => setTotal(payload.total));
return <Text>{total} votes</Text>;
}

Delivery​

  • The host subscribes to the install's WebSocket channel extension_install:{install_id} with its own credential: the dashboard session in the editor, the overlay or widget token in OBS.
  • Messages arrive in the order the handler pushed them.
  • Nothing is stored or replayed. A message pushed while the surface is not open, or before the extension has started, is not delivered. Load the current state with useQuery when the surface starts, and use useRealtime for changes after that.
  • A message is sent only when the handler that pushed it did not throw.

Push rules​

RuleValue
Topic1-64 characters of A-Z a-z 0-9 _ . : -, starting with a letter or digit
PayloadAny JSON value, at most 16 KiB serialized (omitted = null)
Pushes per handler run32
Pushes per install and minute300; more are dropped
Published bytes per install and minute1 MiB of serialized { topic, payload } messages; more are dropped

A push that breaks the topic, payload or per-run rule throws inside the handler. REALTIME_LIMITS in @zaflun/lumio-protocol holds these values.