Stream overlay generator: deterministic alerts in HTML
A Twitch overlay alerts generator built in HTML/CSS — slide-in follower alert, deterministic CSS-transform confetti burst, slide-out. Render to MP4 or feed OBS as a browser source.
A Twitch overlay alerts generator that actually fits a streamer's brand has to do three things: arrive without stealing focus from the game, celebrate without being obnoxious, and leave cleanly. The default Streamlabs alerts do exactly one of those.
The pattern below is an HTML overlay that drops into OBS as a browser source — or renders to MP4 for pre-made stings on YouTube uploads. Every motion is deterministic, every burst particle is a positioned <span>, no PNG sequences, no GIFs.
The shape of an alert
An on-stream alert has a tighter brief than a generic notification. The streamer is busy, the game is moving, and the viewer's eye is mostly on the action. Good alerts:
- Enter from screen edge, never the middle. Slide from the right is dominant in stream overlay culture and reads as "secondary."
- Hold long enough to be read aloud, typically 3–4 seconds.
- Exit faster than they entered. Quadratic-in on the way out so it feels decisive, not soft.
The demo above runs that exact timeline: 0.7s slide-in, 3.8s hold, 0.7s slide-out.
Deterministic confetti, in 30 lines
The confetti is the part that usually requires a library. It does not. The whole burst is 24 spans, each with a deterministic angle/distance/rotation derived from a hash of its index:
for (let i = 0; i < 24; i++) {
const s = Math.sin(i * 12.9898 + 78.233) * 43758.5453;
const r1 = s - Math.floor(s); // pseudo-random angle jitter
const r2 = (s * 2 - Math.floor(s * 2)); // distance + delay
const r3 = (s * 3 - Math.floor(s * 3)); // rotation
bits.push({
angle: (i / 24) * Math.PI * 2 + r1 * 0.4,
dist: 80 + r2 * 90,
rot: (r3 - 0.5) * 720,
delay: r2 * 0.15,
});
}The sin/floor trick is the classic GLSL pseudo-random — same input, same output, every render. Then each frame computes translate(cos*dist, sin*dist + gravity) and a rotation. That's it. No Matter.js, no particle engine, no Lottie.
Gravity, the easy way
Each particle's vertical position has a falling term added: dy = sin(angle) * dist * easeOut(p) + p² * 90. The first term is the initial radial blast; the p² * 90 term is constant gravity. Multiplying by the square of normalized time gives a quadratic fall, which is how real gravity works at small scales. The particles arc outward and then sag — they don't drift in straight lines.
Customize the alert
OBS as a browser source
The same HTML file works two ways:
- As a browser source in OBS. Add a Browser source, point it at the HTML file or a localhost URL. The alert needs to be triggered — wire a websocket to the streaming platform's webhook and call
dispatchEvent(new CustomEvent('hf-seek', {detail: {time: 0}}))on each new follower, advancing the time on a real-time clock from there. - Pre-rendered as a sting MP4. Render once with HyperFrames, then use it as a Media Source in OBS, triggered manually or via OBS scripting. This is the bulletproof option — the video frame is fixed, no browser surprises mid-stream.
// Hook your platform webhook -> drive hf-seek as wall clock
let alertStart = null;
window.fireAlert = (data) => {
// re-render the alert text from data
document.querySelector('.who').textContent = data.username;
document.querySelector('.avatar').textContent = data.initials;
alertStart = performance.now();
};
function loop(now) {
if (alertStart != null) {
const t = (now - alertStart) / 1000;
dispatchEvent(new CustomEvent('hf-seek', { detail: { time: t } }));
if (t > 5.5) alertStart = null;
}
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);Alert variants worth pre-rendering
A streamer wants 4–6 alert stings ready to drop in:
- New follower (the demo above)
- New subscriber — confetti color shift, gold accent, slightly longer hold
- Raid incoming — extra-large display, sustained burst over 3s
- Bit cheer — number counts up next to the avatar
- Donation milestone — full-screen sting, not a corner alert
All five share the same skeleton. Swap the headline copy and the burst color; the timing, easing, and slide direction stay constant. Brand consistency is the whole point.
Render to MP4
hyperframes render input.html --out clip.mp4 --duration 6 --fps 30Render at your stream's canvas resolution (typically --width 1920 --height 1080). For 1440p streams, --width 2560 --height 1440. The HTML is responsive; the layout adapts to the viewport. Walk through the quickstart for the first render, and the playground for live iteration on the spring constants.
FAQ
Can I use this with Streamlabs or StreamElements?
Yes — both platforms accept custom HTML/CSS/JS widgets. Paste the alert HTML into the custom widget editor and replace their default onEvent handler with one that calls dispatchEvent(new CustomEvent('hf-seek', ...)). The animation logic remains identical between live and pre-rendered modes.
How do I trigger the alert in OBS without polling?
Use the OBS WebSocket plugin. From a small Node.js script subscribing to your Twitch EventSub webhook, send a WebSocket message that calls window.fireAlert({...}) in the browser source. Reaction time is under 100ms end-to-end.
Why does my confetti drift instead of falling?
The gravity term scales with p² (squared normalized time). If you used p (linear), particles drift outward without acceleration and look like they're in zero-g. Squaring the gravity term keeps the arc realistic.
Can I bake-in audio cues?
Render the video-only MP4 with HyperFrames, then attach the sound with ffmpeg -i alert.mp4 -i ding.wav -c:v copy -shortest alert-final.mp4. Time the ding to land on the confetti burst (around 0.8s) for the satisfying "pop."
What dimensions are best for a corner alert?
520×120 is a comfortable footprint at 1080p. Anchor it 80px from the top and 0 from the right (the alert exits to the right). For mobile-portrait streams (vertical Twitch / TikTok Live), put the alert at the top center, full-width, with a vertical slide.
Related: CSS confetti particle effect, deterministic video rendering in CI.
Cite this postBibTeX · APA · Markdown
@misc{okafor2026stream,
author = {Marcus Okafor},
title = {Stream overlay generator: deterministic alerts in HTML},
year = {2026},
url = {https://hyperframes.video/blog/animated-stream-overlay-generator},
note = {HyperFrames blog}
}Marcus Okafor. (2026, May 21). Stream overlay generator: deterministic alerts in HTML. HyperFrames. https://hyperframes.video/blog/animated-stream-overlay-generator
[Stream overlay generator: deterministic alerts in HTML](https://hyperframes.video/blog/animated-stream-overlay-generator) — Marcus Okafor, 2026
Marcus leads design and motion at HyperFrames. Before that he shipped editorial motion for newsrooms and product launches. He thinks every easing curve has a personality.
Animated flight itinerary cards in HTML
Build an animated boarding pass video: a plane traces an arc from origin to destination, gate and time settle in, the pass folds out — rendered as MP4.
Animated fitness summary cards (Strava-style recaps)
Build a fitness recap video generator: distance, pace, and elevation tick up, a route map traces itself, and weekly streak dots fill in — exported as MP4.
Animated poll results as MP4
Build a poll results animation that renders to deterministic MP4: four horizontal bars race to their final percentages, then a winner ribbon sweeps in.
Building with HyperFrames? Come hang out.
We're on GitHub, in Discord, and the playground is one click away. Bring weird ideas — we collect them.