|
@@ -0,0 +1,768 @@
|
|
|
|
|
+---
|
|
|
|
|
+name: frontend-slides
|
|
|
|
|
+description: 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.
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+# 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:
|
|
|
|
|
+
|
|
|
|
|
+```html
|
|
|
|
|
+<!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
|
|
|
|
|
+
|
|
|
|
|
+```javascript
|
|
|
|
|
+/* ===========================================
|
|
|
|
|
+ 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 (`<section>`, `<nav>`, `<main>`)
|
|
|
|
|
+- Keyboard navigation works
|
|
|
|
|
+- ARIA labels where needed
|
|
|
|
|
+- Reduced motion support
|
|
|
|
|
+
|
|
|
|
|
+```css
|
|
|
|
|
+@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
|
|
|
|
|
+
|
|
|
|
|
+```css
|
|
|
|
|
+@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:
|
|
|
|
|
+
|
|
|
|
|
+```python
|
|
|
|
|
+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
|
|
|
|
|
+
|
|
|
|
|
+```css
|
|
|
|
|
+/* 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
|
|
|
|
|
+
|
|
|
|
|
+```css
|
|
|
|
|
+/* 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
|
|
|
|
|
+
|
|
|
|
|
+```javascript
|
|
|
|
|
+/* 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
|