frontend-slides

Frontend & Expérience UX

Create stunning, animation-rich HTML presentations from scratch or by converting PowerPoint files. Use when the user wants to build a presentation, convert a PPT/PPTX to web, or create slides for a talk/pitch. Helps non-designers discover their aesthetic through visual exploration rather than abstract choices.

Documentation

Frontend Slides Skill

Create zero-dependency, animation-rich HTML presentations that run entirely in the browser. This skill helps non-designers discover their preferred aesthetic through visual exploration ("show, don't tell"), then generates production-quality slide decks.

Core Philosophy

1.Zero Dependencies — Single HTML files with inline CSS/JS. No npm, no build tools.
2.Show, Don't Tell — People don't know what they want until they see it. Generate visual previews, not abstract choices.
3.Distinctive Design — Avoid generic "AI slop" aesthetics. Every presentation should feel custom-crafted.
4.Production Quality — Code should be well-commented, accessible, and performant.

---

Phase 0: Detect Mode

First, determine what the user wants:

Mode A: New Presentation

User wants to create slides from scratch
Proceed to Phase 1 (Content Discovery)

Mode B: PPT Conversion

User has a PowerPoint file (.ppt, .pptx) to convert
Proceed to Phase 4 (PPT Extraction)

Mode C: Existing Presentation Enhancement

User has an HTML presentation and wants to improve it
Read the existing file, understand the structure, then enhance

---

Phase 1: Content Discovery (New Presentations)

Before designing, understand the content. Ask via AskUserQuestion:

Step 1.1: Presentation Context

Question 1: Purpose

Header: "Purpose"
Question: "What is this presentation for?"
Options:
"Pitch deck" — Selling an idea, product, or company to investors/clients
"Teaching/Tutorial" — Explaining concepts, how-to guides, educational content
"Conference talk" — Speaking at an event, tech talk, keynote
"Internal presentation" — Team updates, strategy meetings, company updates

Question 2: Slide Count

Header: "Length"
Question: "Approximately how many slides?"
Options:
"Short (5-10)" — Quick pitch, lightning talk
"Medium (10-20)" — Standard presentation
"Long (20+)" — Deep dive, comprehensive talk

Question 3: Content

Header: "Content"
Question: "Do you have the content ready, or do you need help structuring it?"
Options:
"I have all content ready" — Just need to design the presentation
"I have rough notes" — Need help organizing into slides
"I have a topic only" — Need help creating the full outline

If user has content, ask them to share it (text, bullet points, images, etc.).

---

Phase 2: Style Discovery (Visual Exploration)

CRITICAL: This is the "show, don't tell" phase.

Most people can't articulate design preferences in words. Instead of asking "do you want minimalist or bold?", we generate mini-previews and let them react.

Step 2.1: Mood Selection

Question 1: Feeling

Header: "Vibe"
Question: "What feeling should the audience have when viewing your slides?"
Options:
"Impressed/Confident" — Professional, trustworthy, this team knows what they're doing
"Excited/Energized" — Innovative, bold, this is the future
"Calm/Focused" — Clear, thoughtful, easy to follow
"Inspired/Moved" — Emotional, storytelling, memorable
multiSelect: true (can choose up to 2)

Step 2.2: Generate Style Previews

Based on their mood selection, generate 3 distinct style previews as mini HTML files in a temporary directory. Each preview should be a single title slide showing:

Typography (font choices, heading/body hierarchy)
Color palette (background, accent, text colors)
Animation style (how elements enter)
Overall aesthetic feel

Preview Styles to Consider (pick 3 based on mood):

| Mood | Style Options |

|------|---------------|

| Impressed/Confident | "Corporate Elegant", "Dark Executive", "Clean Minimal" |

| Excited/Energized | "Neon Cyber", "Bold Gradients", "Kinetic Motion" |

| Calm/Focused | "Paper & Ink", "Soft Muted", "Swiss Minimal" |

| Inspired/Moved | "Cinematic Dark", "Warm Editorial", "Atmospheric" |

IMPORTANT: Never use these generic patterns:

Purple gradients on white backgrounds
Inter, Roboto, or system fonts
Standard blue primary colors
Predictable hero layouts

Instead, use distinctive choices:

Unique font pairings (Clash Display, Satoshi, Cormorant Garamond, DM Sans, etc.)
Cohesive color themes with personality
Atmospheric backgrounds (gradients, subtle patterns, depth)
Signature animation moments

Step 2.3: Present Previews

Create the previews in: .claude-design/slide-previews/

.claude-design/slide-previews/
├── style-a.html   # First style option
├── style-b.html   # Second style option
├── style-c.html   # Third style option
└── assets/        # Any shared assets

Each preview file should be:

