From jiffy-toolkit
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.
How this skill is triggered — by the user, by Claude, or both
Slash command
/jiffy-toolkit:frontend-slidesThe summary Claude sees in its skill listing — used to decide when to auto-load this 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.
references/accessibility-and-quality.mdreferences/agent-team-prompts.mdreferences/edit-mode.mdreferences/engagement-defaults.mdreferences/html-architecture.mdreferences/media-and-widgets.mdreferences/multi-file-architecture.mdreferences/navigation-and-interaction.mdreferences/presenter-features.mdreferences/style-presets.mdreferences/viewport-fitting.mdscripts/export-to-gslides.pyCreate 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.
python3 serve.py. Single-file option available with --single-file for portability.This section is mandatory for ALL presentations. Every slide must be fully visible without scrolling on any screen size.
Each slide = exactly one viewport height (100vh/100dvh)
Content overflows? -> Split into multiple slides or reduce content
Never scroll within a slide.
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) |
| Two-column | 1 heading + 2 columns of 3-4 bullets each |
| Fact/stat | 1 large number + 1 subtitle + optional context line |
| Section divider | 1 heading + optional subtitle |
| Image-left/right | 1 image + 1 heading + 3-4 bullets |
| Video slide | 1 heading + 1 video (max 60vh height) |
If content exceeds these limits -> Split into multiple slides
For the full mandatory CSS architecture, responsive breakpoints, and troubleshooting, see references/viewport-fitting.md.
First, determine what the user wants:
Mode A: New Presentation
Mode B: PPT Conversion
Mode C: Existing Presentation Enhancement
Mode D: Multi-File Output (Default for New Presentations)
~/.claude/presentations/[presentation-name]/--single-file or mentions wanting a portable single file, post-process the multi-file output into one HTML file (see multi-file-architecture.md)When enhancing existing presentations, follow these mandatory rules:
1. Before Adding Any Content:
2. When Adding Images (MOST COMMON ISSUE):
max-height: min(50vh, 400px) or similar viewport constraint3. When Adding Text Content:
4. Required Checks After ANY Modification:
Does the slide have `overflow: hidden` on `.slide` class?
Are all new elements using `clamp()` for font sizes?
Do new images have viewport-relative max-height?
Does total content respect density limits?
Will this fit on a 1280x720 screen? On mobile portrait?
5. Proactive Reorganization (NOT Optional): When you detect that modifications will cause overflow:
6. Testing After Modifications: Mentally verify the modified slide at these viewport sizes:
If in doubt -> Split the content. Never allow scrolling within a slide.
Before designing, understand the content. Ask via AskUserQuestion:
IMPORTANT: Ask ALL 4 questions in a single AskUserQuestion call so the user can fill everything out at once before submitting.
Question 1: Purpose
Question 2: Slide Count
Question 3: Content
Question 4: Images
assets/ folder in the current projectThe user can select "Other" to type or paste any custom folder path (e.g. ~/Desktop/screenshots). This way the image folder path is collected in the same form — no extra round-trip.
Question 5: Inline Editing
Remember the user's choice — it determines whether edit-related HTML/CSS/JS is included in Phase 3.
If user has content, ask them to share it (text, bullet points, images, etc.).
User-provided assets are important visual anchors — but not every asset is necessarily usable. The first step is always to evaluate. After evaluation, the curated assets become additional context that shapes how the presentation is built. This is a co-design process: text content + curated visuals together inform the slide structure from the start, not a post-hoc "fit images in after the fact."
If user selected "No images" -> Skip the entire image pipeline. Proceed directly to Phase 2 (Style Discovery) and Phase 3 (Generate Presentation) using text content only. The presentation will use CSS-generated visuals (gradients, shapes, patterns, typography) for visual interest — this is the original behavior and produces fully polished results without any images.
If user provides an image folder:
ls to list all image files (.png, .jpg, .jpeg, .gif, .svg, .webp)USABLE or NOT USABLE (with reason: blurry, irrelevant, broken, etc.)Co-design: curated assets inform the outline
After evaluation, the usable images become context for planning the slide structure alongside text content. This is not "plan slides then add images" — it's designing the presentation around both text and visuals from the start:
This means curated images are factored in before style selection (Phase 2) and before HTML generation (Phase 3). They are co-equal context in the design process.
Question: Outline Confirmation
This keeps the entire flow in the AskUserQuestion format without dropping to free-text chat.
For image processing code (Pillow operations), see references/media-and-widgets.md.
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.
Users can select a style in three ways:
Option A: Guided Discovery ("Show me options")
Option B: Direct Selection ("I know what I want")
Option C: Full Browse ("Let me browse all")
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 |
| 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 |
| Liquid Glass | Modern, premium, depth | Product launches |
| Director's Cut | Cinematic, moody | Keynotes, stories |
| Micrographic | Precise, technical | Engineering reviews |
| Jewel Mono | Focused, brandable | Corporate, fintech |
| Whiteboard | Informal, sketch-like | Brainstorming, workshops |
| Bento Box | Premium, modular | Product launches, QBRs |
| Aurora Glow | Atmospheric, cinematic | Vision decks, keynotes |
| Scrapbook | Curated chaos, collage | Retrospectives, culture |
| Retro Futura | Space-age, retrofuturist | Roadmaps, innovation |
For full preset details (colors, fonts, signature elements), see references/style-presets.md.
First, ask how the user wants to choose their style:
Question: Style Selection Method
If "Show me options" -> Continue to Step 2.1 (Mood Selection)
If "I know what I want" -> Show preset picker:
Question: Pick a Preset
(If user picks one, skip to Phase 3. If they want to see more options, proceed to "Let me browse all" flow.)
If "Let me browse all" -> Skip to Step 2.2, generating the theme explorer with ALL 20 presets visible (no mood filtering, no highlighted recommendations).
This step only runs when the user chose "Show me options" in Step 2.0.
Question 1: Feeling
Based on the user's path, generate a single self-contained HTML file as the theme explorer:
Output: ~/.claude/presentations/.theme-explorer/index.html
This file replaces the old 3-file preview system. It contains all candidate presets as switchable views in a single page.
Structure:
<section> with inline CSS variables in a <style> block, preventing cross-contaminationLayout:
Interaction:
Mood-to-Preset Mapping (for "Show me options" path -- determines which 3 presets are highlighted):
| Mood | Recommended Presets |
|---|---|
| Impressed/Confident | Bold Signal, Electric Studio, Dark Botanical, Liquid Glass, Bento Box |
| Excited/Energized | Creative Voltage, Neon Cyber, Retro Futura |
| Calm/Focused | Notebook Tabs, Paper & Ink, Swiss Modern, Micrographic, Jewel Mono |
| Inspired/Moved | Dark Botanical, Vintage Editorial, Pastel Geometry, Director's Cut, Aurora Glow, Scrapbook |
Pick 3 presets from the matching mood(s). If the user selected 2 moods, pick 2 from the first mood and 1 from the second.
Logo in explorer: If the user provided images in Phase 1 and a logo was identified as USABLE, embed it (base64) into each preset's preview card. This creates a "wow moment" -- the user sees their own brand identity styled twenty different ways.
Open the theme explorer in the browser:
I've created a theme explorer for you to browse all available styles:
~/.claude/presentations/.theme-explorer/index.html
Open it in your browser to see each style in action. Click any card for a full-size preview, use arrow keys to cycle, and press Escape to return to the gallery.
Then use AskUserQuestion:
Question: Pick Your Style
If "Other", ask which preset name. If "Mix elements", ask for specifics.
Now generate the full presentation using the multi-file architecture.
Output directory: ~/.claude/presentations/[presentation-name]/
For agent persona prompts, see references/agent-team-prompts.md. For engagement defaults, see references/engagement-defaults.md. For multi-file architecture, see references/multi-file-architecture.md.
Check for the CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS environment variable:
echo $CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS
Branch to Step 3A (agent team) or Step 3B (sub-agent fallback).
Requires
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1This path uses agent teams for DEBATE and PLANNING only, then switches to parallel sub-agents for HTML generation. Agent teams excel at inter-agent discussion; sub-agents excel at independent parallel generation.
Based on the narrative outline slide count:
Before spawning teammates, the team lead (you) must:
Create the narrative outline with per-slide specifications:
Generate style.css:
Use the TeamCreate tool to create the team. You (the main session) are the
Story Architect and team lead.
TeamCreate(team_name="slides-[presentation-name]", description="Planning engagement for [presentation-name]")
Spawn teammate(s) using the Agent tool with team_name and name parameters:
# Always spawn:
Agent(
team_name="slides-[presentation-name]",
name="engagement-strategist",
subagent_type="general-purpose",
prompt="[Full Engagement Strategist persona from references/agent-team-prompts.md + narrative outline + engagement rules + style preset]"
)
# Only spawn if 16+ slides:
Agent(
team_name="slides-[presentation-name]",
name="visual-critic",
subagent_type="general-purpose",
prompt="[Full Visual Critic persona from references/agent-team-prompts.md + narrative outline]"
)
Debate phase:
After debate concludes, the Story Architect synthesizes all feedback into an enhanced narrative outline — the locked plan. This is the same outline from 3A.2 but enriched with engagement and visual decisions from the debate:
Write the enhanced outline to a file the sub-agents will read:
~/.claude/presentations/[presentation-name]/plan.md
Shut down teammates via SendMessage(type="shutdown_request") and clean up team resources.
IMPORTANT: Use standalone background sub-agents here, NOT agent team members. The debate team was shut down in Step 3A.5. Generation sub-agents must be spawned as independent background agents using
Agent(run_in_background: true)— do NOT passteam_nameornameparameters. Agent teams are for debate (Steps 3A.1-3A.5); sub-agents are for parallel generation (this step). Mixing these patterns causes coordination overhead and delivery problems.
Spawn 2-3 parallel sub-agents using a single message with multiple Agent tool calls,
each with run_in_background: true and subagent_type: "general-purpose".
Determine count based on slide count (same logic as Step 3B):
Each sub-agent receives in their prompt:
~/.claude/presentations/[name]/slides/)Each sub-agent writes their batch of slides/*.html files and returns: list of files written, any auto-animate pairs created.
CRITICAL: Wait for ALL sub-agents to complete before proceeding. Do NOT generate slides yourself while sub-agents are running — even if they appear slow. Sub-agents with detailed prompts produce specialized, high-quality output that ad-hoc generation cannot match. Generating HTML yourself while sub-agents run wastes their output, creates integration problems, and produces an inferior result. If a sub-agent crashes or fails (not just "takes a while"), only then should you generate its assigned slides yourself.
After all sub-agents complete:
Used when agent teams are not enabled
Display notice:
Agent teams not enabled. Using sub-agent fallback.
To enable agent teams, set CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
3B.1: Main session creates narrative outline (acts as Story Architect)
3B.2: Main session generates style.css
3B.3: Spawn 2-3 parallel sub-agents for slide generation
Spawn sub-agents (Agent tool, subagent_type: general-purpose, model: sonnet):
3B.4: Main session reviews engagement (acts as Engagement Reviewer)
Read all generated slides and apply engagement defaults:
3B.5: Main session assembles
If the user requested --single-file or mentioned wanting a portable file:
Features are organized by reference file. Load the relevant file when the presentation needs that feature.
Load when generating the SlidePresentation class JavaScript.
Load when the presentation includes images, video, diagrams, or animated widgets.
Load when the presentation needs presenter/audience tools.
Load ONLY when user opted in to inline editing in Phase 1.
Load when finalizing any presentation.
Load when generating style previews or applying a preset in Phase 2/3.
Load when generating any new presentation (Phase 3).
Load when generating slides (Phase 3) — both agent team and sub-agent paths.
Load when executing Phase 3 (Generate Presentation).
Fonts: Inter, Roboto, Arial, system fonts as display
Colors: #6366f1 (generic indigo), purple gradients on white
Layouts: Everything centered, generic hero sections, identical card grids
Decorations: Realistic illustrations, gratuitous glassmorphism, drop shadows without purpose
CSS Function Negation:
-clamp(), -min(), -max() are silently ignored by browsers with no console errorcalc(-1 * clamp(...)) instead/* WRONG — silently ignored by browsers: */
right: -clamp(28px, 3.5vw, 44px); /* Invalid! */
/* CORRECT — wrap in calc(): */
right: calc(-1 * clamp(28px, 3.5vw, 44px)); /* Works */
Responsive & Viewport Fitting (CRITICAL):
.slide must have height: 100vh; height: 100dvh; overflow: hidden;clamp()For animation patterns (entrance animations, staggered text, backgrounds, grain textures, interactive effects) and style-effect mapping, see references/html-architecture.md.
When converting PowerPoint files:
Use Python with python-pptx to extract all content. For each slide, collect:
slide.shapes.titleshape.has_text_frame shapesshape.shape_type == 13 (Picture) — save shape.image.blob to assets/ directoryslide.notes_slide.notes_text_frame if presentPresent the extracted content to the user and confirm before proceeding to style selection.
Proceed to Phase 2 (Style Discovery) with the extracted content in mind.
Convert the extracted content into the chosen style, preserving:
When the presentation is complete:
~/.claude/presentations/.theme-explorer/ if it existscd ~/.claude/presentations/[presentation-name] && python3 serve.py &
open http://localhost:8000
Your presentation is ready!
Folder: ~/.claude/presentations/[presentation-name]/
Slides: [count]
Style: [Style Name]
**To view:**
cd ~/.claude/presentations/[presentation-name]
python3 serve.py
# Then open http://localhost:8000
**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: Edit style.css (look for :root CSS variables)
- Individual slides: Edit files in slides/ directory
- Fonts: Change the font link in index.html
**To edit a specific slide:**
- Open slides/[NN]-[name].html in your editor
- Changes take effect on browser refresh
Would you like me to make any adjustments?
If user opted in to inline editing, add:
**Editing:**
- Hover over top-left corner or press E to enter edit mode
- Click any text to edit directly
- Ctrl+S or click "Save file" to save changes
If single-file was generated, add:
**Portable version:**
A single-file version is also available at:
~/.claude/presentations/[name]/[name].html
This file can be opened directly in any browser without a server.
After delivering the presentation, offer to export it to Google Slides or PDF.
Always mention export availability at the end of Phase 5 delivery. Add this to the summary:
**To export:**
- Google Slides: Just ask "export to Google Slides"
- PDF: Just ask "export to PDF"
The following must be installed (one-time setup):
npm install -g decktape
pip install google-api-python-client google-auth google-auth-httplib2 beautifulsoup4
gcloud auth application-default login \
--scopes=https://www.googleapis.com/auth/drive.file,https://www.googleapis.com/auth/presentations,https://www.googleapis.com/auth/cloud-platform
If the user asks to export and prerequisites are missing, guide them through setup first.
When the user asks to export to Google Slides:
Run the export script:
python3 ${CLAUDE_PLUGIN_ROOT}/skills/frontend-slides/scripts/export-to-gslides.py \
~/.claude/presentations/[presentation-name]/ \
--title "[Presentation Title]" \
--format gslides
Report results:
Exported to Google Slides!
Google Slides: [URL]
PDF: ~/.claude/presentations/[name]/[name].pdf
The presentation is shared via Google Slides (view-only).
Note: Animations and transitions are not preserved in Google Slides —
each fragment step becomes a separate slide. For the full animated
experience, use the original HTML version.
When the user asks for PDF only:
Run the export script:
python3 ${CLAUDE_PLUGIN_ROOT}/skills/frontend-slides/scripts/export-to-gslides.py \
~/.claude/presentations/[presentation-name]/ \
--format pdf
Report results:
PDF exported!
PDF: ~/.claude/presentations/[name]/[name].pdf
Each fragment step is a separate page. The PDF preserves the visual
appearance of each slide exactly as rendered.
npm install -g decktapegcloud auth application-default login command above--pause (default 2000ms). Increase for complex animations, decrease for simple slides.gcloud auth includes the drive.file scopeFor viewport troubleshooting (content overflow, text scaling, short screens), see references/viewport-fitting.md.
Fonts not loading: Check Fontshare/Google Fonts URL and font names in CSS.
Animations not triggering: Verify Intersection Observer is running and .visible class is being added.
Scroll snap not working: Ensure scroll-snap-type on html/body and scroll-snap-align: start on each slide.
Performance issues: Use will-change sparingly; prefer transform and opacity animations.
New presentation: User asks for pitch deck -> Phase 1 (purpose, content, images) -> Evaluate images -> Confirm outline -> Phase 2 (style path selection -> theme explorer -> pick style) -> Phase 3 (agent team generates multi-file presentation to ~/.claude/presentations/) -> Phase 5 (serve and open) -> Tweaks -> Done.
Single-file presentation: Same as above, but user requests --single-file -> Phase 3 generates multi-file first, then post-processes into one HTML file -> Open directly in browser -> Done.
PPT conversion: User provides .pptx -> Extract content/images -> Confirm structure -> Phase 2 (style selection) -> Generate HTML with preserved assets -> Done.
Export to Google Slides: User asks to export -> Check prerequisites -> Run export-to-gslides.py with --format gslides -> Report Google Slides URL and PDF path -> Done.
npx claudepluginhub jonnycbb/claude-code-config --plugin jiffy-toolkitCreates zero-dependency, animation-rich HTML presentations from scratch or by converting PowerPoint files. Useful when users request slide decks or pitch materials.
Creates zero-dependency, animation-rich HTML presentations from scratch or by converting PPT/PPTX files into self-contained slides for talks, pitches, or tutorials.
Generates zero-dependency HTML slide presentations with inline CSS/JS and animations. Use for new decks from scratch, PPT/PPTX conversions, or enhancing existing HTML presentations.