Skip to main content

React to live events

A widget gets interesting when it reacts to your stream. In this tutorial you'll make a widget that thanks your most recent follower and flashes when a new one comes in — and you'll test it without needing a real follow, using the simulator.

This builds on Build your first widget; start there if you haven't.

1. Declare the binding

Before a widget can receive an event, you declare it on the Bindings surface. Open Bindings and toggle on Follow.

That's the contract: you've told Streamerly to deliver follow events to this widget. (If you use an event in code without declaring it, the console warns you and it won't arrive live.)

2. Show the latest follower

The simplest way to use an event in a template is the useLatestEvent hook — it gives you the most recent payload and re-renders when a new one arrives.

// main.tsx
import { useLatestEvent, Event } from '@widget';

export default function Main() {
const follow = useLatestEvent(Event.Follow);
const name = follow?.user.displayName;

return (
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: '100%',
fontSize: '40px',
fontWeight: 800,
color: '#fff',
}}
>
{name ? `Thanks for the follow, ${name}!` : 'Waiting for a follower…'}
</div>
);
}

3. Test it with the simulator

You don't need a real follow to see this work. Go to the Simulate surface:

  1. Select the Follow event.
  2. Edit the payload's displayName to anything you like.
  3. Click Fire.

The preview updates to thank that name. Use Burst to fire several in a row and check it keeps up.

tip

Every event carries a specific payload — a follow has a user, a cheer has bits, a raid has viewers. The simulator shows the payload shape so you can see exactly what your handler receives. The full catalogue is in Event bindings.

4. Add a flash on each new follow

Reacting to the moment a follow happens (rather than just showing the latest name) is a job for a handler. Use useEvent in the template, or registerBinding in the core. Here's a flash effect with a little state:

// main.tsx
import { useState } from 'react';
import { useEvent, Event } from '@widget';

export default function Main() {
const [flashing, setFlashing] = useState(false);
const [name, setName] = useState<string | null>(null);

useEvent(Event.Follow, (payload) => {
setName(payload.user.displayName);
setFlashing(true);
setTimeout(() => setFlashing(false), 800);
});

return (
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: '100%',
fontSize: '40px',
fontWeight: 800,
color: '#fff',
transition: 'filter 200ms ease, transform 200ms ease',
filter: flashing ? 'brightness(1.8)' : 'none',
transform: flashing ? 'scale(1.08)' : 'scale(1)',
}}
>
{name ? `Thanks for the follow, ${name}!` : 'Waiting for a follower…'}
</div>
);
}

Fire a Follow from the simulator and watch it pulse.

5. Reading live values

Some bindings aren't moments but live values — the current viewer count, the stream title, your goals. Read them the same way:

import { useLatestEvent, Event } from '@widget';

export default function Main() {
const stats = useLatestEvent(Event.Stats);
return <div>{stats?.viewers ?? 0} watching now</div>;
}

Declare Channel Stats on the Bindings surface first, the same way you did for Follow.

6. Build and place it

Click Build, then add the widget to an overlay just like before. When you're live, real follows will drive it.

Where to go next