agentsclimarketplace

Design obs alert overlay

Skill slogsdon/skills-design/skills/design-obs-alert-overlay

Generate an OBS browser-source alert overlay — single 1920×1080 HTML file with TRANSPARENT background and hash-routed scenes for stream events (#follow, #sub, #donation, #raid). Each scene auto-plays a single entrance animation, holds, then fades. Reads ./design/<brand-slug>/DESIGN.md, tokens.css, and components.html. Triggers include "obs alert overlay", "stream alerts", "follower alert", "/obs-alert-overlay".From its SKILL.md

Install
npx -y skills add slogsdon/skills-design --skill design-obs-alert-overlay

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
  • runs commandsInstructs the agent to run 2 commands, including `test -f ./design/<brand-slug>/tokens.css` and 1 more.

SKILL.md

12.8 KB, ~3.3k tokens by cl100k_base, as published. Nobody here has run it

Skill: obs-alert-overlay

Produces ONE self-contained obs-alert-overlay.html file at 1920×1080 with transparent background that streams compositors (OBS, Streamlabs, Twitch Studio) load as a browser source. The page contains four hash-routed scenes — #follow, #sub, #donation, #raid — each with its own auto-playing entrance animation. Switching scenes is just changing the URL hash.

This is distinct from the stream-overlay skill (which produces persistent scene chrome — starting / brb / webcam / lower-third / ending). This skill produces TRANSIENT alert cards triggered per event.

When to use

  • User streams on Twitch / YouTube Live / Kick and wants branded alert cards
  • A DESIGN.md exists for the brand

Inputs

  • Required: brand slug
  • Optional: alert position (default: lower-right corner; alternates: lower-left, upper-right, top-bar)
  • Optional: brand voice for alert copy (e.g. "ack." vs "thanks for the follow." vs "noted." — Shane's brand prefers terse + sentence-case)

Output

./design/<brand-slug>/artifacts/obs-alert-overlay.html (single file — overwrite OK; canonical alert overlay for the brand)

Scenes (default 4)

HashTriggerDefault copy
#follownew follower"<name> just followed."
#subnew subscriber"<name> subscribed."
#donationtip / donation"<name> sent $<amount>."
#raidincoming raid"<name> raided with <count>."

Each scene takes scene parameters via URL: obs-alert-overlay.html#follow?name=Sam (or via OBS alert variable substitution per stream tool).

Steps

1. Verify brand exists

test -f ./design/<brand-slug>/tokens.css

2. Gather the brief

Ask in one message:

1. Default alert position — lower-right (default) | lower-left | upper-right | top-bar
2. Brand voice for alert copy — terse ("noted.") | declarative ("just followed.") | warm ("welcome.")
3. Hold duration (seconds) — default 4
4. Any scenes to skip — default: include all 4

3. Pick variation — applies to ALL scenes (consistency for live broadcasts)

Alert cards must read consistently across scene types — viewers shouldn't have to re-parse the visual language for each event type. Pick ONE set:

  • Card style: bracketed (corner-frame L-marks) | chromeless (no border, type-only) | block (solid color block) | hairline (1px border + cream surface)
  • Type pressure: display-led (Fraunces or brand display dominant) | mono-led (mono labels carry it)
  • Color usage: cream-card (cream surface on transparent overlay) | inverted-card (dark ink card on transparent overlay)
  • Position: lower-right (default) | lower-left | upper-right | top-bar

Differentiation between scenes comes from copy + a small mono label ("FOLLOW" / "SUB" / "TIP" / "RAID"), NOT from changing the visual treatment per scene.

4. Generate the HTML

The file structure mirrors stream-overlay: one .scene per hash, JS reveals the active scene. Each .scene contains an .alert-card with auto-playing CSS keyframe animation.

Template:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title><Brand> — OBS Alert Overlay</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=<families>&display=swap">
<style>
/* Embed tokens.css verbatim */
<contents of tokens.css>

/* Critical: page must be transparent for OBS compositing */
html, body { margin: 0; padding: 0; width: 1920px; height: 1080px; overflow: hidden; background: transparent; font-family: var(--type-sans-family); color: var(--color-ink); }

.scene { position: fixed; inset: 0; width: 1920px; height: 1080px; display: none; }
.scene.is-active { display: block; }

/* Alert card — positioned by variation choice */
.alert-card {
  position: absolute;
  /* lower-right default: */
  bottom: 80px; right: 80px;
  min-width: 480px; max-width: 720px;
  padding: 24px 32px;
  background: var(--color-surface);   /* cream-card; or var(--color-ink) for inverted-card */
  color: var(--color-ink);
  border: 1px solid var(--color-rule); /* hairline variation */
  /* Auto-play sequence: slide-in (0–600ms) → hold (600ms–4400ms) → fade (4400–4800ms) */
  animation: alert-sequence 4800ms cubic-bezier(0.2, 0.6, 0.2, 1) forwards;
}

/* Single animation per scene — entrance + hold + exit as one sequence */
@keyframes alert-sequence {
  0%      { transform: translateX(120%); opacity: 0; }     /* off-screen right */
  12%     { transform: translateX(0);    opacity: 1; }     /* slid in by ~600ms */
  92%     { transform: translateX(0);    opacity: 1; }     /* hold until 4400ms */
  100%    { transform: translateX(0);    opacity: 0; }     /* fade out by 4800ms */
}

/* Alert card structure */
.alert-card .label {
  font-family: var(--type-mono-family);
  font-size: 11px; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--color-ink-3);
  margin: 0 0 8px;
}
.alert-card .copy {
  font-family: var(--type-display-family);
  font-weight: 500; font-size: 32px; line-height: 1.18;
  letter-spacing: -0.012em;
  margin: 0;
  color: var(--color-ink);
}
.alert-card .copy .name { color: var(--color-accent); }   /* the dynamic name in accent — the only place accent is used */

/* Variant: inverted card */
.alert-card--inverted {
  background: var(--color-ink); color: var(--color-surface);
  border-color: rgba(251, 250, 249, 0.18);
}
.alert-card--inverted .label { color: rgba(251, 250, 249, 0.55); }
.alert-card--inverted .copy { color: var(--color-surface); }

/* Bracketed variation */
.alert-card--bracketed { border: 0; }
.alert-card--bracketed::before, .alert-card--bracketed::after {
  content: ""; position: absolute; width: 12px; height: 12px;
  border: 1px solid var(--color-ink);
}
.alert-card--bracketed::before { top: -1px; left: -1px; border-right: none; border-bottom: none; }
.alert-card--bracketed::after { bottom: -1px; right: -1px; border-left: none; border-top: none; }
</style>
</head>
<body>
<!--
Stream Alert Overlay — single file, hash-routed scenes.
Load as OBS browser source at 1920×1080 (transparent background).
Switch via URL hash:
  #follow · #sub · #donation · #raid
Each scene auto-plays its 4.8s alert sequence on load.
Pass dynamic names via URL query: ?name=Sam&amount=10

Variation choices:
  card-style:    <picked>
  type-pressure: <picked>
  color:         <picked>
  position:      <picked>
-->

<section id="scene-follow" class="scene">
  <div class="alert-card">
    <p class="label">— follow</p>
    <p class="copy"><span class="name">[name]</span> just followed.</p>
  </div>
</section>

<section id="scene-sub" class="scene">
  <div class="alert-card">
    <p class="label">— subscriber</p>
    <p class="copy"><span class="name">[name]</span> subscribed.</p>
  </div>
</section>

<section id="scene-donation" class="scene">
  <div class="alert-card">
    <p class="label">— tip</p>
    <p class="copy"><span class="name">[name]</span> sent $<span class="amount">[amount]</span>.</p>
  </div>
</section>

<section id="scene-raid" class="scene">
  <div class="alert-card">
    <p class="label">— raid</p>
    <p class="copy"><span class="name">[name]</span> raided with <span class="count">[count]</span>.</p>
  </div>
</section>

<script>
function activateScene() {
  var hash = (window.location.hash || '#follow').split('?')[0].slice(1);
  var scenes = document.querySelectorAll('.scene');
  scenes.forEach(function(el) { el.classList.toggle('is-active', el.id === 'scene-' + hash); });
  // Parse URL query for dynamic substitution (name, amount, count)
  var params = new URLSearchParams(window.location.hash.split('?')[1] || '');
  ['name', 'amount', 'count'].forEach(function(key) {
    var val = params.get(key);
    if (!val) return;
    document.querySelectorAll('.scene.is-active .' + key).forEach(function(el) { el.textContent = val; });
  });
}
window.addEventListener('hashchange', activateScene);
activateScene();
</script>
</body>
</html>

5. Document the OBS setup for the user

After writing the file:

OBS alert overlay generated at ./design/<brand-slug>/artifacts/obs-alert-overlay.html.

OBS setup (one alert source per scene):

  1. Sources → Add → Browser
  2. Local file → point to obs-alert-overlay.html
  3. Width: 1920, Height: 1080
  4. URL hash: #follow (or other scene)
  5. Optional dynamic name via query: …/obs-alert-overlay.html#follow?name={user}

Connect your alert provider (Streamlabs / StreamElements) to trigger a refresh of the browser source per event so the animation re-plays.

Variation: <card-style> × <type-pressure> × <color> × <position>.

6. Verify

  • Single file, 1920×1080, transparent body background (CRITICAL — OBS compositing depends on this)
  • All 4 scenes present with .is-active toggle via hash
  • One animation per scene — the slide-in + hold + fade is a single sequence (per anti-patterns §8)
  • No decorative motion outside the alert sequence
  • Variation choice consistent across all 4 scenes
  • Read ../design-anti-patterns.md and verify the artifact violates none of its rules. Pay special attention to §3 (no accent on a single punctuation mark — but accent on the dynamic name token IS allowed because it's doing semantic work, marking the new entity), §5 (no editorial-cosplay markers), and §8 (animation discipline)
  • Dynamic name span uses --color-accent ONLY when the name is the new entity (not as decoration)

Anti-Slop Rules

Governed by three shared canonical references — read them, do not restate them:

  • ../design-anti-patterns.md — the hard floor. Wins every conflict.
  • ../design-principles.md — the craft floor (typographic hierarchy, spatial rhythm, color theory, layout logic, visual tension).
  • ../design-variation-sop.md — the named-aesthetic roster + the procedure for varying every invocation.

Forbidden (fast scan — the references hold the full list):

  • Indigo/violet/purple as default accent or primary — the hsl(230–280) family on a near-white surface. The single loudest AI tell.
  • Purple→blue / "aurora" / gradient-mesh backgrounds; gradient-fill text.
  • Glassmorphism without an explicit AA-contrast scrim; floating gradient "blobs" as atmosphere.
  • The three-up icon-card feature grid; the "hero → 3 cards → CTA" median skeleton.
  • One global border-radius on every element; timid evenly-weighted low-contrast palette.
  • Inter / Roboto / Arial / Open Sans / Lato / Helvetica / system as the primary family (Space Grotesk = yellow flag). Use a category-matched stack from the variation roster.
  • Value-free CTAs ("Get Started", "Learn More", "Sign Up"); the two-CTA hero. Name the real action and its value.

Required variation (every invocation):

  • Make at least two intentional decisions that differ from the safe defaults (palette, layout structure, typographic voice, or spatial density) AND from the most recent artifact in this brand.
  • Never default to "clean / minimal / modern" — that is the absence of a direction (variation-sop Rule 1).
  • Sketch three distinct directions, offer them as a one-line menu, generate the best-fit by default, all three only if asked (variation-sop Rule 3).

Authenticity: prefer specific over generic everywhere — real datelines (not "today"), the brand's actual voice (not "build the future" filler), concrete CTAs over placeholders.

Rules

  • Single file always. OBS loads one URL; multiple files would defeat the purpose.
  • Transparent background — hard requirement. body { background: transparent } must be present.
  • One animation per scene. Slide-in + hold + fade is ONE sequence. Adding a separate spinner or pulse would be two animations — forbidden.
  • No sound. This is a visual artifact. Audio belongs to the streaming software's alert config, not the overlay.
  • Dynamic substitution via URL query. Name, amount, count are passed in by the streaming tool — the artifact must accept them via ?name=... parsing.
  • Token-pure. Same rules as other platform skills.
  • Anti-pattern compliance. This skill defers to three shared canonical references: ../design-anti-patterns.md (the hard floor — wins every conflict), ../design-principles.md (the craft floor), and ../design-variation-sop.md (direction roster + offer-3 procedure). The anti-patterns file is the canonical anti-tell list.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.