Skillshub frontend-slides
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.
git clone https://github.com/ComeOnOliver/skillshub
T=$(mktemp -d) && git clone --depth=1 https://github.com/ComeOnOliver/skillshub "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/happycapy-ai/Happycapy-skills/frontend-slides" ~/.claude/skills/comeonoliver-skillshub-frontend-slides-e7a822 && rm -rf "$T"
skills/happycapy-ai/Happycapy-skills/frontend-slides/SKILL.mdFrontend 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
- Zero Dependencies — Single HTML files with inline CSS/JS. No npm, no build tools.
- Show, Don't Tell — People don't know what they want until they see it. Generate visual previews, not abstract choices.
- Distinctive Design — Avoid generic "AI slop" aesthetics. Every presentation should feel custom-crafted.
- Production Quality — Code should be well-commented, accessible, and performant.
- Viewport Fitting (CRITICAL) — Every slide MUST fit exactly within the viewport. No scrolling within slides, ever. This is non-negotiable.
CRITICAL: Viewport Fitting Requirements
This section is mandatory for ALL presentations. Every slide must be fully visible without scrolling on any screen size.
The Golden Rule
Each slide = exactly one viewport height (100vh/100dvh) Content overflows? → Split into multiple slides or reduce content Never scroll within a slide.
Content Density Limits
To guarantee viewport fitting, enforce these limits per slide:
| Slide Type | Maximum Content |
|---|---|
| Title slide | 1 heading + 1 subtitle + optional tagline |
| Content slide | 1 heading + 4-6 bullet points OR 1 heading + 2 paragraphs |
| Feature grid | 1 heading + 6 cards maximum (2x3 or 3x2 grid) |
| Code slide | 1 heading + 8-10 lines of code maximum |
| Quote slide | 1 quote (max 3 lines) + attribution |
| Image slide | 1 heading + 1 image (max 60vh height) |
If content exceeds these limits → Split into multiple slides
Required CSS Architecture
Every presentation MUST include this base CSS for viewport fitting:
/* =========================================== VIEWPORT FITTING: MANDATORY BASE STYLES These styles MUST be included in every presentation. They ensure slides fit exactly in the viewport. =========================================== */ /* 1. Lock html/body to viewport */ html, body { height: 100%; overflow-x: hidden; } html { scroll-snap-type: y mandatory; scroll-behavior: smooth; } /* 2. Each slide = exact viewport height */ .slide { width: 100vw; height: 100vh; height: 100dvh; /* Dynamic viewport height for mobile browsers */ overflow: hidden; /* CRITICAL: Prevent ANY overflow */ scroll-snap-align: start; display: flex; flex-direction: column; position: relative; } /* 3. Content container with flex for centering */ .slide-content { flex: 1; display: flex; flex-direction: column; justify-content: center; max-height: 100%; overflow: hidden; /* Double-protection against overflow */ padding: var(--slide-padding); } /* 4. ALL typography uses clamp() for responsive scaling */ :root { /* Titles scale from mobile to desktop */ --title-size: clamp(1.5rem, 5vw, 4rem); --h2-size: clamp(1.25rem, 3.5vw, 2.5rem); --h3-size: clamp(1rem, 2.5vw, 1.75rem); /* Body text */ --body-size: clamp(0.75rem, 1.5vw, 1.125rem); --small-size: clamp(0.65rem, 1vw, 0.875rem); /* Spacing scales with viewport */ --slide-padding: clamp(1rem, 4vw, 4rem); --content-gap: clamp(0.5rem, 2vw, 2rem); --element-gap: clamp(0.25rem, 1vw, 1rem); } /* 5. Cards/containers use viewport-relative max sizes */ .card, .container, .content-box { max-width: min(90vw, 1000px); max-height: min(80vh, 700px); } /* 6. Lists auto-scale with viewport */ .feature-list, .bullet-list { gap: clamp(0.4rem, 1vh, 1rem); } .feature-list li, .bullet-list li { font-size: var(--body-size); line-height: 1.4; } /* 7. Grids adapt to available space */ .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr)); gap: clamp(0.5rem, 1.5vw, 1rem); } /* 8. Images constrained to viewport */ img, .image-container { max-width: 100%; max-height: min(50vh, 400px); object-fit: contain; } /* =========================================== RESPONSIVE BREAKPOINTS Aggressive scaling for smaller viewports =========================================== */ /* Short viewports (< 700px height) */ @media (max-height: 700px) { :root { --slide-padding: clamp(0.75rem, 3vw, 2rem); --content-gap: clamp(0.4rem, 1.5vw, 1rem); --title-size: clamp(1.25rem, 4.5vw, 2.5rem); --h2-size: clamp(1rem, 3vw, 1.75rem); } } /* Very short viewports (< 600px height) */ @media (max-height: 600px) { :root { --slide-padding: clamp(0.5rem, 2.5vw, 1.5rem); --content-gap: clamp(0.3rem, 1vw, 0.75rem); --title-size: clamp(1.1rem, 4vw, 2rem); --body-size: clamp(0.7rem, 1.2vw, 0.95rem); } /* Hide non-essential elements */ .nav-dots, .keyboard-hint, .decorative { display: none; } } /* Extremely short (landscape phones, < 500px height) */ @media (max-height: 500px) { :root { --slide-padding: clamp(0.4rem, 2vw, 1rem); --title-size: clamp(1rem, 3.5vw, 1.5rem); --h2-size: clamp(0.9rem, 2.5vw, 1.25rem); --body-size: clamp(0.65rem, 1vw, 0.85rem); } } /* Narrow viewports (< 600px width) */ @media (max-width: 600px) { :root { --title-size: clamp(1.25rem, 7vw, 2.5rem); } /* Stack grids vertically */ .grid { grid-template-columns: 1fr; } } /* =========================================== REDUCED MOTION Respect user preferences =========================================== */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.2s !important; } html { scroll-behavior: auto; } }
Overflow Prevention Checklist
Before generating any presentation, mentally verify:
- ✅ Every
has.slideheight: 100vh; height: 100dvh; overflow: hidden; - ✅ All font sizes use
clamp(min, preferred, max) - ✅ All spacing uses
or viewport unitsclamp() - ✅ Content containers have
constraintsmax-height - ✅ Images have
or similarmax-height: min(50vh, 400px) - ✅ Grids use
withauto-fit
for responsive columnsminmax() - ✅ Breakpoints exist for heights: 700px, 600px, 500px
- ✅ No fixed pixel heights on content elements
- ✅ Content per slide respects density limits
When Content Doesn't Fit
If you find yourself with too much content:
DO:
- Split into multiple slides
- Reduce bullet points (max 5-6 per slide)
- Shorten text (aim for 1-2 lines per bullet)
- Use smaller code snippets
- Create a "continued" slide
DON'T:
- Reduce font size below readable limits
- Remove padding/spacing entirely
- Allow any scrolling
- Cram content to fit
Testing Viewport Fit
After generating, recommend the user test at these sizes:
- Desktop: 1920×1080, 1440×900, 1280×720
- Tablet: 1024×768, 768×1024 (portrait)
- Mobile: 375×667, 414×896
- Landscape phone: 667×375, 896×414
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.
How Users Choose Presets
Users can select a style in two ways:
Option A: Guided Discovery (Default)
- User answers mood questions
- Skill generates 3 preview files based on their answers
- User views previews in browser and picks their favorite
- This is best for users who don't have a specific style in mind
Option B: Direct Selection
- If user already knows what they want, they can request a preset by name
- Example: "Use the Bold Signal style" or "I want something like Dark Botanical"
- Skip to Phase 3 immediately
Available Presets:
| Preset | Vibe | Best For |
|---|---|---|
| Bold Signal | Confident, high-impact | Pitch decks, keynotes |
| Electric Studio | Clean, professional | Agency presentations |
| Creative Voltage | Energetic, retro-modern | Creative pitches |
| Dark Botanical | Elegant, sophisticated | Premium brands |
| Notebook Tabs | Editorial, organized | Reports, reviews |
| Pastel Geometry | Friendly, approachable | Product overviews |
| Split Pastel | Playful, modern | Creative agencies |
| Vintage Editorial | Witty, personality-driven | Personal brands |
| Neon Cyber | Futuristic, techy | Tech startups |
| Terminal Green | Developer-focused | Dev tools, APIs |
| Swiss Modern | Minimal, precise | Corporate, data |
| Paper & Ink | Literary, thoughtful | Storytelling |
Step 2.0: Style Path Selection
First, ask how the user wants to choose their style:
Question: Style Selection Method
- Header: "Style"
- Question: "How would you like to choose your presentation style?"
- Options:
- "Show me options" — Generate 3 previews based on my needs (recommended for most users)
- "I know what I want" — Let me pick from the preset list directly
If "Show me options" → Continue to Step 2.1 (Mood Selection)
If "I know what I want" → Show preset picker:
Question: Pick a Preset
- Header: "Preset"
- Question: "Which style would you like to use?"
- Options:
- "Bold Signal" — Vibrant card on dark, confident and high-impact
- "Dark Botanical" — Elegant dark with soft abstract shapes
- "Notebook Tabs" — Editorial paper look with colorful section tabs
- "Pastel Geometry" — Friendly pastels with decorative pills
(If user picks one, skip to Phase 3. If they want to see more options, show additional presets or proceed to guided discovery.)
Step 2.1: Mood Selection (Guided Discovery)
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 | "Bold Signal", "Electric Studio", "Dark Botanical" |
| Excited/Energized | "Creative Voltage", "Neon Cyber", "Split Pastel" |
| Calm/Focused | "Notebook Tabs", "Paper & Ink", "Swiss Modern" |
| Inspired/Moved | "Dark Botanical", "Vintage Editorial", "Pastel Geometry" |
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 - MUST use clamp() for responsive scaling */ --font-display: 'Clash Display', sans-serif; --font-body: 'Satoshi', sans-serif; --title-size: clamp(2rem, 6vw, 5rem); --subtitle-size: clamp(0.875rem, 2vw, 1.25rem); --body-size: clamp(0.75rem, 1.2vw, 1rem); /* Spacing - MUST use clamp() for responsive scaling */ --slide-padding: clamp(1.5rem, 4vw, 4rem); --content-gap: clamp(1rem, 2vw, 2rem); /* 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; height: 100%; } body { font-family: var(--font-body); background: var(--bg-primary); color: var(--text-primary); overflow-x: hidden; height: 100%; } /* =========================================== SLIDE CONTAINER CRITICAL: Each slide MUST fit exactly in viewport - Use height: 100vh (NOT min-height) - Use overflow: hidden to prevent scroll - Content must scale with clamp() values =========================================== */ .slide { width: 100vw; height: 100vh; /* EXACT viewport height - no scrolling */ height: 100dvh; /* Dynamic viewport height for mobile */ padding: var(--slide-padding); scroll-snap-align: start; display: flex; flex-direction: column; justify-content: center; position: relative; overflow: hidden; /* Prevent any content overflow */ } /* Content wrapper that prevents overflow */ .slide-content { flex: 1; display: flex; flex-direction: column; justify-content: center; max-height: 100%; overflow: hidden; } /* =========================================== RESPONSIVE BREAKPOINTS Adjust content for different screen sizes =========================================== */ @media (max-height: 600px) { :root { --slide-padding: clamp(1rem, 3vw, 2rem); --content-gap: clamp(0.5rem, 1.5vw, 1rem); } } @media (max-width: 768px) { :root { --title-size: clamp(1.5rem, 8vw, 3rem); } } @media (max-height: 500px) and (orientation: landscape) { /* Extra compact for landscape phones */ :root { --title-size: clamp(1.25rem, 5vw, 2rem); --slide-padding: clamp(0.75rem, 2vw, 1.5rem); } } /* =========================================== 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:
-
SlidePresentation Class — Main controller
- Keyboard navigation (arrows, space)
- Touch/swipe support
- Mouse wheel navigation
- Progress bar updates
- Navigation dots
-
Intersection Observer — For scroll-triggered animations
- Add
class when slides enter viewport.visible - Trigger CSS animations efficiently
- Add
-
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 (
,<section>
,<nav>
)<main> - Keyboard navigation works
- ARIA labels where needed
- Reduced motion support
@media (prefers-reduced-motion: reduce) { .reveal { transition: opacity 0.3s ease; transform: none; } }
Responsive & Viewport Fitting (CRITICAL):
See the "CRITICAL: Viewport Fitting Requirements" section above for complete CSS and guidelines.
Quick reference:
- Every
must have.slideheight: 100vh; height: 100dvh; overflow: hidden; - All typography and spacing must use
clamp() - Respect content density limits (max 4-6 bullets, max 6 cards, etc.)
- Include breakpoints for heights: 700px, 600px, 500px
- When content doesn't fit → split into multiple slides, never scroll
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:
-
Clean up temporary files
- Delete
if it exists.claude-design/slide-previews/
- Delete
-
Open the presentation
- Use
to launch in browseropen [filename].html
- Use
-
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
class is being added.visible
Scroll snap not working:
- Ensure
on html/bodyscroll-snap-type - 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
sparinglywill-change - Prefer
andtransform
animationsopacity - 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
- User: "I want to create a pitch deck for my AI startup"
- Skill asks about purpose, length, content
- User shares their bullet points and key messages
- Skill asks about desired feeling (Impressed + Excited)
- Skill generates 3 style previews
- User picks Style B (Neon Cyber), asks for darker background
- Skill generates full presentation with all slides
- Skill opens the presentation in browser
- User requests tweaks to specific slides
- Final presentation delivered
Conversion Session Flow
- User: "Convert my slides.pptx to a web presentation"
- Skill extracts content and images from PPT
- Skill confirms extracted content with user
- Skill asks about desired feeling/style
- Skill generates style previews
- User picks a style
- Skill generates HTML presentation with preserved assets
- Final presentation delivered