presentation-chef
Scannednpx machina-cli add skill sacredvoid/presentation-chef/presentation-chef --openclawPresentation Chef
Generate cinematic, Apple Keynote-style HTML presentations from any content. Single self-contained .html file with zero dependencies.
<HARD-GATE> You MUST gather all inputs interactively using AskUserQuestion before generating any HTML. Do NOT skip the input gathering phase. Do NOT generate a presentation without knowing the content, theme, and design preferences. </HARD-GATE>Process
Follow these steps exactly:
Pre-Step: Initialize Task Pipeline
Before starting Step 1, create tasks to give the user visibility into the full workflow:
TaskCreate:
subject: "Gather content source"
description: "Ask the user for their presentation content — paste, file, or topic"
activeForm: "Gathering content source"
TaskCreate:
subject: "Select theme & customize design"
description: "Analyze content, recommend a theme, and gather design customization preferences"
activeForm: "Selecting theme and design preferences"
TaskCreate:
subject: "Plan slide structure"
description: "Map content to slide types and confirm the structure with user"
activeForm: "Planning slide structure"
TaskCreate:
subject: "Build presentation"
description: "Generate the complete HTML presentation with slides, navigation, and effects"
activeForm: "Building presentation"
Update each task to in_progress when starting that phase, and completed when done:
- "Gather content source" → covers Step 1
- "Select theme & customize design" → covers Steps 2-3
- "Plan slide structure" → covers Step 4
- "Build presentation" → covers Steps 5-6
Step 1: Gather Content
TaskUpdate: Mark "Gather content source" → in_progress
Ask the user for their content source using AskUserQuestion:
AskUserQuestion:
question: "What content should I turn into a presentation?"
header: "Content"
options:
- label: "Paste or describe it"
description: "I'll type/paste content or describe what I want in the presentation"
- label: "Read from a file"
description: "I have a markdown file, text file, or other document to convert"
- label: "Generate from topic"
description: "Give me a topic and I'll create both content and design"
multiSelect: false
If the user selects "Read from a file", ask for the file path and use the Read tool to get the content. If the user selects "Generate from topic", ask what the topic is and what audience/purpose it serves. If the user pastes content, analyze it to understand its structure.
TaskUpdate: Mark "Gather content source" → completed
Step 2: Analyze Content & Suggest Theme
TaskUpdate: Mark "Select theme & customize design" → in_progress
After receiving content, analyze it to determine:
- Content type: pitch deck, portfolio, product launch, educational, report, personal story, etc.
- Tone: professional, creative, technical, casual, dramatic
- Slide count: how many slides the content naturally breaks into
Then present theme options interactively:
AskUserQuestion:
question: "What visual theme should the presentation use?"
header: "Theme"
options:
- label: "Dark Cinematic (Recommended)"
description: "[AI reasoning why this fits the content]. Pure black bg, ambient orbs, glassmorphism cards, Apple blue/purple accents"
markdown: |
DARK CINEMATIC
──────────────────────────────
Background: #000000 (pure black)
Text: #ffffff / #86868b
Accent 1: #0071e3 (Apple blue)
Accent 2: #a855f7 (purple)
Warm: #ff6723 (orange)
Success: #30d158 (green)
Effects: Ambient orbs, grain overlay
Glassmorphism cards
Gradient text on headlines
Font: SF Pro / system sans-serif
Animations: Cinematic (900ms, spring easing)
- label: "Light Minimal"
description: "Clean, Chronicle-style white canvas with bold typography and single accent color"
markdown: |
LIGHT MINIMAL
──────────────────────────────
Background: #ffffff / #fafafa
Text: #1d1d1f / #86868b
Accent: #0071e3 (or content-matched)
Border: #e5e5e5
Effects: Subtle shadows, no orbs
Clean card borders
Understated elegance
Font: Geist / clean geometric sans
Animations: Smooth (600ms, ease-out)
- label: "Warm Editorial"
description: "Magazine-style warmth with serif typography and rich earth tones"
markdown: |
WARM EDITORIAL
──────────────────────────────
Background: #1a1210 / #f5efe8
Text: #f5efe8 / #a89585
Accent: #e8734a (coral)
Secondary: #c4956a (warm gold)
Effects: Warm ambient glow
Paper-like texture
Editorial layouts
Font: Playfair Display + Source Sans
Animations: Elegant (800ms, smooth)
- label: "Neon Cyberpunk"
description: "High-energy tech aesthetic with neon accents on deep dark backgrounds"
markdown: |
NEON CYBERPUNK
──────────────────────────────
Background: #0a0a1a / #0d1117
Text: #e0e0ff / #6b7280
Accent 1: #00f0ff (cyan)
Accent 2: #ff00aa (magenta)
Glow: #7c3aed (purple)
Effects: Neon glow borders
Scanline overlay
Matrix-style grid bg
Font: JetBrains Mono + Space Grotesk
Animations: Snappy (500ms, sharp easing)
multiSelect: false
IMPORTANT: Customize the recommendation text based on the actual content analyzed. Don't use generic descriptions. For example: "Since this is a startup pitch, Dark Cinematic will make your numbers feel impactful and your product feel premium."
Step 3: Customize Design
Ask about specific design preferences:
AskUserQuestion:
question: "Any design customizations?"
header: "Customize"
options:
- label: "Use defaults"
description: "The theme preset looks great as-is, no changes needed"
- label: "Custom accent color"
description: "I want to use a specific brand color as the primary accent"
- label: "Custom fonts"
description: "I want specific fonts (e.g., Google Fonts or system fonts)"
- label: "Multiple customizations"
description: "I have specific requirements for colors, fonts, or effects"
multiSelect: false
If the user wants customizations, ask follow-up questions one at a time about each customization.
TaskUpdate: Mark "Select theme & customize design" → completed
Step 4: Map Content to Slides
TaskUpdate: Mark "Plan slide structure" → in_progress
Analyze the content and map it to the appropriate slide types. Present the slide plan:
AskUserQuestion:
question: "Here's my proposed slide structure. Does this look right?"
header: "Structure"
options:
- label: "Looks perfect"
description: "Generate the presentation with this structure"
- label: "Adjust order"
description: "I want to reorder some slides"
- label: "Add/remove slides"
description: "I want to add or remove specific slides"
- label: "Different approach"
description: "I want a different overall structure"
multiSelect: false
Before asking, present the slide plan as a numbered list in your message text. Example:
Slide 1: Hero — "Company Name" + tagline
Slide 2: Stats — 3 key metrics with count-up
Slide 3: Chapter — "The Problem"
Slide 4: Content Card — Problem description
...
TaskUpdate: Mark "Plan slide structure" → completed
Step 5: Ask Output Location
AskUserQuestion:
question: "Where should I save the presentation?"
header: "Output"
options:
- label: "Current directory"
description: "Save as presentation.html in the current working directory"
- label: "Custom path"
description: "I'll specify the exact file path and name"
- label: "Desktop"
description: "Save to ~/Desktop/ for easy access"
multiSelect: false
Step 6: Generate the Presentation (Batched with Progress Tracking)
When entering this step, mark the "Build presentation" high-level task as in_progress.
6a: Create Build Sub-Tasks
Based on the confirmed slide plan, create granular build tasks. Group slides into batches of 3-4:
TaskCreate:
subject: "Set up HTML structure & CSS theme"
description: "Create HTML skeleton, CSS reset, theme variables, effects (grain/orbs), slide system, reveal animations, typography, responsive breakpoints, print styles"
activeForm: "Setting up document structure and CSS"
# For each batch of 3-4 slides, create a task:
TaskCreate:
subject: "Build slides [X]-[Y]: [slide types]"
description: "Generate HTML for: Slide X ([type] — [title]), Slide X+1 ([type] — [title]), ..."
activeForm: "Building slides [X] through [Y]"
# Example for a 12-slide presentation:
# "Build slides 1-4: Hero, Stats, Chapter, Content Card"
# "Build slides 5-8: Feature Grid, Timeline, Comparison, Quote"
# "Build slides 9-12: Data, Split Screen, List, CTA"
TaskCreate:
subject: "Add navigation, controls & speaker notes"
description: "Progress bar, nav dots, keyboard hints, speaker notes sidebar with talking points for every slide, controls bar"
activeForm: "Adding navigation and speaker notes"
TaskCreate:
subject: "Wire up JavaScript engine"
description: "Slide navigation, reveal animations, count-up, data bars, keyboard/mouse/touch handlers, parallax, loading screen, notes toggle, PDF export"
activeForm: "Wiring up JavaScript engine"
TaskCreate:
subject: "Run quality checklist & save file"
description: "Verify all 23 quality checks pass, then write the final .html file"
activeForm: "Running quality checklist and saving"
6b: Execute Build Pipeline
Work through each task sequentially. For every task:
TaskUpdate→in_progressbefore you start working on it- Generate that section of the presentation
TaskUpdate→completedwhen done- Move to the next task
Slide batch details: When building a slide batch, generate the HTML for all slides in that batch. Each slide must include:
- The slide container
<div>with correctdata-slideindex - Background variant class
- Ambient orbs (if dark theme)
- All content elements wrapped in
reveal-elementwith sequential delays - Proper slide type pattern from the Design System Reference below
6c: Assemble & Write
After all build tasks are complete, assemble the full HTML document in this order:
- Document structure (head, meta,
<style>open) - All CSS (reset, theme, effects, slides, typography, responsive, print)
<body>open, loading screen, grain overlay (if dark theme)- Progress bar, nav dots, keyboard hint
- Speaker notes sidebar (all slides)
- Controls bar
<div class="slide-container">with all slide batches in order<script>with full JS engine- Close body/html
Use the Write tool to save the assembled HTML to the confirmed output path.
Mark the "Build presentation" high-level task as completed, then mark "Run quality checklist & save file" as completed.
Tell the user the file path and suggest opening it in a browser.
Design System Reference
When generating the HTML presentation, follow these specifications exactly.
Document Structure
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>[Presentation Title]</title>
<style>/* ALL CSS INLINE */</style>
</head>
<body>
<!-- Loading Screen -->
<!-- Grain Overlay (if dark theme) -->
<!-- Progress Bar -->
<!-- Navigation Dots -->
<!-- Keyboard Hint -->
<!-- Speaker Notes Sidebar -->
<!-- Controls Bar (Notes T, PDF P) -->
<!-- Slide Container -->
<script>/* ALL JS INLINE */</script>
</body>
</html>
Everything must be inline. Zero external dependencies. No CDN links. No Google Fonts links (use system font stacks or embed @font-face with base64 only if absolutely necessary for a specific requested font).
CSS Foundation
Reset & Base
*, *::before, *::after {
margin: 0; padding: 0; box-sizing: border-box;
}
:root {
/* Theme tokens - set these per theme */
--bg-primary: #000000;
--bg-secondary: #0a1628;
--text-primary: #ffffff;
--text-secondary: #86868b;
--text-muted: #6e6e73;
--accent-1: #0071e3;
--accent-1-light: #2997ff;
--accent-2-start: #6e3aff;
--accent-2-end: #a855f7;
--accent-warm: #ff6723;
--accent-pink: #ff375f;
--accent-green: #30d158;
--accent-teal: #64d2ff;
--gray-100: #f5f5f7;
--gray-200: #d2d2d7;
--gray-400: #86868b;
--gray-600: #6e6e73;
--gray-800: #1d1d1f;
--card-bg: rgba(255, 255, 255, 0.04);
--card-border: rgba(255, 255, 255, 0.08);
--card-blur: 40px;
--transition-smooth: cubic-bezier(0.25, 0.46, 0.45, 0.94);
--transition-spring: cubic-bezier(0.175, 0.885, 0.32, 1.275);
--transition-cinematic: cubic-bezier(0.16, 1, 0.3, 1);
--slide-duration: 900ms;
--reveal-stagger: 150ms;
}
html { scroll-behavior: auto; overflow: hidden; background: var(--bg-primary); }
body {
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Inter', 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
background: var(--bg-primary);
color: var(--text-primary);
overflow: hidden;
height: 100vh;
width: 100vw;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
Light Theme Override
For light themes, override:
:root {
--bg-primary: #ffffff;
--bg-secondary: #fafafa;
--text-primary: #1d1d1f;
--text-secondary: #86868b;
--text-muted: #aeaeb2;
--card-bg: rgba(0, 0, 0, 0.03);
--card-border: rgba(0, 0, 0, 0.08);
/* Adjust accent colors for contrast on light */
}
Effects
Grain Overlay (dark themes only)
.grain-overlay {
position: fixed;
top: -50%; left: -50%;
width: 200%; height: 200%;
pointer-events: none;
z-index: 9998;
opacity: 0.035;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
animation: grainShift 0.5s steps(3) infinite;
}
@keyframes grainShift {
0% { transform: translate(0, 0); }
33% { transform: translate(-2px, 1px); }
66% { transform: translate(1px, -1px); }
100% { transform: translate(0, 0); }
}
Ambient Orbs (dark themes)
.ambient-orb {
position: absolute;
border-radius: 50%;
filter: blur(120px);
opacity: 0.15;
pointer-events: none;
animation: orbFloat 12s ease-in-out infinite alternate;
}
@keyframes orbFloat {
0% { transform: translate(0, 0) scale(1); }
100% { transform: translate(30px, -20px) scale(1.1); }
}
Create 2-3 orbs per slide with different colors matching the theme. Vary sizes (400-600px), positions, animation delays.
Hero Glow Ring
.hero-glow {
position: absolute;
width: 600px; height: 600px;
border-radius: 50%;
background: radial-gradient(circle, rgba(accent1, 0.08) 0%, rgba(accent2, 0.04) 40%, transparent 70%);
pointer-events: none;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
animation: glowPulse 6s ease-in-out infinite alternate;
}
Slide System
Container & Transitions
.slide-container {
position: fixed; inset: 0;
width: 100vw; height: 100vh;
}
.slide {
position: absolute; inset: 0;
width: 100%; height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40px;
opacity: 0;
visibility: hidden;
transform: scale(0.95) translateY(30px);
transition: opacity var(--slide-duration) var(--transition-cinematic),
transform var(--slide-duration) var(--transition-cinematic),
visibility 0s linear var(--slide-duration);
will-change: opacity, transform;
overflow-y: auto;
overflow-x: hidden;
}
.slide.active {
opacity: 1;
visibility: visible;
transform: scale(1) translateY(0);
transition: opacity var(--slide-duration) var(--transition-cinematic),
transform var(--slide-duration) var(--transition-cinematic),
visibility 0s linear 0s;
}
.slide.exiting-up {
opacity: 0; visibility: hidden;
transform: scale(1.05) translateY(-50px);
}
.slide.exiting-down {
opacity: 0; visibility: hidden;
transform: scale(0.9) translateY(50px);
}
Slide Background Variants
For dark themes, create gradient backgrounds per slide:
.slide--dark { background: var(--bg-primary); }
.slide--gradient-blue { background: linear-gradient(145deg, #000 0%, #0a1628 40%, #0d2137 70%, #0a0a2e 100%); }
.slide--gradient-purple { background: linear-gradient(145deg, #000 0%, #1a0a2e 40%, #2d1b4e 60%, #0a0a2e 100%); }
.slide--gradient-warm { background: linear-gradient(145deg, #000 0%, #2e1a0a 40%, #3d1f0f 60%, #1a0a00 100%); }
For light themes, use subtle gradients:
.slide--light { background: var(--bg-primary); }
.slide--gradient-soft { background: linear-gradient(145deg, #fff 0%, #f8f9fa 50%, #f0f0f5 100%); }
Reveal Animations
.reveal-element {
opacity: 0;
transform: translateY(40px);
transition: opacity 0.8s var(--transition-cinematic),
transform 0.8s var(--transition-cinematic);
}
.reveal-element.revealed {
opacity: 1; transform: translateY(0);
}
/* Staggered delays */
.reveal-element[data-delay="1"] { transition-delay: 0.15s; }
.reveal-element[data-delay="2"] { transition-delay: 0.3s; }
.reveal-element[data-delay="3"] { transition-delay: 0.45s; }
/* Continue up to data-delay="12" at 0.15s increments */
Wrap every content element in a <div class="reveal-element" data-delay="N"> with sequential delay values per slide.
Slide Types — HTML Patterns
1. Hero Slide
<div class="slide slide--dark active" data-slide="0">
<div class="hero-glow"></div>
<div class="reveal-element" data-delay="0">
<h1 class="hero-name">[Title]</h1>
</div>
<div class="reveal-element" data-delay="2">
<p class="hero-subtitle">[Subtitle with separator spans]</p>
</div>
<div class="reveal-element" data-delay="4">
<div class="divider-line"></div>
</div>
<div class="reveal-element" data-delay="5">
<p class="hero-location">[Location or tagline]</p>
</div>
</div>
Typography:
.hero-name {
font-size: clamp(48px, 10vw, 120px);
font-weight: 700;
letter-spacing: -0.03em;
line-height: 1;
text-align: center;
background: linear-gradient(135deg, var(--text-primary) 0%, var(--gray-200) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.hero-subtitle {
font-size: clamp(18px, 3vw, 32px);
font-weight: 400;
color: var(--text-secondary);
text-align: center;
margin-top: 24px;
letter-spacing: 0.02em;
}
2. Stats Slide
<div class="slide slide--gradient-blue" data-slide="N">
<div class="ambient-orb ambient-orb--accent1"></div>
<div class="reveal-element" data-delay="0">
<p class="section-label">[Label text]</p>
</div>
<div class="stats-grid">
<div class="stat-item reveal-element" data-delay="1">
<div class="stat-number mega-number--accent1"><span class="count-up" data-target="[N]">0</span>[suffix]</div>
<div class="stat-label">[Label]</div>
</div>
<!-- Repeat for each stat (2-4 stats ideal) -->
</div>
</div>
Stats grid: grid-template-columns: repeat(2, 1fr), gap 48px 64px, max-width 900px.
Mega numbers: font-size: clamp(48px, 8vw, 96px), weight 800, gradient text with matching glow.
Count-up JS animates from 0 to target with ease-out cubic easing over 1200ms.
3. Chapter Divider Slide
<div class="slide slide--gradient-[color]" data-slide="N">
<div class="ambient-orb"></div>
<div class="reveal-element" data-delay="0">
<p class="section-label">[Small label]</p>
</div>
<div class="reveal-element" data-delay="1">
<h2 class="section-title">[Big title with gradient text]</h2>
</div>
<div class="reveal-element" data-delay="2">
<p class="section-subtitle">[Supporting text, max 2 lines]</p>
</div>
</div>
Section title: font-size: clamp(36px, 7vw, 96px), weight 700, tight tracking.
4. Content Card Slide
<div class="slide slide--gradient-[color]" data-slide="N">
<div class="ambient-orb"></div>
<div class="reveal-element" data-delay="0">
<p class="section-label">[Context label]</p>
</div>
<div class="reveal-element" data-delay="1">
<h2 class="section-title" style="font-size: clamp(28px, 5vw, 56px);">[Title]</h2>
</div>
<div class="experience-card reveal-element" data-delay="2">
<div class="card-title">[Title]</div>
<div class="card-subtitle">[Subtitle in accent color]</div>
<div class="card-meta">[Date/location/metadata]</div>
<div class="card-body">
<ul>
<li>[Point 1]</li>
<li>[Point 2]</li>
</ul>
</div>
</div>
</div>
Card: background: var(--card-bg), backdrop-filter: blur(var(--card-blur)), border: 1px solid var(--card-border), border-radius: 24px, padding clamp(32px, 4vw, 56px).
Top highlight: ::before pseudo-element with gradient line.
Bullet points: custom dot (6px circle in accent color) via ::before.
5. Feature Grid Slide
<div class="slide slide--gradient-deep" data-slide="N">
<div class="reveal-element" data-delay="0">
<p class="section-label">[Label]</p>
</div>
<div class="reveal-element" data-delay="1">
<h2 class="section-title">[Title]</h2>
</div>
<div class="tech-grid">
<div class="tech-chip tech-chip--[category] reveal-element" data-delay="2">
[Item name]
<span class="tech-category-label">[Category]</span>
</div>
<!-- Repeat -->
</div>
</div>
Grid: repeat(auto-fit, minmax(120px, 1fr)), gap 16px. Chips have hover lift + scale, radial gradient glow on hover.
6. Timeline Slide
<div class="slide slide--gradient-[color]" data-slide="N">
<div class="reveal-element" data-delay="0">
<p class="section-label">[Label]</p>
</div>
<div class="reveal-element" data-delay="1">
<h2 class="section-title">[Title]</h2>
</div>
<div class="timeline">
<div class="timeline-item reveal-element" data-delay="2">
<div class="timeline-marker"></div>
<div class="timeline-content">
<div class="timeline-date">[Date]</div>
<div class="timeline-title">[Title]</div>
<div class="timeline-desc">[Description]</div>
</div>
</div>
<!-- Repeat -->
</div>
</div>
Timeline: vertical line (2px, accent gradient) with circular markers (12px). Content cards to the right. Alternating layout on desktop.
.timeline {
position: relative;
max-width: 800px;
width: 100%;
margin-top: 32px;
padding-left: 40px;
}
.timeline::before {
content: '';
position: absolute;
left: 16px;
top: 0;
bottom: 0;
width: 2px;
background: linear-gradient(to bottom, var(--accent-1), var(--accent-2-end));
}
.timeline-item {
position: relative;
margin-bottom: 32px;
padding-left: 24px;
}
.timeline-marker {
position: absolute;
left: -32px;
top: 6px;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent-1);
border: 2px solid var(--bg-primary);
box-shadow: 0 0 0 4px rgba(var(--accent-1-rgb), 0.2);
}
7. Comparison Slide
<div class="slide slide--gradient-[color]" data-slide="N">
<div class="reveal-element" data-delay="0">
<p class="section-label">[Label]</p>
</div>
<div class="reveal-element" data-delay="1">
<h2 class="section-title">[Title]</h2>
</div>
<div class="comparison-grid">
<div class="comparison-col reveal-element" data-delay="2">
<h3 class="comparison-heading">[Side A]</h3>
<ul class="comparison-list">
<li>[Point]</li>
</ul>
</div>
<div class="comparison-divider reveal-element" data-delay="3"></div>
<div class="comparison-col reveal-element" data-delay="4">
<h3 class="comparison-heading">[Side B]</h3>
<ul class="comparison-list">
<li>[Point]</li>
</ul>
</div>
</div>
</div>
Two-column grid with vertical divider. Cards have frosted glass background.
8. Quote Slide
<div class="slide slide--dark" data-slide="N">
<div class="hero-glow" style="opacity: 0.3;"></div>
<div class="reveal-element" data-delay="0">
<blockquote class="quote-text">"[Quote text]"</blockquote>
</div>
<div class="reveal-element" data-delay="2">
<p class="quote-attribution">— [Name], [Title]</p>
</div>
</div>
Quote: font-size: clamp(24px, 4vw, 48px), weight 400, italic, line-height 1.4. Center aligned with max-width 800px.
9. Image Slide
<div class="slide slide--image" data-slide="N" style="background: linear-gradient(rgba(0,0,0,0.6), rgba(0,0,0,0.8)), url('[base64 or path]') center/cover;">
<div class="reveal-element" data-delay="0">
<p class="section-label">[Label]</p>
</div>
<div class="reveal-element" data-delay="1">
<h2 class="section-title">[Overlay text]</h2>
</div>
</div>
Note: For truly self-contained files, images should be base64-encoded inline if the user provides them. Otherwise use descriptive gradient backgrounds as visual stand-ins.
10. Data Slide
<div class="slide slide--gradient-[color]" data-slide="N">
<div class="reveal-element" data-delay="0">
<p class="section-label">[Label]</p>
</div>
<div class="reveal-element" data-delay="1">
<h2 class="section-title">[Title]</h2>
</div>
<div class="data-bars">
<div class="data-bar-item reveal-element" data-delay="2">
<div class="data-bar-label">[Label]</div>
<div class="data-bar-track">
<div class="data-bar-fill" style="--bar-width: [N]%;" data-value="[N]%"></div>
</div>
</div>
<!-- Repeat -->
</div>
</div>
CSS-only animated bars. Fill animates width from 0 to --bar-width on reveal. Gradient fill matching theme accent.
.data-bar-track {
height: 8px;
background: var(--card-bg);
border-radius: 4px;
overflow: hidden;
flex: 1;
}
.data-bar-fill {
height: 100%;
width: 0;
background: linear-gradient(90deg, var(--accent-1), var(--accent-2-end));
border-radius: 4px;
transition: width 1.2s var(--transition-cinematic);
}
.data-bar-fill.revealed { width: var(--bar-width); }
11. Split Screen Slide
<div class="slide slide--gradient-[color]" data-slide="N">
<div class="split-layout">
<div class="split-text reveal-element" data-delay="0">
<p class="section-label">[Label]</p>
<h2 class="section-title" style="text-align: left; font-size: clamp(28px, 5vw, 56px);">[Title]</h2>
<p class="section-subtitle" style="text-align: left;">[Description]</p>
</div>
<div class="split-visual reveal-element" data-delay="2">
<!-- Visual content: card, graphic, or placeholder -->
</div>
</div>
</div>
.split-layout {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 64px;
max-width: 1100px;
width: 100%;
align-items: center;
}
@media (max-width: 768px) {
.split-layout { grid-template-columns: 1fr; gap: 32px; }
}
12. List / Achievements Slide
<div class="slide slide--dark" data-slide="N">
<div class="reveal-element" data-delay="0">
<h2 class="section-title">[Title]</h2>
</div>
<div class="achievements-list">
<div class="achievement-item reveal-element" data-delay="1">
<div class="achievement-icon">[emoji or icon]</div>
<div class="achievement-content">
<div class="achievement-title">[Title]</div>
<div class="achievement-desc">[Description]</div>
</div>
</div>
<!-- Repeat -->
</div>
</div>
Icon container: 48x48, rounded 12px, frosted glass bg. Flex row with 20px gap.
13. CTA / Contact Slide
<div class="slide slide--gradient-[color]" data-slide="N">
<div class="reveal-element" data-delay="0">
<div class="available-badge">
<span class="available-pulse"></span>
[Status text]
</div>
</div>
<div class="reveal-element" data-delay="1">
<h2 class="section-title">[CTA headline]</h2>
</div>
<div class="reveal-element" data-delay="2">
<p class="section-subtitle">[Supporting text]</p>
</div>
<div class="contact-links reveal-element" data-delay="3">
<a href="[url]" class="contact-link contact-link--primary">
<svg>...</svg> [Label]
</a>
<a href="[url]" class="contact-link">
<svg>...</svg> [Label]
</a>
</div>
</div>
Pill-shaped links: border-radius: 100px, frosted glass bg, hover lift.
Available badge: green pulse animation, pill shape, green tint bg.
Navigation Components
Progress Bar
.progress-bar {
position: fixed; top: 0; left: 0;
height: 2px;
background: linear-gradient(90deg, var(--accent-1), var(--accent-2-end));
z-index: 200;
transition: width 0.6s var(--transition-cinematic);
box-shadow: 0 0 10px rgba(accent1, 0.5);
}
Navigation Dots
Fixed right side, vertical, 8px circles. Active dot: white, scale 1.4, glow shadow. Hover shows label via ::before content.
Keyboard Hint
Fixed bottom center. Shows arrow keys and space. Hidden class after first interaction. Bounce arrow animation.
JavaScript Engine
The JS engine handles:
- Slide navigation —
goToSlide(index, direction)with transition locking - Reveal animations — trigger
.revealedclass on active slide elements - Count-up animations —
requestAnimationFramewith ease-out cubic - Data bar animations — trigger fill width on reveal
- Dot/progress updates — sync with current slide
- Keyboard navigation — arrows, space, page up/down, home/end, escape, T (notes), P (pdf)
- Mouse wheel — debounced with accumulator (threshold 50, debounce 80ms)
- Touch — swipe detection with 50px threshold
- Parallax — mousemove on hero glow and ambient orbs
- Loading screen — fade out after 600ms on window load
- Speaker notes toggle —
toggleNotes()opens/closes sidebar,updateNotes()syncs content to current slide - PDF export —
exportPdf()snaps all count-up numbers todata-targetvalues and data bars to full width before callingwindow.print(), ensuring animated values render correctly in the PDF
Key constants:
const TOTAL_SLIDES = [number];
const TRANSITION_DURATION = 900;
const DEBOUNCE_MS = 80;
const COUNT_DURATION = 1200;
const WHEEL_THRESHOLD = 50;
Use an IIFE wrapper. No external dependencies. All event listeners with proper passive flags.
Responsive Breakpoints
- 768px: Single columns, reduced gaps, hidden dot labels, smaller padding
- 480px: Further simplified grids, hidden keyboard hints
- Touch devices: Disable hover transforms via
@media (hover: none)
Speaker Notes Sidebar (Press T)
Every presentation MUST include a speaker notes sidebar. The sidebar:
- Slides in from the left when pressing
Tkey or clicking the Notes button - Frosted glass panel (
rgba(10,10,20,0.92)bg,backdrop-filter: blur(30px), 340px wide) - Has a sticky header with "Talking Points" title, close button, and "Slide X of N" label
- Contains a
<div class="note-content" data-note="N">for each slide with talking points - Only the
.note-content.activematching current slide is shown (display block/none) - When open, the main slide container shifts right and scales down:
transform: translateX(170px) scale(0.88) - Progress bar left offset adjusts:
left: 340px - Toggle via
body.notes-openclass
Talking points content: Write 2-3 paragraphs per slide with:
- Bold opener — what to emphasize on this slide
- Key talking points in natural speaking language (not bullet points)
- A
.note-tipcallout for delivery tips (when to pause, make eye contact, etc.)
Important: Call updateNotes() inside goToSlide() when notesOpen is true.
Controls Bar
Fixed bottom-right, two buttons:
<div class="controls-bar">
<button class="control-btn" id="btnNotes">
<svg><!-- document icon --></svg> Notes <span class="key-badge">T</span>
</button>
<button class="control-btn" id="btnPdf">
<svg><!-- download icon --></svg> PDF <span class="key-badge">P</span>
</button>
</div>
Buttons: border-radius: 10px, frosted glass bg, 12px font. Key badge: 20x20 rounded square.
Hide controls bar on mobile (@media (max-width: 480px) { .controls-bar { display: none; } }).
PDF / Print Export (Press P)
Every presentation MUST include PDF export via window.print() with a print stylesheet.
Critical: Count-up number fix. Before printing, the exportPdf() function MUST:
- Snap ALL
.count-upelements to theirdata-targetvalues (settextContent = getAttribute('data-target')) - Add
.revealedclass to ALL.data-bar-fillelements so bars show at full width - Close speaker notes if open
- Call
window.print()after a 100ms delay to let CSS settle
function exportPdf() {
document.querySelectorAll('.count-up').forEach(function(el) {
el.textContent = el.getAttribute('data-target');
});
document.querySelectorAll('.data-bar-fill').forEach(function(el) {
el.classList.add('revealed');
});
var wasNotesOpen = notesOpen;
if (notesOpen) toggleNotes();
setTimeout(function() {
window.print();
if (wasNotesOpen) setTimeout(toggleNotes, 300);
}, 100);
}
Print stylesheet (@media print):
@media print {
*, *::before, *::after { animation: none !important; transition: none !important; }
html, body { overflow: visible !important; height: auto !important; width: auto !important; }
.loading-screen, .grain-overlay, .progress-bar, .nav-dots,
.keyboard-hint, .controls-bar, .speaker-notes,
.ambient-orb, .hero-glow { display: none !important; }
.slide-container { position: static !important; transform: none !important; }
.slide {
position: relative !important;
opacity: 1 !important; visibility: visible !important; transform: none !important;
width: 100% !important; height: 100vh !important;
page-break-after: always; break-after: page;
page-break-inside: avoid; break-inside: avoid;
overflow: hidden !important;
}
.slide:last-child { page-break-after: auto; }
.reveal-element { opacity: 1 !important; transform: none !important; }
.data-bar-fill { width: var(--bar-width) !important; }
}
@page { size: landscape; margin: 0; }
Typography Scale
| Element | Size | Weight | Tracking |
|---|---|---|---|
| Hero name | clamp(48px, 10vw, 120px) | 700 | -0.03em |
| Section title | clamp(36px, 7vw, 96px) | 700 | -0.03em |
| Mega number | clamp(64px, 15vw, 180px) | 800 | -0.04em |
| Section label | clamp(14px, 1.5vw, 18px) | 600 | 0.15em, uppercase |
| Body text | clamp(14px, 1.8vw, 18px) | 400 | normal |
| Subtitle | clamp(16px, 2.5vw, 28px) | 400 | normal |
| Chip text | clamp(12px, 1.4vw, 15px) | 500 | normal |
Quality Checklist
Before outputting the final HTML, verify:
- All CSS is inline in a single
<style>tag - All JS is inline in a single
<script>tag - No external dependencies or CDN links
- Every content element wrapped in
reveal-elementwith sequential delays - Navigation dots count matches total slides
-
TOTAL_SLIDESconstant matches actual slide count - Progress bar gradient matches theme
- All
data-slideattributes are sequential from 0 - Count-up elements have
data-targetset - Cards have
::beforetop highlight gradient - Responsive styles handle 768px and 480px breakpoints
- Touch prevention (
touchmovepreventDefault) is included - Loading screen included and auto-hides
-
will-changehints on slide elements - Grain overlay included (dark themes) or omitted (light themes)
- Ambient orbs have varied positions, sizes, and animation delays
- Speaker notes sidebar included with talking points for EVERY slide
- Each
.note-content[data-note="N"]matches a slide (0-indexed) - Controls bar with Notes (T) and PDF (P) buttons is included
-
exportPdf()snaps count-up values to targets beforewindow.print() -
@media printstylesheet hides UI chrome and shows all slides as pages -
@page { size: landscape; margin: 0; }is set -
updateNotes()is called ingoToSlide()when notes are open - T key toggles notes, P key triggers PDF export, Escape closes notes
Common SVG Icons for Contact Links
Include these inline SVGs as needed:
- Email:
<path d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/> - LinkedIn:
<path d="M19 3a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14m-.5 15.5v-5.3a3.26 3.26 0 0 0-3.26-3.26c-.85 0-1.84.52-2.32 1.3v-1.11h-2.79v8.37h2.79v-4.93c0-.77.62-1.4 1.39-1.4a1.4 1.4 0 0 1 1.4 1.4v4.93h2.79M6.88 8.56a1.68 1.68 0 0 0 1.68-1.68c0-.93-.75-1.69-1.68-1.69a1.69 1.69 0 0 0-1.69 1.69c0 .93.76 1.68 1.69 1.68m1.39 9.94v-8.37H5.5v8.37h2.77z"/> - GitHub:
<path d="M12 2A10 10 0 0 0 2 12c0 4.42 2.87 8.17 6.84 9.5.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34-.46-1.16-1.11-1.47-1.11-1.47-.91-.62.07-.6.07-.6 1 .07 1.53 1.03 1.53 1.03.87 1.52 2.34 1.07 2.91.83.09-.65.35-1.09.63-1.34-2.22-.25-4.55-1.11-4.55-4.92 0-1.11.38-2 1.03-2.71-.1-.25-.45-1.29.1-2.64 0 0 .84-.27 2.75 1.02.79-.22 1.65-.33 2.5-.33.85 0 1.71.11 2.5.33 1.91-1.29 2.75-1.02 2.75-1.02.55 1.35.2 2.39.1 2.64.65.71 1.03 1.6 1.03 2.71 0 3.82-2.34 4.66-4.57 4.91.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0 0 12 2z"/> - Twitter/X:
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/> - Website:
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/>
All SVGs use viewBox="0 0 24 24" and fill="currentColor" at 18x18px.
Theme Definitions
When the user selects a theme, apply these complete variable sets:
Dark Cinematic
--bg-primary: #000000
--text-primary: #ffffff
--text-secondary: #86868b
--accent-1: #0071e3
--accent-1-light: #2997ff
--accent-2-start: #6e3aff
--accent-2-end: #a855f7
--accent-warm: #ff6723
--accent-green: #30d158
--card-bg: rgba(255, 255, 255, 0.04)
--card-border: rgba(255, 255, 255, 0.08)
Font: -apple-system, BlinkMacSystemFont, SF Pro, system
Effects: grain overlay, ambient orbs, hero glow
Light Minimal
--bg-primary: #ffffff
--bg-secondary: #fafafa
--text-primary: #1d1d1f
--text-secondary: #86868b
--text-muted: #aeaeb2
--accent-1: #0071e3
--card-bg: rgba(0, 0, 0, 0.03)
--card-border: rgba(0, 0, 0, 0.08)
Font: 'Geist', -apple-system, system
Effects: subtle shadows, no grain, no orbs
Warm Editorial
--bg-primary: #1a1210
--text-primary: #f5efe8
--text-secondary: #a89585
--accent-1: #e8734a
--accent-2-end: #c4956a
--card-bg: rgba(245, 239, 232, 0.04)
--card-border: rgba(245, 239, 232, 0.08)
Font: 'Playfair Display', Georgia, serif (headings) + 'Source Sans 3', system (body)
Effects: warm grain, warm orbs, paper texture
Neon Cyberpunk
--bg-primary: #0a0a1a
--text-primary: #e0e0ff
--text-secondary: #6b7280
--accent-1: #00f0ff
--accent-2-end: #ff00aa
--accent-warm: #7c3aed
--card-bg: rgba(0, 240, 255, 0.04)
--card-border: rgba(0, 240, 255, 0.12)
Font: 'JetBrains Mono', monospace (headings) + 'Space Grotesk', system (body)
Effects: neon glow borders, scanline overlay, grid background
Earth Organic
--bg-primary: #faf8f5
--text-primary: #2d2a26
--text-secondary: #7a7470
--accent-1: #2d6a4f
--accent-2-end: #b07d62
--card-bg: rgba(45, 106, 79, 0.04)
--card-border: rgba(45, 106, 79, 0.1)
Font: 'DM Sans', system (headings + body)
Effects: no grain, organic blob shapes instead of orbs, warm shadows
Content-Aware AI Decisions
When analyzing content, use these heuristics to suggest themes and slide types:
| Content Type | Suggested Theme | Typical Slides |
|---|---|---|
| Startup pitch | Dark Cinematic | Hero, Stats, Chapter, Content Card, Feature Grid, CTA |
| Portfolio | Dark Cinematic or Light Minimal | Hero, Stats, Chapter, Content Card x N, Feature Grid, List, CTA |
| Product launch | Neon Cyberpunk or Dark Cinematic | Hero, Chapter, Split, Feature Grid, Comparison, Stats, CTA |
| Educational | Light Minimal or Earth Organic | Hero, Chapter, Content Card, Data, Timeline, List, CTA |
| Report / research | Light Minimal | Hero, Stats, Data, Content Card, Comparison, List, CTA |
| Personal story | Warm Editorial | Hero, Timeline, Quote, Content Card, List, CTA |
| Company overview | Dark Cinematic | Hero, Stats, Chapter, Content Card, Feature Grid, Timeline, CTA |
Always tell the user WHY you're recommending a specific theme. Be specific about the content, not generic.
Narrative Arc Guidelines
Structure slides to follow a story arc:
- Hook — Hero slide that grabs attention
- Context — Stats or chapter that establishes credibility
- Body — The core content (cards, grids, timelines, comparisons)
- Surprise — A "one more thing" moment or unexpected highlight
- Close — CTA or contact slide
Each slide should communicate ONE idea. If a slide has too much content, split it into multiple slides.
Keep total slide count between 8-15 for optimal pacing. Fewer than 8 feels thin; more than 15 feels long.
Source
git clone https://github.com/sacredvoid/presentation-chef/blob/main/skills/presentation-chef/SKILL.mdView on GitHub Overview
Convert markdown, text, or structured data into a polished Apple Keynote–style HTML presentation. The output is a single self-contained .html file with zero dependencies, cinematic animations, glassmorphism, and premium design inspired by ChronicleHQ.
How This Skill Works
Input types like markdown, plain text descriptions, or structured data are analyzed and mapped to slide types and narrative flow. The tool then renders a self-contained HTML file with embedded CSS and JavaScript, delivering cinematic animations and glassmorphism without external assets. Critically, it enforces interactive input gathering via AskUserQuestion before producing any HTML content.
When to Use It
- You need to turn a product brief, pitch deck, or topic into a polished keynote-style deck.
- You want a single-file HTML presentation for easy sharing on the web without hosting dependencies.
- You’re converting educational content or training notes into structured slides.
- You’re building a portfolio, personal story, or designer showcase as a premium HTML deck.
- You’re preparing a product launch or company update with cinematic visuals.
Quick Start
- Step 1: Gather content with the interactive prompts (paste/describe, or provide a file or topic).
- Step 2: Choose a visual theme and design preferences (tone, colors, effects).
- Step 3: Generate and download the single self-contained HTML presentation.
Best Practices
- Define your content source clearly and provide it via paste, file, or topic to satisfy the interactive gathering step.
- Plan slide structure in advance so content maps cleanly to slide types and transitions.
- Choose a theme early and communicate tone, colors, and design preferences.
- Keep slide count and density manageable to preserve readability and pacing.
- Test the final HTML on target devices and ensure accessibility (contrast, keyboard navigation).
Example Use Cases
- Pitch deck generated from a product brief for a startup.
- Designer portfolio slides created from project notes and descriptions.
- Educational module outline transformed from curriculum content.
- Conference talk outline converted from talk notes.
- Research report summary presented as a premium HTML deck.