design-stream-overlay — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited design-stream-overlay (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Produces ONE self-contained stream-overlay.html file at 1920×1080 that contains all the standard live-stream scenes. JavaScript reads the URL hash and shows only the matching scene. OBS / Streamlabs / Twitch Studio loads the file once as a browser source; switching scenes is just changing the hash (e.g. file://.../stream-overlay.html#brb).
DESIGN.md exists for the brand./design/<brand-slug>/artifacts/stream-overlay.html (single file — overwrite OK; the file is the brand's canonical overlay)
| Hash | Purpose | Layout |
|---|---|---|
#starting | "Starting Soon" pre-stream waiting screen | Full-canvas headline + countdown placeholder + brand mark |
#brb | "Be Right Back" mid-stream pause | Full-canvas message + small brand mark, intentionally calm |
#webcam | Webcam frame — sized + positioned for the streamer's webcam capture | Cam window region defined as a transparent cutout with frame around it; rest of canvas shows brand chrome (sidebar with stream title, lower-third with handles) |
#lower-third | Just a lower-third name plate at the bottom — for code-only segments | Bottom 20% of canvas: name + role + handles, rest fully transparent |
#ending | "Thanks for watching" outro screen | Full-canvas thank-you + handles + "Subscribe" prompt (rendered as text, not a button graphic) |
test -f ./design/<brand-slug>/tokens.cssAsk in one message:
1. Stream name / show title (e.g. "Live Coding with Shane" or just leave blank)
2. Social handles to display (Twitter/X, GitHub, website, etc.) — comma-separated
3. Streamer name + role for the lower-third (e.g. "Shane Logsdon · Indie Dev")
4. Webcam position for #webcam scene: top-right | bottom-right | bottom-left | top-left (default: bottom-right)
5. Webcam size: 480x270 | 640x360 | 320x180 (default: 480x270, the typical 16:9 cam window)
6. Any scenes to skip? (default: include all 5)Unlike single-artifact skills, the overlay must be visually consistent across scenes. Pick variation ONCE for the whole file:
hairline (thin rules + restrained type) | bracketed (corner brackets framing each scene) | gridded (subtle grid-paper background) | block (solid color blocks delineating zones) | chromeless (no rules, no brackets — pure type and color)display-led (large display type carries scene state) | mono-led (mono labels dominate, very technical feel)monochrome | single-accent-on-cam-frame | inverted-on-pause-scenestop-left | bottom-right | top-bar | corner-mark | none (rely on the streamer's voice + camera, not a chrome mark)Anti-tell guardrails (apply across all scenes):
../design-anti-patterns.md and verify scene chrome violates none of its rules. Pay special attention to sections 5 (editorial cosplay markers — no § 01, EP. 01, Episode), 4 (no top-metadata-row eyebrow disguises across scenes), and 8 (animations — at most ONE functional animation across all scenes; a pulsing dot AND a blinking cursor counts as two).Single self-contained file with all scenes as <section> elements. JS toggles visibility by hash.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title><Brand> — Stream 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>
html, body { margin: 0; padding: 0; width: 1920px; height: 1080px; overflow: hidden; background: transparent; font-family: var(--type-body-md-family); color: var(--color-ink); }
/* All scenes start hidden; JS reveals the one matching the hash */
.scene { position: fixed; inset: 0; width: 1920px; height: 1080px; display: none; box-sizing: border-box; }
.scene.is-active { display: block; }
/* Full-canvas scenes get a brand surface background */
#scene-starting, #scene-brb, #scene-ending { background: var(--color-surface); }
/* #webcam and #lower-third are transparent — OBS composites the webcam underneath */
#scene-webcam, #scene-lower-third { background: transparent; }
/* Eyebrow / mono label */
.eyebrow {
font: var(--type-label-caps-weight) var(--type-label-caps-size)/var(--type-label-caps-leading) var(--type-label-caps-family);
letter-spacing: var(--type-label-caps-tracking);
text-transform: uppercase;
color: var(--color-ink-soft);
}
/* Display headline */
.headline {
font-family: var(--type-display-xl-family);
font-weight: var(--type-display-xl-weight);
letter-spacing: var(--type-display-xl-tracking);
font-size: clamp(120px, 12vw, 180px);
line-height: 1;
margin: 0;
}
/* Centered scene content (for #starting, #brb, #ending) */
.scene--centered { display: flex; flex-direction: column; align-items: <by variation>; justify-content: center; padding: var(--space-4xl); }
/* Webcam frame — transparent inner, framed outer */
.cam-frame {
position: absolute;
/* Position from variation: bottom-right default */
bottom: var(--space-xl);
right: var(--space-xl);
width: 480px; /* matches user-chosen size */
height: 270px;
border: 2px solid var(--color-ink);
background: transparent; /* OBS shows webcam through this */
}
.cam-frame::after {
/* Optional name plate beneath the cam frame */
content: "<streamer name> · <role>";
position: absolute;
top: 100%; left: 0;
margin-top: var(--space-xs);
font: var(--type-label-caps-weight) var(--type-label-caps-size)/var(--type-label-caps-leading) var(--type-label-caps-family);
letter-spacing: var(--type-label-caps-tracking);
text-transform: uppercase;
color: var(--color-ink);
/* Add a subtle background for legibility over screen content */
background: var(--color-surface);
padding: var(--space-2xs) var(--space-xs);
}
/* Sidebar info column on #webcam scene */
.cam-sidebar {
position: absolute;
top: var(--space-xl);
left: var(--space-xl);
max-width: 320px;
background: var(--color-surface);
padding: var(--space-md);
border: 1px solid var(--color-rule);
}
.cam-sidebar h2 { font: var(--type-headline-sm-weight) var(--type-headline-sm-size)/var(--type-headline-sm-leading) var(--type-headline-sm-family); margin: 0 0 var(--space-xs); }
.cam-sidebar .handles { font-family: var(--type-code-family); font-size: var(--type-body-sm-size); color: var(--color-ink-soft); margin: 0; line-height: 1.6; }
/* Lower-third (used both as standalone scene and inside webcam scene) */
.lower-third {
position: absolute;
bottom: 0; left: 0;
width: 100%;
background: var(--color-ink);
color: var(--color-surface);
padding: var(--space-md) var(--space-xl);
display: flex;
align-items: baseline;
gap: var(--space-xl);
box-sizing: border-box;
}
.lower-third .name { font: var(--type-headline-sm-weight) var(--type-headline-sm-size)/var(--type-headline-sm-leading) var(--type-headline-sm-family); margin: 0; }
.lower-third .role { font-family: var(--type-label-caps-family); letter-spacing: var(--type-label-caps-tracking); text-transform: uppercase; font-size: 14px; opacity: 0.75; }
.lower-third .handles { margin-left: auto; font-family: var(--type-code-family); font-size: var(--type-body-sm-size); opacity: 0.85; }
</style>
</head>
<body>
<!--
Stream Overlay — single file, hash-routed scenes
Load this file as an OBS Browser Source (1920x1080).
Switch scenes by changing the URL hash:
#starting → "Starting Soon"
#brb → "Be Right Back"
#webcam → live coding scene with webcam frame
#lower-third → just a name plate (transparent rest)
#ending → outro
Variation choices:
chrome: <picked>
type-pressure: <picked>
color: <picked>
brand-mark: <picked>
-->
<section id="scene-starting" class="scene scene--centered">
<span class="eyebrow"><Brand mark / show title></span>
<h1 class="headline">Starting Soon.</h1>
<p class="eyebrow" style="margin-top: var(--space-lg);">Stream begins shortly · grab a coffee</p>
</section>
<section id="scene-brb" class="scene scene--centered">
<span class="eyebrow"><Brand mark / show title></span>
<h1 class="headline">Right back.</h1>
</section>
<section id="scene-webcam" class="scene">
<aside class="cam-sidebar">
<span class="eyebrow"><Show title / "Now playing"></span>
<h2><Stream name></h2>
<p class="handles">
<handle 1><br>
<handle 2><br>
<handle 3>
</p>
</aside>
<div class="cam-frame"></div>
</section>
<section id="scene-lower-third" class="scene">
<div class="lower-third">
<h2 class="name"><Streamer name></h2>
<span class="role"><Role></span>
<span class="handles"><handle 1> · <handle 2></span>
</div>
</section>
<section id="scene-ending" class="scene scene--centered">
<span class="eyebrow">Stream ended</span>
<h1 class="headline">Thanks for watching.</h1>
<p class="eyebrow" style="margin-top: var(--space-lg);">Subscribe / follow for next session · <handles></p>
</section>
<script>
function activateScene() {
var hash = (window.location.hash || '#starting').slice(1);
var scenes = document.querySelectorAll('.scene');
var matched = false;
scenes.forEach(function(el) {
var isMatch = el.id === 'scene-' + hash;
el.classList.toggle('is-active', isMatch);
if (isMatch) matched = true;
});
if (!matched) {
// Fallback to starting scene if hash doesn't match
document.getElementById('scene-starting').classList.add('is-active');
}
}
window.addEventListener('hashchange', activateScene);
activateScene();
</script>
</body>
</html>After writing the file, give the user a copy-paste setup block:
Stream overlay generated at ./design/<brand-slug>/artifacts/stream-overlay.html.>
OBS setup (one-time): 1. Sources → Add → Browser 2. Local file → point tostream-overlay.html3. Width:1920, Height:10804. Add#starting(or your starting scene hash) to the file URL
>
Scene switching: create one OBS scene per hash, each with its own browser source pointing to the same file with a different URL hash: -…/stream-overlay.html#starting-…/stream-overlay.html#brb-…/stream-overlay.html#webcam-…/stream-overlay.html#lower-third-…/stream-overlay.html#ending
>
The#webcamand#lower-thirdscenes have transparent backgrounds — composite your webcam / screen capture BENEATH them in OBS.
>
Variation:<chrome>×<type>×<color>×<mark>.
#webcam and #lower-third have background: transparent (critical for OBS compositing)file://.../stream-overlay.html#brb shows ONLY the BRB sceneGoverned by three shared canonical references — read them, do not restate them:
Forbidden (fast scan — the references hold the full list):
hsl(230–280) family on a near-white surface. The single loudest AI tell.Required variation (every invocation):
Authenticity: prefer specific over generic everywhere — real datelines (not "today"), the brand's actual voice (not "build the future" filler), concrete CTAs over placeholders.
#webcam and #lower-third MUST have transparent canvas backgrounds.../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. If you find a new tell in the output, add it there.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.