Builds presentation decks as HTML and exports them to 16:9 PDF via headless Chromium, not PowerPoint files. Comes with content scaffolding for pitch decks, conference keynotes, product launches, and research reports. The art direction workflow is surprisingly thorough: it generates a visual style picker with three rendered preview options, extracts design cues from reference URLs or uploaded images, and writes a style brief before you build anything. Supports bilingual layouts for Hong Kong and Singapore audiences. Uses CSS Grid and Flexbox for layout, which gives you more control than dragging boxes around in Keynote, and the output is git-friendly. If you need pixel-perfect PDFs and want to avoid the usual presentation software, this does the job.
npx -y skills add starchild-ai-agent/official-skills --skill slide-creator --agent claude-codeInstalls into .claude/skills of the current project.
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(action='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(action='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: pre-installed via workspace/setup.sh on container start (~641 MB cached at ~/.cache/ms-playwright/). Do NOT run playwright install on every export — it re-downloads the same browser. Only run it if export_pdf.py fails with Executable doesn't exist, and in that case also append the command to workspace/setup.sh so it persists.
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).
sickn33/antigravity-awesome-skills
moizibnyousaf/ai-agent-skills
github/awesome-copilot