Skip to main content

Interactive Page

The interactive surface renders on a standalone web page at /ext/\{slug\} where viewers can interact with your extension — voting, playing games, submitting requests, or anything that requires direct audience participation.

Entry point

Every extension that includes the "interactive" target must have a src/interactive.tsx file:

// src/interactive.tsx
import { Lumio, CompactView, Button, Text, VStack, useExtensionStorage, useMutation, useQuery } from "@zaflun/lumio-sdk";

function VotingPage() {
const [storage] = useExtensionStorage();
const { data: results } = useQuery("getVoteResults");
const { mutate: vote, isLoading } = useMutation("castVote");

const total = (results?.yes ?? 0) + (results?.no ?? 0);

return (
<CompactView title={storage.topic ?? "Cast your vote"}>
<VStack>
<Text
content={`${total} votes so far`}
variant="muted"
/>
<Button
label={`Yes (${results?.yes ?? 0})`}
onClick={() => vote({ choice: "yes" })}
disabled={isLoading}
/>
<Button
label={`No (${results?.no ?? 0})`}
onClick={() => vote({ choice: "no" })}
disabled={isLoading}
/>
</VStack>
</CompactView>
);
}

Lumio.render(<VotingPage />, { target: "interactive" });

Authentication

Interactive pages use short-lived token authentication. The URL format is:

https://lumio.vision/ext/{slug}?token=lm_ext_xxxxxxxxxxxx
  • Tokens are 15 minutes short-lived and scoped to the specific extension installation
  • The token grants read access to the installation's storage and write access to permitted server mutations
  • Tokens are generated by the Lumio host and distributed to viewers (e.g., via a bot command configured in the editor)
  • No cookies or session storage are used — the token is the only credential

Full interactivity

Unlike the layer surface, the interactive surface has full component interactivity. All input components work as expected:

ComponentInteractive behavior
ButtonClickable, triggers onClick
ToggleToggleable, triggers onChange
TextFieldEditable text input
TextAreaEditable multi-line input
NumberFieldEditable number input
DropdownSelectable options
SliderDraggable range input

Use cases

Use caseExample
VotingViewers vote on which game challenge to attempt next
PredictionsAudience predicts the outcome of a game event
Song requestsViewers submit song requests for the streamer
Chat gamesTrivia, bingo, word games driven by viewer input
Challenge suggestionsCommunity submits ideas for the streamer
PollsQuick one-question audience polls

The interactive page URL is available in the extension dashboard under the installation settings. To automatically share it in chat, request the chat:send permission and use useLumioAction("chat:send") in the editor:

{
"permissions": ["chat:send"]
}

Real-time updates

The interactive page receives storage updates in real time via WebSocket, just like the layer surface. If the editor changes the voting topic, the interactive page updates immediately for all viewers already on the page:

function VotingPage() {
const [storage] = useExtensionStorage();
// storage.topic updates in real time when the editor changes it

return (
<CompactView title={storage.topic ?? "Vote now"}>
...
</CompactView>
);
}

No OBS dependency

The interactive page works independently of any OBS Browser Source. Viewers access it directly in their browser — it does not require OBS to be open or the stream to be live.