| 1 | # html-ppt — HTML PPT Studio |
| 2 | |
| 3 | > A world-class AgentSkill for producing professional HTML presentations in |
| 4 | > **36 themes**, **15 full-deck templates**, **36 page layouts**, |
| 5 | > **47 animations** (27 CSS + 20 canvas FX), and a **true presenter mode** |
| 6 | > with pixel-perfect previews + speaker script + timer — all pure static |
| 7 | > HTML/CSS/JS, no build step. |
| 8 | |
| 9 | **Author:** lewis <sudolewis@gmail.com> |
| 10 | **License:** MIT |
| 11 | **中文文档:** [README.zh-CN.md](README.zh-CN.md) |
| 12 | |
| 13 |  |
| 14 | |
| 15 | > One command installs **36 themes × 20 canvas FX × 36 layouts × 15 full decks + presenter mode**. Every preview above is a live iframe of a real template file rendering inside the deck — no screenshots, no mock-ups. |
| 16 | |
| 17 | ## 🎤 Presenter Mode (new!) |
| 18 | |
| 19 | Press `S` on any deck to pop open a dedicated presenter window with four |
| 20 | draggable, resizable **magnetic cards**: current slide, next slide preview, |
| 21 | speaker script (逐字稿), and timer. Two windows stay in sync via |
| 22 | `BroadcastChannel`. |
| 23 | |
| 24 |  |
| 25 | |
| 26 | **Why previews are pixel-perfect:** each card is an `<iframe>` that loads the |
| 27 | same deck HTML with a `?preview=N` query param. The runtime detects this and |
| 28 | renders only slide N with no chrome — so the preview uses the **same CSS, |
| 29 | theme, fonts and viewport** as the audience view. Colors and layout are |
| 30 | guaranteed identical. |
| 31 | |
| 32 | **Smooth (no-reload) navigation:** on slide change, the presenter window |
| 33 | sends `postMessage({type:'preview-goto', idx:N})` to each iframe. The iframe |
| 34 | just toggles `.is-active` between slides — **no reload, no flicker**. |
| 35 | |
| 36 | **Speaker script rules (3 golden):** |
| 37 | 1. **Prompt signals, not lines to read** — bold the keywords, separate |
| 38 | transition sentences into their own paragraphs |
| 39 | 2. **150–300 words per slide** — that's the ~2–3 min/page pace |
| 40 | 3. **Write it like you speak** — conversational, not written prose |
| 41 | |
| 42 | See [`references/presenter-mode.md`](references/presenter-mode.md) for the |
| 43 | full authoring guide, or copy the ready-made template at |
| 44 | `templates/full-decks/presenter-mode-reveal/` which ships with full 150-300 |
| 45 | word speaker scripts on every slide. |
| 46 | |
| 47 | ## Install (one command) |
| 48 | |
| 49 | ```bash |
| 50 | npx skills add https://github.com/lewislulu/html-ppt-skill |
| 51 | ``` |
| 52 | |
| 53 | That registers the skill with your agent runtime. After install, any agent |
| 54 | that supports AgentSkills can author presentations by asking things like: |
| 55 | |
| 56 | > "做一份 8 页的技术分享 slides,用 cyberpunk 主题" |
| 57 | > "turn this outline into a pitch deck" |
| 58 | > "做一个小红书图文,9 张,白底柔和风" |
| 59 | |
| 60 | ## Offline / manual install |
| 61 | |
| 62 | `npx skills add <url>` needs network on the target machine. Three alternatives, |
| 63 | in decreasing order of how much network they need. |
| 64 | |
| 65 | **1. Install from a local copy.** Fetch the repo anywhere, move the folder over |
| 66 | (git, zip, USB), then point the CLI at the directory instead of the URL: |
| 67 | |
| 68 | ```bash |
| 69 | git clone https://github.com/lewislulu/html-ppt-skill |
| 70 | npx skills add ./html-ppt-skill |
| 71 | ``` |
| 72 | |
| 73 | `npx` still downloads the `skills` package itself once. For a fully air-gapped |
| 74 | machine, run `npm i -g skills` on a connected one first, or use method 2. |
| 75 | |
| 76 | **2. Copy it in by hand — no Node, no CLI.** A skill is just a folder with |
| 77 | `SKILL.md` at its root. Drop it in the directory your agent scans: |
| 78 | |
| 79 | | Agent | Project scope | Global scope | |
| 80 | |---|---|---| |
| 81 | | Claude Code | `.claude/skills/html-ppt/` | `~/.claude/skills/html-ppt/` | |
| 82 | | Codex | `.agents/skills/html-ppt/` | `~/.codex/skills/html-ppt/` | |
| 83 | | Cursor | `.agents/skills/html-ppt/` | `~/.cursor/skills/html-ppt/` | |
| 84 | | OpenCode | `.agents/skills/html-ppt/` | `~/.config/opencode/skills/html-ppt/` | |
| 85 | | Gemini CLI | `.agents/skills/html-ppt/` | `~/.gemini/skills/html-ppt/` | |
| 86 | | Windsurf | `.windsurf/skills/html-ppt/` | `~/.codeium/windsurf/skills/html-ppt/` | |
| 87 | |
| 88 | ```bash |
| 89 | mkdir -p ~/.claude/skills |
| 90 | cp -R html-ppt-skill ~/.claude/skills/html-ppt |
| 91 | ls ~/.claude/skills/html-ppt/SKILL.md # must exist |
| 92 | ``` |
| 93 | |
| 94 | Only `SKILL.md`, `assets/`, `templates/`, `references/` and `scripts/` are |
| 95 | needed at runtime. `docs/` is ~4.6 MB of README artwork and can be dropped from |
| 96 | an offline copy. |
| 97 | |
| 98 | **3. No agent at all.** The templates are plain static files — usable directly: |
| 99 | |
| 100 | ```bash |
| 101 | ./scripts/new-deck.sh my-talk |
| 102 | open examples/my-talk/index.html |
| 103 | ``` |
| 104 | |
| 105 | ### Does it run without a network? |
| 106 | |
| 107 | Yes, with one caveat. Themes, layouts, animations, presenter mode and PNG |
| 108 | rendering are all local static HTML/CSS/JS with no build step and no runtime |
| 109 | fetches. The single remote dependency is `assets/fonts.css`, which `@import`s |
| 110 | Google Fonts. |
| 111 | |
| 112 | Offline, those imports simply fail and the browser falls back to the system |
| 113 | stack already declared in `assets/base.css` (`-apple-system` / Helvetica / |
| 114 | Georgia / Menlo), so decks render correctly — just in different typefaces. To |
| 115 | pin typography offline, replace `assets/fonts.css` with `@font-face` rules |
| 116 | pointing at font files you ship yourself, or delete the imports and accept the |
| 117 | system stack. |
| 118 | |
| 119 | ## What's in the box |
| 120 | |
| 121 | | | Count | Where | |
| 122 | |---|---|---| |
| 123 | | 🎤 **Presenter mode** | **NEW** | `S` key / `?preview=N` | |
| 124 | | 🎨 **Themes** | **36** | `assets/themes/*.css` | |
| 125 | | 📑 **Full-deck templates** | **15** | `templates/full-decks/<name>/` | |
| 126 | | 🧩 **Single-page layouts** | **36** | `templates/single-page/*.html` | |
| 127 | | ✨ **CSS animations** | **27** | `assets/animations/animations.css` | |
| 128 | | 💥 **Canvas FX animations** | **20** | `assets/animations/fx/*.js` | |
| 129 | | 🖼️ **Showcase decks** | 4 | `templates/*-showcase.html` | |
| 130 | | 📸 **Verification screenshots** | 56 | `scripts/verify-output/` | |
| 131 | |
| 132 | ### 36 Themes |
| 133 | |
| 134 | `minimal-white`, `editorial-serif`, `soft-pastel`, `sharp-mono`, `arctic-cool`, |
| 135 | `sunset-warm`, `catppuccin-latte`, `catppuccin-mocha`, `dracula`, `tokyo-night`, |
| 136 | `nord`, `solarized-light`, `gruvbox-dark`, `rose-pine`, `neo-brutalism`, |
| 137 | `glassmorphism`, `bauhaus`, `swiss-grid`, `terminal-green`, `xiaohongshu-white`, |
| 138 | `rainbow-gradient`, `aurora`, `blueprint`, `memphis-pop`, `cyberpunk-neon`, |
| 139 | `y2k-chrome`, `retro-tv`, `japanese-minimal`, `vaporwave`, `midcentury`, |
| 140 | `corporate-clean`, `academic-paper`, `news-broadcast`, `pitch-deck-vc`, |
| 141 | `magazine-bold`, `engineering-whiteprint`. |
| 142 | |
| 143 |  |
| 144 | |
| 145 | Each is a pure CSS-tokens file — swap one `<link>` to reskin the entire deck. |
| 146 | Browse them all in `templates/theme-showcase.html` (each slide rendered in an |
| 147 | isolated iframe so theme ≠ theme is visually guaranteed). |
| 148 | |
| 149 |  |
| 150 | |
| 151 | ### 15 Full-deck templates |
| 152 | |
| 153 | Eight extracted from real-world decks, seven generic scenario scaffolds: |
| 154 | |
| 155 | **Extracted looks** |
| 156 | - `xhs-white-editorial` — 小红书白底杂志风 |
| 157 | - `graphify-dark-graph` — 暗底 + 力导向知识图谱 |
| 158 | - `knowledge-arch-blueprint` — 蓝图 / 架构图风 |
| 159 | - `hermes-cyber-terminal` — 终端 cyberpunk |
| 160 | - `obsidian-claude-gradient` — 紫色渐变卡 |
| 161 | - `testing-safety-alert` — 红 / 琥珀警示风 |
| 162 | - `xhs-pastel-card` — 柔和马卡龙图文 |
| 163 | - `dir-key-nav-minimal` — 方向键极简 |
| 164 | |
| 165 | **Scenario decks** |
| 166 | - `pitch-deck`, `product-launch`, `tech-sharing`, `weekly-report`, |
| 167 | `xhs-post` (9-slide 3:4), `course-module`, |
| 168 | **`presenter-mode-reveal`** 🎤 — complete talk template with full 150-300 |
| 169 | word speaker scripts on every slide, designed around the `S` key presenter mode |
| 170 | |
| 171 | Each is a self-contained folder with scoped `.tpl-<name>` CSS so multiple |
| 172 | decks can be previewed side-by-side without collisions. Browse the full |
| 173 | gallery in `templates/full-decks-index.html`. |
| 174 | |
| 175 |  |
| 176 | |
| 177 | ### 36 Single-page layouts |
| 178 | |
| 179 | cover · toc · section-divider · bullets · two-column · three-column · |
| 180 | big-quote · stat-highlight · kpi-grid · table · code · diff · terminal · |
| 181 | flow-diagram · timeline · roadmap · mindmap · comparison · pros-cons · |
| 182 | todo-checklist · gantt · image-hero · image-grid · chart-bar · chart-line · |
| 183 | chart-pie · chart-radar · arch-diagram · process-steps · cta · thanks |
| 184 | |
| 185 | Every layout ships with realistic demo data so you can drop it into a deck |
| 186 | and immediately see it render. |
| 187 | |
| 188 |  |
| 189 | |
| 190 | *The big iframe is loading `templates/single-page/<name>.html` directly and cycling through all 36 layouts every 2.8 seconds.* |
| 191 | |
| 192 |  |
| 193 | |
| 194 | ### 27 CSS animations + 20 Canvas FX |
| 195 | |
| 196 | **CSS (lightweight)** — directional fades, `rise-in`, `zoom-pop`, `blur-in`, |
| 197 | `glitch-in`, `typewriter`, `neon-glow`, `shimmer-sweep`, `gradient-flow`, |
| 198 | `stagger-list`, `counter-up`, `path-draw`, `morph-shape`, `parallax-tilt`, |
| 199 | `card-flip-3d`, `cube-rotate-3d`, `page-turn-3d`, `perspective-zoom`, |
| 200 | `marquee-scroll`, `kenburns`, `ripple-reveal`, `spotlight`, … |
| 201 | |
| 202 | **Canvas FX (cinematic)** — `particle-burst`, `confetti-cannon`, `firework`, |
| 203 | `starfield`, `matrix-rain`, `knowledge-graph` (force-directed physics), |
| 204 | `neural-net` (signal pulses), `constellation`, `orbit-ring`, `galaxy-swirl`, |
| 205 | `word-cascade`, `letter-explode`, `chain-react`, `magnetic-field`, |
| 206 | `data-stream`, `gradient-blob`, `sparkle-trail`, `shockwave`, |
| 207 | `typewriter-multi`, `counter-explosion`. Each is a real hand-rolled canvas |
| 208 | module auto-initialised on slide enter via `fx-runtime.js`. |
| 209 | |
| 210 | ## Quick start (manual, after install or git clone) |
| 211 | |
| 212 | ```bash |
| 213 | # Scaffold a new deck from the base template |
| 214 | ./scripts/new-deck.sh my-talk |
| 215 | |
| 216 | # ...or from a full-deck template, into any directory you like. |
| 217 | # Asset paths are computed for wherever the deck lands, then verified. |
| 218 | ./scripts/new-deck.sh my-talk ~/decks -t pitch-deck |
| 219 | |
| 220 | # Browse everything |
| 221 | open templates/theme-showcase.html # all 36 themes (iframe-isolated) |
| 222 | open templates/layout-showcase.html # all 36 layouts |
| 223 | open templates/animation-showcase.html # all 47 animations |
| 224 | open templates/full-decks-index.html # all 15 full decks |
| 225 | |
| 226 | # Render any template to PNG via headless Chrome |
| 227 | ./scripts/render.sh templates/theme-showcase.html |
| 228 | ./scripts/render.sh examples/my-talk/index.html 12 |
| 229 | ``` |
| 230 | |
| 231 | ## Images on a slide |
| 232 | |
| 233 | Five layouts take real images — pick by how many the page has to carry: |
| 234 | |
| 235 | | I have… | Layout | |
| 236 | |---|---| |
| 237 | | one screenshot / diagram / chart | `image-single.html` — letterboxed, never cropped | |
| 238 | | one photo that should carry the page | `image-full-bleed.html` — fills the slide, scrim keeps the title readable | |
| 239 | | one image plus an argument | `image-text-split.html` — 50/50, `flip` to swap sides | |
| 240 | | 3–6 images | `image-gallery.html` — uniform grid, one caption each | |
| 241 | | a before and an after | `image-compare.html` — both sides identical size | |
| 242 | |
| 243 | They share one primitive from `assets/base.css`: |
| 244 | |
| 245 | ```html |
| 246 | <figure class="img-frame"><img src="shot.png" alt=""></figure> <!-- crops to fill --> |
| 247 | <figure class="img-frame contain"><img src="diagram.svg" alt=""></figure> <!-- letterboxed --> |
| 248 | ``` |
| 249 | |
| 250 | The frame owns the aspect ratio (`--img-ratio`) and the crop, so you can drop in |
| 251 | a portrait, square or ultrawide image without touching the layout. Placeholder |
| 252 | artwork in `assets/demo-images/` is hand-written SVG (~1 KB each) so every |
| 253 | layout renders **offline**. |
| 254 | |
| 255 | ## Custom logo |
| 256 | |
| 257 | Brand a deck with one attribute — no per-slide `<img>` copy-paste: |
| 258 | |
| 259 | ```html |
| 260 | <body data-logo="logo.svg" data-logo-position="bottom-right" data-logo-size="40px"> |
| 261 | ``` |
| 262 | |
| 263 | `data-logo-position` takes `top-left` / `top-right` / `bottom-left` / |
| 264 | `bottom-right` (default `top-right`); `data-logo-size` sets the height. |
| 265 | Skip it on a single slide with `<section class="slide" data-no-logo>` — handy |
| 266 | for the cover. The logo also shows in the presenter preview, and on **every |
| 267 | page** of a PDF export (skipping the `data-no-logo` ones). |
| 268 | |
| 269 | Prefer to place it yourself? `<img class="deck-logo" data-pos="top-left" src="logo.svg">` |
| 270 | inside `.deck` works with no JS at all. |
| 271 | |
| 272 | ## Keyboard cheat sheet |
| 273 | |
| 274 | On a phone or tablet, **swipe left for the next slide, right for the previous |
| 275 | one** — no keyboard needed. Pinch-zoom, vertical scrolling, the overview grid |
| 276 | and the notes drawer are left alone. |
| 277 | |
| 278 | ``` |
| 279 | ← → Space PgUp PgDn Home End navigate |
| 280 | swipe ← / → (touch) navigate |
| 281 | F fullscreen |
| 282 | S open presenter window (magnetic cards) |
| 283 | N quick notes drawer (bottom) |
| 284 | R reset timer (in presenter window) |
| 285 | O slide overview grid |
| 286 | T cycle themes (syncs to presenter) |
| 287 | A cycle a demo animation on current slide |
| 288 | #/N (URL) deep-link to slide N |
| 289 | ?preview=N (URL) preview-only mode (single slide, no chrome) |
| 290 | ``` |
| 291 | |
| 292 | ## Project structure |
| 293 | |
| 294 | ``` |
| 295 | html-ppt-skill/ |
| 296 | ├── SKILL.md agent-facing dispatcher |
| 297 | ├── README.md this file |
| 298 | ├── references/ detailed catalogs |
| 299 | │ ├── themes.md 36 themes with when-to-use |
| 300 | │ ├── layouts.md 31 layout types |
| 301 | │ ├── animations.md 27 CSS + 20 FX catalog |
| 302 | │ ├── full-decks.md 15 full-deck templates |
| 303 | │ └── authoring-guide.md full workflow |
| 304 | ├── assets/ |
| 305 | │ ├── base.css shared tokens + primitives |
| 306 | │ ├── fonts.css webfont imports |
| 307 | │ ├── runtime.js keyboard + presenter + overview |
| 308 | │ ├── themes/*.css 36 theme token files |
| 309 | │ └── animations/ |
| 310 | │ ├── animations.css 27 named CSS animations |
| 311 | │ ├── fx-runtime.js auto-init [data-fx] on slide enter |
| 312 | │ └── fx/*.js 20 canvas FX modules |
| 313 | ├── templates/ |
| 314 | │ ├── deck.html minimal starter |
| 315 | │ ├── theme-showcase.html iframe-isolated theme tour |
| 316 | │ ├── layout-showcase.html all 36 layouts |
| 317 | │ ├── animation-showcase.html 47 animation slides |
| 318 | │ ├── full-decks-index.html 15-deck gallery |
| 319 | │ ├── full-decks/<name>/ 15 scoped multi-slide decks |
| 320 | │ └── single-page/*.html 31 layout files with demo data |
| 321 | ├── scripts/ |
| 322 | │ ├── new-deck.sh scaffold |
| 323 | │ ├── render.sh headless Chrome → PNG |
| 324 | │ └── verify-output/ 56 self-test screenshots |
| 325 | └── examples/demo-deck/ complete working deck |
| 326 | ``` |
| 327 | |
| 328 | ## Philosophy |
| 329 | |
| 330 | - **Token-driven design system.** All color, radius, shadow, font decisions |
| 331 | live in `assets/base.css` + the current theme file. Change one variable, |
| 332 | the whole deck reflows tastefully. |
| 333 | - **Iframe isolation for previews.** Theme / layout / full-deck showcases all |
| 334 | use `<iframe>` per slide so each preview is a real, independent render. |
| 335 | - **Zero build.** Pure static HTML/CSS/JS. CDN only for webfonts, highlight.js |
| 336 | and chart.js (optional). |
| 337 | - **Senior-designer defaults.** Opinionated type scale, spacing rhythm, |
| 338 | gradients and card treatments — no "Corporate PowerPoint 2006" vibes. |
| 339 | - **Chinese + English first-class.** Noto Sans SC / Noto Serif SC pre-imported. |
| 340 | |
| 341 | ## License |
| 342 | |
| 343 | MIT © 2026 lewis <sudolewis@gmail.com>. |
| 344 |