Self-contained (inline CSS/JS)
A single "title slide" showing the aesthetic
Animated to demonstrate motion style
~50-100 lines, not a full presentation

Present to user:

I've created 3 style previews for you to compare:

**Style A: [Name]** — [1 sentence description]
**Style B: [Name]** — [1 sentence description]
**Style C: [Name]** — [1 sentence description]

Open each file to see them in action:
- .claude-design/slide-previews/style-a.html
- .claude-design/slide-previews/style-b.html
- .claude-design/slide-previews/style-c.html

Take a look and tell me:
1. Which style resonates most?
2. What do you like about it?
3. Anything you'd change?

Then use AskUserQuestion:

Question: Pick Your Style

Header: "Style"
Question: "Which style preview do you prefer?"
Options:
"Style A: [Name]" — [Brief description]
"Style B: [Name]" — [Brief description]
"Style C: [Name]" — [Brief description]
"Mix elements" — Combine aspects from different styles

If "Mix elements", ask for specifics.

---

Phase 3: Generate Presentation

Now generate the full presentation based on:

Content from Phase 1
Style from Phase 2

File Structure

For single presentations:

presentation.html    # Self-contained presentation
assets/              # Images, if any

For projects with multiple presentations:

[presentation-name].html
[presentation-name]-assets/

HTML Architecture

Follow this structure for all presentations:

<!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>

    <!-- Fonts (use Fontshare or Google Fonts) -->
    <link rel="stylesheet" href="https://api.fontshare.com/v2/css?f[]=...">

    <style>
        /* ===========================================
           CSS CUSTOM PROPERTIES (THEME)
           Easy to modify: change these to change the whole look
           =========================================== */
        :root {
            /* Colors */
            --bg-primary: #0a0f1c;
            --bg-secondary: #111827;
            --text-primary: #ffffff;
            --text-secondary: #9ca3af;
            --accent: #00ffcc;
            --accent-glow: rgba(0, 255, 204, 0.3);

            /* Typography */
            --font-display: 'Clash Display', sans-serif;
            --font-body: 'Satoshi', sans-serif;

            /* Spacing */
            --slide-padding: clamp(2rem, 5vw, 4rem);

            /* Animation */
            --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
            --duration-normal: 0.6s;
        }

        /* ===========================================
           BASE STYLES
           =========================================== */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        html {
            scroll-behavior: smooth;
            scroll-snap-type: y mandatory;
        }

        body {
            font-family: var(--font-body);
            background: var(--bg-primary);
            color: var(--text-primary);
            overflow-x: hidden;
        }

        /* ===========================================
           SLIDE CONTAINER
           Each section is one slide
           =========================================== */
        .slide {
            min-height: 100vh;
            padding: var(--slide-padding);
            scroll-snap-align: start;
            display: flex;
            flex-direction: column;
            justify-content: center;
            position: relative;
            overflow: hidden;
        }

        /* ===========================================
           ANIMATIONS
           Trigger via .visible class (added by JS on scroll)
           =========================================== */
        .reveal {
            opacity: 0;
            transform: translateY(30px);
            transition: opacity var(--duration-normal) var(--ease-out-expo),
                        transform var(--duration-normal) var(--ease-out-expo);
        }

        .slide.visible .reveal {
            opacity: 1;
            transform: translateY(0);
        }

        /* Stagger children */
        .reveal:nth-child(1) { transition-delay: 0.1s; }
        .reveal:nth-child(2) { transition-delay: 0.2s; }
        .reveal:nth-child(3) { transition-delay: 0.3s; }
        .reveal:nth-child(4) { transition-delay: 0.4s; }

        /* ... more styles ... */
    </style>
</head>
<body>
    <!-- Progress bar (optional) -->
    <div class="progress-bar"></div>

    <!-- Navigation dots (optional) -->
    <nav class="nav-dots">
        <!-- Generated by JS -->
    </nav>

    <!-- Slides -->
    <section class="slide title-slide">
        <h1 class="reveal">Presentation Title</h1>
        <p class="reveal">Subtitle or author</p>
    </section>

    <section class="slide">
        <h2 class="reveal">Slide Title</h2>
        <p class="reveal">Content...</p>
    </section>

    <!-- More slides... -->

    <script>
        /* ===========================================
           SLIDE PRESENTATION CONTROLLER
           Handles navigation, animations, and interactions
           =========================================== */

        class SlidePresentation {
            constructor() {
                // ... initialization
            }

            // ... methods
        }

        // Initialize
        new SlidePresentation();
    </script>
</body>
</html>

Required JavaScript Features

Every presentation should include:

1.SlidePresentation Class — Main controller
Keyboard navigation (arrows, space)
Touch/swipe support
Mouse wheel navigation
Progress bar updates
Navigation dots
2.Intersection Observer — For scroll-triggered animations
Add .visible class when slides enter viewport
Trigger CSS animations efficiently
3.Optional Enhancements (based on style):
Custom cursor with trail
Particle system background (canvas)
Parallax effects
3D tilt on hover
Magnetic buttons
Counter animations

Code Quality Requirements

Comments:

Every section should have clear comments explaining:

What it does
Why it exists
How to modify it
/* ===========================================
   CUSTOM CURSOR
   Creates a stylized cursor that follows mouse with a trail effect.
   - Uses lerp (linear interpolation) for smooth movement
   - Grows larger when hovering over interactive elements
   =========================================== */
class CustomCursor {
    constructor() {
        // ...
    }
}

Accessibility:

Semantic HTML (
,
Keyboard navigation works
ARIA labels where needed
Reduced motion support
@media (prefers-reduced-motion: reduce) {
    .reveal {
        transition: opacity 0.3s ease;
        transform: none;
    }
}

Responsive:

Mobile-friendly (single column, adjusted spacing)
Disable heavy effects on mobile
Touch-friendly interactions
@media (max-width: 768px) {
    .nav-dots,
    .keyboard-hint {
        display: none;
    }
}

---

Phase 4: PPT Conversion

When converting PowerPoint files:

Step 4.1: Extract Content

Use Python with python-pptx to extract:

from pptx import Presentation
from pptx.util import Inches, Pt
import json
import os
import base64

def extract_pptx(file_path, output_dir):
    """
    Extract all content from a PowerPoint file.
    Returns a JSON structure with slides, text, and images.
    """
    prs = Presentation(file_path)
    slides_data = []

    # Create assets directory
    assets_dir = os.path.join(output_dir, 'assets')
    os.makedirs(assets_dir, exist_ok=True)

    for slide_num, slide in enumerate(prs.slides):
        slide_data = {
            'number': slide_num + 1,
            'title': '',
            'content': [],
            'images': [],
            'notes': ''
        }

        for shape in slide.shapes:
            # Extract title
            if shape.has_text_frame:
                if shape == slide.shapes.title:
                    slide_data['title'] = shape.text
                else:
                    slide_data['content'].append({
                        'type': 'text',
                        'content': shape.text
                    })

            # Extract images
            if shape.shape_type == 13:  # Picture
                image = shape.image
                image_bytes = image.blob
                image_ext = image.ext
                image_name = f"slide{slide_num + 1}_img{len(slide_data['images']) + 1}.{image_ext}"
                image_path = os.path.join(assets_dir, image_name)

                with open(image_path, 'wb') as f:
                    f.write(image_bytes)

                slide_data['images'].append({
                    'path': f"assets/{image_name}",
                    'width': shape.width,
                    'height': shape.height
                })

        # Extract notes
        if slide.has_notes_slide:
            notes_frame = slide.notes_slide.notes_text_frame
            slide_data['notes'] = notes_frame.text

        slides_data.append(slide_data)

    return slides_data

Step 4.2: Confirm Content Structure

Present the extracted content to the user:

I've extracted the following from your PowerPoint:

**Slide 1: [Title]**
- [Content summary]
- Images: [count]

**Slide 2: [Title]**
- [Content summary]
- Images: [count]

...

All images have been saved to the assets folder.

Does this look correct? Should I proceed with style selection?

Step 4.3: Style Selection

Proceed to Phase 2 (Style Discovery) with the extracted content in mind.

Step 4.4: Generate HTML

Convert the extracted content into the chosen style, preserving:

All text content
All images (referenced from assets folder)
Slide order
Any speaker notes (as HTML comments or separate file)

---

Phase 5: Delivery

Final Output

When the presentation is complete:

1.Clean up temporary files
Delete .claude-design/slide-previews/ if it exists
2.Open the presentation
Use open [filename].html to launch in browser
3.Provide summary
Your presentation is ready!

📁 File: [filename].html
🎨 Style: [Style Name]
📊 Slides: [count]

**Navigation:**
- Arrow keys (← →) or Space to navigate
- Scroll/swipe also works
- Click the dots on the right to jump to a slide

**To customize:**
- Colors: Look for `:root` CSS variables at the top
- Fonts: Change the Fontshare/Google Fonts link
- Animations: Modify `.reveal` class timings

Would you like me to make any adjustments?

---

Style Reference: Effect → Feeling Mapping

Use this guide to match animations to intended feelings:

Dramatic / Cinematic

Slow fade-ins (1-1.5s)
Large scale transitions (0.9 → 1)
Dark backgrounds with spotlight effects
Parallax scrolling
Full-bleed images

Techy / Futuristic

Neon glow effects (box-shadow with accent color)
Particle systems (canvas background)
Grid patterns
Monospace fonts for accents
Glitch or scramble text effects
Cyan, magenta, electric blue palette

Playful / Friendly

Bouncy easing (spring physics)
Rounded corners (large radius)
Pastel or bright colors
Floating/bobbing animations
Hand-drawn or illustrated elements

Professional / Corporate

Subtle, fast animations (200-300ms)
Clean sans-serif fonts
Navy, slate, or charcoal backgrounds
Precise spacing and alignment
Minimal decorative elements
Data visualization focus

Calm / Minimal

Very slow, subtle motion
High whitespace
Muted color palette
Serif typography
Generous padding
Content-focused, no distractions

Editorial / Magazine

Strong typography hierarchy
Pull quotes and callouts
Image-text interplay
Grid-breaking layouts
Serif headlines, sans-serif body
Black and white with one accent

---

Animation Patterns Reference

Entrance Animations

/* Fade + Slide Up (most common) */
.reveal {
    opacity: 0;
    transform: translateY(30px);
    transition: opacity 0.6s var(--ease-out-expo),
                transform 0.6s var(--ease-out-expo);
}

.visible .reveal {
    opacity: 1;
    transform: translateY(0);
}

/* Scale In */
.reveal-scale {
    opacity: 0;
    transform: scale(0.9);
    transition: opacity 0.6s, transform 0.6s var(--ease-out-expo);
}

/* Slide from Left */
.reveal-left {
    opacity: 0;
    transform: translateX(-50px);
    transition: opacity 0.6s, transform 0.6s var(--ease-out-expo);
}

/* Blur In */
.reveal-blur {
    opacity: 0;
    filter: blur(10px);
    transition: opacity 0.8s, filter 0.8s var(--ease-out-expo);
}

Background Effects

/* Gradient Mesh */
.gradient-bg {
    background:
        radial-gradient(ellipse at 20% 80%, rgba(120, 0, 255, 0.3) 0%, transparent 50%),
        radial-gradient(ellipse at 80% 20%, rgba(0, 255, 200, 0.2) 0%, transparent 50%),
        var(--bg-primary);
}

/* Noise Texture */
.noise-bg {
    background-image: url("data:image/svg+xml,..."); /* Inline SVG noise */
}

/* Grid Pattern */
.grid-bg {
    background-image:
        linear-gradient(rgba(255,255,255,0.03) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255,255,255,0.03) 1px, transparent 1px);
    background-size: 50px 50px;
}

Interactive Effects

/* 3D Tilt on Hover */
class TiltEffect {
    constructor(element) {
        this.element = element;
        this.element.style.transformStyle = 'preserve-3d';
        this.element.style.perspective = '1000px';
        this.bindEvents();
    }

    bindEvents() {
        this.element.addEventListener('mousemove', (e) => {
            const rect = this.element.getBoundingClientRect();
            const x = (e.clientX - rect.left) / rect.width - 0.5;
            const y = (e.clientY - rect.top) / rect.height - 0.5;

            this.element.style.transform = `
                rotateY(${x * 10}deg)
                rotateX(${-y * 10}deg)
            `;
        });

        this.element.addEventListener('mouseleave', () => {
            this.element.style.transform = 'rotateY(0) rotateX(0)';
        });
    }
}

---

Troubleshooting

Common Issues

Fonts not loading:

Check Fontshare/Google Fonts URL
Ensure font names match in CSS

Animations not triggering:

Verify Intersection Observer is running
Check that .visible class is being added

Scroll snap not working:

Ensure scroll-snap-type on html/body
Each slide needs scroll-snap-align: start

Mobile issues:

Disable heavy effects at 768px breakpoint
Test touch events
Reduce particle count or disable canvas

Performance issues:

Use will-change sparingly
Prefer transform and opacity animations
Throttle scroll/mousemove handlers

---

Related Skills

learn — Generate FORZARA.md documentation for the presentation
frontend-design — For more complex interactive pages beyond slides
design-and-refine:design-lab — For iterating on component designs

---

Example Session Flow

1.User: "I want to create a pitch deck for my AI startup"
2.Skill asks about purpose, length, content
3.User shares their bullet points and key messages
4.Skill asks about desired feeling (Impressed + Excited)
5.Skill generates 3 style previews
6.User picks Style B (Neon Cyber), asks for darker background
7.Skill generates full presentation with all slides
8.Skill opens the presentation in browser
9.User requests tweaks to specific slides
10.Final presentation delivered

---

Conversion Session Flow

1.User: "Convert my slides.pptx to a web presentation"
2.Skill extracts content and images from PPT
3.Skill confirms extracted content with user
4.Skill asks about desired feeling/style
5.Skill generates style previews
6.User picks a style
7.Skill generates HTML presentation with preserved assets
8.Final presentation delivered
Utiliser l'Agent frontend-slides - Outil & Compétence IA | Skills Catalogue | Skills Catalogue