| name | design-speaker-bio-card |
| description | Generate a conference / CFP speaker bio card — pixel-exact 800×600 main canvas + 400×200 compact variant in a single HTML file. Contains: name, title, headshot placeholder (circular 160px), 2-line bio, social handles, optional talk title. Used for CFP applications, conference apps, sponsor decks. Reads ./design/<brand-slug>/DESIGN.md, tokens.css, and components.html. Triggers include "speaker bio card", "CFP card", "conference bio", "/speaker-bio-card".
|
Skill: speaker-bio-card
Produces a single self-contained HTML file containing two pixel-exact canvases:
- Main card (800×600) — full speaker bio for CFP applications, conference apps, sponsor pages
- Compact card (400×200) — condensed for event programs, list views, social cards
Both render the same speaker identity at appropriate proportions. Screenshot each separately for the format the venue requires.
When to use
- User has a CFP submission, conference profile, or sponsor-deck speaker page that needs a bio card
- A
DESIGN.md exists for the brand
Inputs
- Required: brand slug, speaker name, title/role
- Required: 2-line bio (max ~30 words across the two lines combined; sentence-case ending in period per brand voice)
- Required: social handle (1 primary; optional secondary)
- Optional: talk title — if provided, gets prominent placement on the main card
- Optional: headshot URL — if not provided, the skill renders a typographic placeholder (initials in a circle)
Output
./design/<brand-slug>/artifacts/speaker-bio-card-YYYY-MM-DD-<slug>.html
Steps
1. Verify brand exists
test -f ./design/<brand-slug>/tokens.css
2. Gather the brief
Ask in one message:
1. Speaker name + title/role (e.g. "Shane Logsdon, technical product leader")
2. Bio — 2 lines, sentence-case ending in period (max ~30 words combined)
3. Social handle — primary (e.g. @shanelogsdon)
4. Optional talk title — "What I look for in operator tooling." (gets prominent placement)
5. Optional headshot URL — if omitted, renders initials in a circle as a placeholder
3. Pick variation — apply CONSISTENTLY across both cards
Speaker bio cards reward editorial restraint over visual flourish:
chrome-led — name + title + bio + handles in structured rows. Brand-earned for editorial speakers.
inverse-text — full canvas dark inversion (canonical v2 feature treatment). Reads as confident.
type-only — name + bio at maximum scale; no chrome. Strongest for speakers with strong personal brand.
headshot-led — circular headshot anchors the composition; bio orbits.
Talk title placement — if provided, treat it as the SECOND-MOST-IMPORTANT element after the name. Display weight at 28-36px.
4. Generate the HTML
Template:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title><Brand> — Speaker bio — <name></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>
<contents of tokens.css>
html, body { margin: 0; padding: 0; background: #2a2a2a; min-height: 100vh; font-family: var(--type-sans-family); }
body { display: flex; flex-direction: column; align-items: center; gap: 32px; padding: 32px 0; }
.canvas-label { font-family: var(--type-mono-family); font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase; color: rgba(255,255,255,0.7); align-self: center; }
.canvas-main {
width: 800px; height: 600px;
background: var(--color-surface);
color: var(--color-ink);
position: relative; overflow: hidden;
padding: 48px 56px;
box-sizing: border-box;
display: grid;
grid-template-rows: auto 1fr auto;
gap: 24px;
}
.canvas-compact {
width: 400px; height: 200px;
background: var(--color-surface);
color: var(--color-ink);
position: relative; overflow: hidden;
padding: 20px 24px;
box-sizing: border-box;
display: grid;
grid-template-columns: 80px 1fr;
gap: 16px;
align-items: center;
}
.headshot {
width: 160px; height: 160px;
border-radius: 999px;
background: var(--color-ink);
color: var(--color-surface);
display: grid; place-items: center;
font-family: var(--type-display-family);
font-weight: 500;
font-size: 64px;
letter-spacing: -0.02em;
}
.canvas-compact .headshot { width: 80px; height: 80px; font-size: 32px; }
.speaker-name {
font-family: var(--type-display-family);
font-weight: 500;
font-size: 48px;
line-height: 1.0;
letter-spacing: -0.018em;
margin: 0;
color: var(--color-ink);
}
.canvas-compact .speaker-name { font-size: 22px; }
.speaker-title {
font-family: var(--type-display-family);
font-weight: 600;
font-variant-caps: small-caps; font-feature-settings: 'smcp';
text-transform: lowercase;
font-size: 14px; letter-spacing: 0.08em;
color: var(--color-ink-3);
margin: 8px 0 0;
}
.canvas-compact .speaker-title { font-size: 11px; margin-top: 4px; }
.speaker-bio {
font-family: var(--type-sans-family);
font-size: 18px; line-height: 1.5;
color: var(--color-ink-soft);
margin: 0;
max-width: 56ch;
}
.talk-title {
font-family: var(--type-display-family);
font-weight: 500;
font-size: 32px;
line-height: 1.15;
letter-spacing: -0.012em;
color: var(--color-ink);
margin: 0;
border-top: 1px solid var(--color-rule);
padding-top: 20px;
}
.talk-title .accent { color: var(--color-accent); }
.talk-title-label {
font-family: var(--type-display-family); font-weight: 600;
font-variant-caps: small-caps; font-feature-settings: 'smcp';
text-transform: lowercase;
font-size: 12px; letter-spacing: 0.1em;
color: var(--color-ink-3);
margin-bottom: 10px;
}
.speaker-foot {
display: flex; justify-content: space-between; align-items: baseline;
padding-top: 16px;
border-top: 1px solid var(--color-rule);
font-family: var(--type-mono-family);
font-size: 13px; letter-spacing: 0.06em;
color: var(--color-ink-3);
}
.speaker-foot .pos { color: var(--color-ink); }
@page { size: 800px 600px; margin: 0; }
</style>
</head>
<body>
<span class="canvas-label">→ MAIN · 800×600 · CFP applications, conference apps, sponsor pages</span>
<article class="canvas-main">
<header style="display: grid; grid-template-columns: 160px 1fr; gap: 32px; align-items: center;">
<div class="headshot">[initials]</div>
<div>
<h1 class="speaker-name">[Speaker name]</h1>
<p class="speaker-title">[role / title]</p>
<p class="speaker-bio">[bio line 1 — sentence ending in period.] [bio line 2 — sentence ending in period.]</p>
</div>
</header>
<div>
<p class="talk-title-label">— current talk</p>
<h2 class="talk-title">[Talk title with optional <span class="accent">[one accent word]</span>]</h2>
</div>
<footer class="speaker-foot">
<span><span class="pos">[handle]</span> · [URL]</span>
<span>[venue or event date if known]</span>
</footer>
</article>
<span class="canvas-label">→ COMPACT · 400×200 · event programs, list views, social cards</span>
<article class="canvas-compact">
<div class="headshot">[initials]</div>
<div>
<h1 class="speaker-name">[Speaker name]</h1>
<p class="speaker-title">[role / title]</p>
<p style="margin: 6px 0 0; font-size: 11px; font-family: var(--type-mono-family); letter-spacing: 0.06em; color: var(--color-ink-3);">[handle]</p>
</div>
</article>
</body>
</html>
5. Verify
Speaker bio card at ./design/<brand-slug>/artifacts/speaker-bio-card-YYYY-MM-DD-<slug>.html.
Variation: <archetype>.
Export main: open in browser → DevTools → 800×600 viewport → screenshot the .canvas-main element.
Export compact: 400×200 viewport → screenshot .canvas-compact.
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
- Pixel exactness on both canvases.
- Headshot placeholder uses initials. If the user provides an actual headshot URL, use that; if not, the placeholder is the speaker's initials in a circle in the brand's ink color — NOT a generic icon.
- Talk title is the second-most-important element when provided. Sized prominently, may carry one type-accent word.
- No "Featured Speaker" badges or decorative eyebrows. The card stands as itself.
- Token-pure. Every visual value via
var(--*) from tokens.css.
- 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.