Get the FREE Ultimate OpenClaw Setup Guide →

presentation-chef

Scanned
npx machina-cli add skill sacredvoid/presentation-chef/presentation-chef --openclaw
Files (1)
SKILL.md
41.9 KB

Presentation 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:

  1. TaskUpdatein_progress before you start working on it
  2. Generate that section of the presentation
  3. TaskUpdatecompleted when done
  4. 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 correct data-slide index
  • Background variant class
  • Ambient orbs (if dark theme)
  • All content elements wrapped in reveal-element with 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:

  1. Document structure (head, meta, <style> open)
  2. All CSS (reset, theme, effects, slides, typography, responsive, print)
  3. <body> open, loading screen, grain overlay (if dark theme)
  4. Progress bar, nav dots, keyboard hint
  5. Speaker notes sidebar (all slides)
  6. Controls bar
  7. <div class="slide-container"> with all slide batches in order
  8. <script> with full JS engine
  9. 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:

  1. Slide navigationgoToSlide(index, direction) with transition locking
  2. Reveal animations — trigger .revealed class on active slide elements
  3. Count-up animationsrequestAnimationFrame with ease-out cubic
  4. Data bar animations — trigger fill width on reveal
  5. Dot/progress updates — sync with current slide
  6. Keyboard navigation — arrows, space, page up/down, home/end, escape, T (notes), P (pdf)
  7. Mouse wheel — debounced with accumulator (threshold 50, debounce 80ms)
  8. Touch — swipe detection with 50px threshold
  9. Parallax — mousemove on hero glow and ambient orbs
  10. Loading screen — fade out after 600ms on window load
  11. Speaker notes toggletoggleNotes() opens/closes sidebar, updateNotes() syncs content to current slide
  12. PDF exportexportPdf() snaps all count-up numbers to data-target values and data bars to full width before calling window.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 T key 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.active matching 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-open class

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-tip callout 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:

  1. Snap ALL .count-up elements to their data-target values (set textContent = getAttribute('data-target'))
  2. Add .revealed class to ALL .data-bar-fill elements so bars show at full width
  3. Close speaker notes if open
  4. 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

ElementSizeWeightTracking
Hero nameclamp(48px, 10vw, 120px)700-0.03em
Section titleclamp(36px, 7vw, 96px)700-0.03em
Mega numberclamp(64px, 15vw, 180px)800-0.04em
Section labelclamp(14px, 1.5vw, 18px)6000.15em, uppercase
Body textclamp(14px, 1.8vw, 18px)400normal
Subtitleclamp(16px, 2.5vw, 28px)400normal
Chip textclamp(12px, 1.4vw, 15px)500normal

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-element with sequential delays
  • Navigation dots count matches total slides
  • TOTAL_SLIDES constant matches actual slide count
  • Progress bar gradient matches theme
  • All data-slide attributes are sequential from 0
  • Count-up elements have data-target set
  • Cards have ::before top highlight gradient
  • Responsive styles handle 768px and 480px breakpoints
  • Touch prevention (touchmove preventDefault) is included
  • Loading screen included and auto-hides
  • will-change hints 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 before window.print()
  • @media print stylesheet hides UI chrome and shows all slides as pages
  • @page { size: landscape; margin: 0; } is set
  • updateNotes() is called in goToSlide() 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 TypeSuggested ThemeTypical Slides
Startup pitchDark CinematicHero, Stats, Chapter, Content Card, Feature Grid, CTA
PortfolioDark Cinematic or Light MinimalHero, Stats, Chapter, Content Card x N, Feature Grid, List, CTA
Product launchNeon Cyberpunk or Dark CinematicHero, Chapter, Split, Feature Grid, Comparison, Stats, CTA
EducationalLight Minimal or Earth OrganicHero, Chapter, Content Card, Data, Timeline, List, CTA
Report / researchLight MinimalHero, Stats, Data, Content Card, Comparison, List, CTA
Personal storyWarm EditorialHero, Timeline, Quote, Content Card, List, CTA
Company overviewDark CinematicHero, 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:

  1. Hook — Hero slide that grabs attention
  2. Context — Stats or chapter that establishes credibility
  3. Body — The core content (cards, grids, timelines, comparisons)
  4. Surprise — A "one more thing" moment or unexpected highlight
  5. 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

  1. Step 1: Gather content with the interactive prompts (paste/describe, or provide a file or topic).
  2. Step 2: Choose a visual theme and design preferences (tone, colors, effects).
  3. 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.

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers