Skip to main content

Real-time Updates

Extensions receive real-time updates via WebSocket when storage or server-side state changes.

Automatic storage sync​

useExtensionStorage() is automatically synced via the ext-storage:\{install_id\} WebSocket channel. When the editor calls a storage setter, every other surface re-renders within milliseconds - no polling, no manual refresh. Layers read storage but do not write it; see Shared Storage.

Editor: setScore(3) // const [score, setScore] = useExtensionStorage("score", 0)
-> Lumio API updates storage
-> Redis PUBLISH to ext-storage:{install_id}
-> WebSocket server broadcasts update
-> Layer: useExtensionStorage("score", 0) re-renders with 3

This is completely automatic. You do not need to configure any WebSocket connections.

Manual refetch after mutations​

Server function results are not automatically refreshed when storage changes. After calling a mutation, call refetch() on any affected queries:

import { useQuery, useMutation, Button } from "@zaflun/lumio-sdk";

function RuleManager() {
const { data: rules, refetch } = useQuery("getRules");
const { mutate: addRule } = useMutation("addRule");

const handleAdd = async () => {
await addRule({ text: "New rule" });
refetch(); // manually trigger re-query
};

return <Button label="Add rule" onClick={handleAdd} />;
}

Real-time events​

Use useLumioEvent() to subscribe to real-time platform events (Twitch followers, YouTube superchats, etc.). Events are pushed via the Lumio event WebSocket channel and do not require any setup:

import { useLumioEvent } from "@zaflun/lumio-sdk";

function LiveCounter() {
const event = useLumioEvent("twitch:follower");
const [count, setCount] = useState(0);

useEffect(() => {
if (event) {
setCount((prev) => prev + 1);
}
}, [event]);

return <Text content={`${count} new followers`} />;
}

WebSocket channel reference​

ChannelTriggered byReceived by
ext-storage:{install_id}A storage setter in the editorAll surfaces for this install
events:{account_id}Platform events (Twitch, YouTube, etc.)All extensions on this account
extension_install:{install_id}ctx.realtime.push() in a server function or bot-module handlerEditor and layer of this install, via useRealtime

A chat command or channel point reward handled by a bot module reaches the layer through ctx.realtime.push() - see Viewer Input.

Connection handling​

The Lumio SDK automatically manages WebSocket reconnection. If the connection drops:

  • The SDK retries with exponential backoff
  • useExtensionStorage() shows the last known value during reconnection
  • useLumioEvent() will miss events that occurred during the disconnect period (events are not replayed)

Polling as a fallback​

For server function data that needs to stay fresh (e.g., a leaderboard that other users update), implement polling with useEffect:

import { useQuery } from "@zaflun/lumio-sdk";
import { useEffect } from "react";

function LiveLeaderboard() {
const { data, refetch } = useQuery("getLeaderboard");

// Refresh every 30 seconds
useEffect(() => {
const interval = setInterval(refetch, 30_000);
return () => clearInterval(interval);
}, [refetch]);

return <List items={(data ?? []).map(...)} />;
}