with one click
slide-creator
// Create presentation slide decks as HTML and auto-export to 16:9 PDF. Use when the user asks to make a PPT, slide deck, presentation, or pitch deck. Final output is a PDF file — not PowerPoint format.
// Create presentation slide decks as HTML and auto-export to 16:9 PDF. Use when the user asks to make a PPT, slide deck, presentation, or pitch deck. Final output is a PDF file — not PowerPoint format.
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | slide-creator |
| version | 2.1.4 |
| description | Create presentation slide decks as HTML and auto-export to 16:9 PDF. Use when the user asks to make a PPT, slide deck, presentation, or pitch deck. Final output is a PDF file — not PowerPoint format. |
| metadata | {"starchild":{"emoji":"🎞️","skillKey":"slide-creator","install":[{"kind":"pip","package":"playwright"},{"kind":"pip","package":"PyMuPDF"}]}} |
| user-invocable | true |
Build slide decks as HTML, export to pixel-perfect 16:9 PDF via headless Chromium.
Output format: PDF — not Microsoft PowerPoint (.pptx). The PDF preserves exact layout, fonts, and colors across all devices.
Before any other step, identify the presentation scenario. Read references/content-scaffolding.md for full templates.
| Scenario keyword | Template to use |
|---|---|
| pitch / investor / fundraising | pitch-deck |
| conference / keynote / summit / talk | conference-keynote |
| product launch / launch event | product-launch |
| report / research / analysis | research-report |
| (none of the above) | ask user which scenario fits best |
Each template defines: slide count, page titles, required content per page.
If the audience is bilingual (e.g. HK, Singapore, global Chinese conference), or the user mentions Chinese + English:
bilingual layout mode from references/content-scaffolding.mdDefine slide count and content per slide based on the scenario template. Each slide = one <section class="slide">.
Run this step whenever the user hasn't provided a specific visual style. Read
skills/slide-creator/references/art-direction.mdfor the full style taxonomy, CSS token templates, and style-brief output format.
Step A — Ask 4 questions:
Step B — Generate a visual style picker page: Do NOT present style options as text descriptions — users can't evaluate styles from words alone.
Reference handling rules:
web_fetch to extract design cues. Critical — follow this extraction protocol to avoid misreading the style:
Then:
output/style-picker/index.html — a single page with 3 side-by-side mini slide previews (16:9 aspect ratio), each fully rendered with real CSS (colors, fonts, layout, decorative elements). Each preview must look like an actual slide, not a color chip.preview_serve the directory and show the preview URL.onclick highlight so the user can click to indicate their choice.User picks by saying "Choose A" / "I want B" / "Blend A+C" etc.
Step C — Generate style-brief.md:
Once user selects a style, write a style-brief.md (template in art-direction.md) in the project directory.
All subsequent HTML/CSS work must follow this brief.
Step D — Ask for brand assets (logo / colors): After user picks a style, ask:
"Do you have a logo or brand color to include? You can upload an image file, and I’ll embed the logo across the slides."
If logo uploaded: embed as base64 in HTML (use base64.b64encode in bash), place in top-left or top-right corner at ≤60px height.
If brand color given: override --accent in CSS token block with user's color.
If Art Direction was completed, the style-brief.md is the theme spec — skip this table.
Otherwise, use as a quick fallback:
| Style | Background | Accent | Font | Mood |
|---|---|---|---|---|
| Dark tech | #000 / #0a0a0a | bright orange/blue/green | Inter, Space Grotesk | Bold, modern |
| Light clean | #fff / #f8f8f8 | navy, teal, coral | Inter, DM Sans | Professional, minimal |
| Gradient | dark gradient | vibrant accent | Any sans-serif | Creative, energetic |
| Corporate | #1a1a2e / white | brand color | system fonts | Trustworthy, formal |
| Playful | soft pastels | warm pop colors | Nunito, Poppins | Friendly, casual |
Create a project directory with index.html + styles.css.
Start from assets/base.css — structural skeleton (slide dimensions, print rules, layout helpers) with NO colors or fonts. Layer your theme on top:
/* Example theme layer — customize freely */
body {
font-family: 'Inter', sans-serif;
color: #fff;
background: #000;
}
.slide { background: #0a0a0a; }
.slide-tag { background: rgba(0,120,255,0.15); color: #0078ff; }
.card { background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.08); }
Mandatory structural rules (in base.css — don't remove):
.slide { width: 1280px; height: 720px; page-break-after: always; overflow: hidden; }
@page { size: 1280px 720px; margin: 0; }
Key rules:
px units — never vh/vw/rem/% for slide dimensions<link> in <head>, export script waits for network idle<meta name="viewport" content="width=1280">Use preview_serve to preview in browser before exporting.
python3 skills/slide-creator/scripts/export_pdf.py --dir <project-dir> --output output/<name>.pdf
Options:
--dir — directory containing index.html (required)--output / -o — output PDF path (default: <dir>/deck.pdf)--width — slide width in px (default: 1280)--height — slide height in px (default: 720)The script prints slide count and confirms output path. Extra check:
import fitz
doc = fitz.open("output/deck.pdf")
print(f"Pages: {doc.page_count}")
for p in doc:
r = p.rect
print(f" {r.width*96/72:.0f}x{r.height*96/72:.0f}px")
style-brief.md).bg-glow with theme-colored radial gradients for depthweb_search for style exploration by default; prioritize user-provided reference images/links plus templates in art-direction.md.web_fetch to extract design cues (color tone / voice / layout), but implement final CSS using local templates and token variables.If user says "change primary color to red" / "switch the font" / "increase corner radius", do NOT restart art direction.
Instead, directly patch the --accent / --font-head / --radius CSS variable in styles.css.
Only restart art direction if user wants a completely different style.
Chromium deps: first run needs python3 -m playwright install chromium && python3 -m playwright install-deps chromium
Fonts: Google Fonts need HTTP — the export script starts a local server automatically
Emoji rendering: headless Chromium may lack emoji fonts — use SVG icons instead
Large images: embed as base64 or use relative paths (local server serves the project dir)
Slide overflow: content exceeding 720px height is clipped — design within bounds
⚠️ PDF text not selectable (verified 2026): filter / backdrop-filter CSS on any ancestor containing text causes Chromium to rasterize that layer to bitmap during PDF export — all child text becomes pixels, not selectable. Fix: NEVER apply filter/backdrop-filter to containers holding text. Only apply to empty decorative <div> elements (e.g. .blur-layer, .glow-overlay) with no text children. Same rule applies to mix-blend-mode on text parents. Pre-export checklist: search HTML for filter/backdrop-filter on non-decorative elements and strip them.
⚠️ Footer / source attribution — use standard component + strict bottom-safe-area contract (verified 2026): ad-hoc footer markup causes inconsistent positioning across slides. Always use this .slide-footer pattern for all source citations, page numbers, and disclaimers.
Hard layout contract (do not skip):
.slide-body) that reserves footer space..slide-body must reserve footer space with bottom-safe-area >= 96px (default 96px). Example: .slide-body { padding: 52px 72px 96px; }.position: absolute; bottom: 24px, as a sibling of .slide-body directly under .slide..slide-body..slide-footer.This enforces physical separation: body content area ends above a reserved footer lane, and footer stays in the canvas-bottom lane, so they never overlap regardless of content density.
<footer class="slide-footer">
<span class="footer-source">Source: CoinGecko · Coinglass · DefiLlama</span>
<span class="footer-page">03 / 12</span>
</footer>
.slide-footer {
position: absolute;
bottom: 24px; left: 48px; right: 48px;
display: flex; justify-content: space-between; align-items: center;
font-size: 11px; color: rgba(255,255,255,0.35);
border-top: 1px solid rgba(255,255,255,0.08);
padding-top: 8px;
z-index: 2;
}
.slide > *:not(.bg-glow):not(.slide-footer) {
position: relative;
z-index: 1;
}
.slide-body { padding-bottom: 96px; }
Never use in-flow / position: relative footers — they shift when slide content height changes. Also exclude .slide-footer from generic .slide > * stacking rules, or CSS order can accidentally override footer layering.
Validation checklist (required before export):
.slide-body and .slide-footer as siblings;.slide-body bottom padding is >=96px;.slide-footer, never in body containers.⚠️ z-index / decorative overlay bug (verified 2026): .bg-glow and other decorative pseudo-layers MUST be positioned with z-index: 0 and all real slide content given z-index: 1 explicitly. If .bg-glow is a sibling of .slide > * (not a ::before/::after pseudo-element), add this rule to ensure content is never visually buried:
.slide > *:not(.bg-glow) { position: relative; z-index: 1; }
.bg-glow { position: absolute; z-index: 0; pointer-events: none; }
Failure mode: PDF exports show content pushed to the bottom or invisible, even though browser preview looks fine (browser compositing handles z-order more forgivingly than Chromium's print path).