Html to pptx skill
● Export HTML slide decks to PPTX or images using Claude Code skills — powered by headless Chrome and Pillow.
npx -y skills add Alienxcript/html-export-skills --skill html-to-pptx skillAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Convert a single-file HTML slide deck into a pixel-perfect PPTX by rendering it in headless Chrome, taking a full-page screenshot, slicing it into per-slide images with Pillow, and packing them into a PowerPoint file. Use when the user has an HTML presentation and wants a .pptx export.
SKILL.md
5.1 KB, as published. Nobody here has run it
HTML to PPTX Skill
Convert any single-file HTML slide deck into a .pptx file that looks exactly like the browser render — fonts, glows, gradients, animations frozen at their initial state.
How It Works
- Headless Chrome (via Puppeteer) renders the HTML at 1920×1080 and takes a single
fullPage: truescreenshot → one tall PNG - Pillow slices that PNG into N equal strips (one per slide)
- python-pptx packs each strip as a full-bleed image on its own PPTX slide
This avoids all scroll/clip coordinate bugs — each slide is a guaranteed unique pixel crop.
Requirements Check
Before running, verify these are available:
node+puppeteernpm package (installed locally or globally)pythonwithpillowandpython-pptxpackages- Chrome or Edge executable on the system
Step-by-Step Instructions
1. Ask the user for inputs
You need:
- HTML file path — the source presentation
- Number of slides — how many slides the deck has
- Output PPTX filename — where to save (default: same folder as HTML, same name with
.pptx) - Slide aspect ratio — default 16:9 (1920×1080). Ask only if non-standard.
- Chrome path — auto-detect from common locations, only ask if not found
Auto-detect Chrome from these paths (check in order):
C:/Program Files/Google/Chrome/Application/chrome.exeC:/Program Files (x86)/Google/Chrome/Application/chrome.exeC:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe/usr/bin/google-chrome/usr/bin/chromium-browser
2. Install puppeteer if needed
# Check
node -e "require('puppeteer')" 2>&1
# Install locally in the HTML file's directory if missing
npm install puppeteer --save-dev
3. Write the screenshot script
Write _screenshot.mjs to the same folder as the HTML:
import puppeteer from 'puppeteer';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const HTML_PATH = path.join(__dirname, '<HTML_FILENAME>');
const W = 1920;
const H = 1080;
const browser = await puppeteer.launch({
executablePath: '<CHROME_PATH>',
headless: true,
args: ['--no-sandbox', `--window-size=${W},${H}`],
});
const page = await browser.newPage();
await page.setViewport({ width: W, height: H, deviceScaleFactor: 1 });
await page.goto(`file:///${HTML_PATH.replace(/\\/g, '/')}`, {
waitUntil: 'networkidle0',
timeout: 30000,
});
// Wait for fonts and transitions to settle
await new Promise(r => setTimeout(r, 2500));
// Freeze animations, hide fixed UI chrome
await page.addStyleTag({ content: `
* { animation: none !important; transition: none !important; }
body::after { display: none !important; }
#nav, #progress, nav, header[data-fixed] { display: none !important; }
` });
await page.screenshot({
path: path.join(__dirname, '_fullpage.png'),
fullPage: true,
});
console.log('Done.');
await browser.close();
4. Write the slice + pack script
Write _pack_pptx.py to the same folder:
from PIL import Image
from pptx import Presentation
from pptx.util import Inches
import os
FOLDER = r'<FOLDER_PATH>'
FULLPAGE = os.path.join(FOLDER, '_fullpage.png')
OUT = os.path.join(FOLDER, '<OUTPUT_FILENAME>')
SLIDES = <SLIDE_COUNT>
img = Image.open(FULLPAGE)
W, H = img.size
slide_h = H // SLIDES
print(f"Full image: {W}x{H}, {SLIDES} slides, {slide_h}px each")
prs = Presentation()
prs.slide_width = Inches(20) # 1920px at 96dpi
prs.slide_height = Inches(11.25) # 1080px at 96dpi
blank = prs.slide_layouts[6]
for i in range(SLIDES):
top = i * slide_h
crop = img.crop((0, top, W, top + slide_h))
tmp = os.path.join(FOLDER, f'_slide_{i+1:02d}.png')
crop.save(tmp)
slide = prs.slides.add_slide(blank)
slide.shapes.add_picture(tmp, left=0, top=0,
width=prs.slide_width,
height=prs.slide_height)
print(f" Slide {i+1:02d} rows {top}-{top+slide_h}")
prs.save(OUT)
print(f"Saved: {OUT}")
5. Run both scripts
node _screenshot.mjs
python _pack_pptx.py
6. Clean up temp files
After confirming the PPTX looks correct, delete:
_fullpage.png_screenshot.mjs_pack_pptx.py_slide_01.png…_slide_NN.png
Common Issues
| Problem | Cause | Fix |
|---|---|---|
| All slides identical | Using clip:{y:0} on scrolled viewport | Always use fullPage:true + slice — never scroll |
| PermissionError on save | PPTX open in PowerPoint | Close the file first, or save to a new filename |
| Fonts wrong in PPTX | Custom web fonts not installed locally | This approach embeds pixel images so fonts are always correct |
| Slide count wrong | H // SLIDES rounding | Check H % SLIDES == 0; if not, slides have min-height inconsistency in HTML |
| Chrome not found | Wrong exe path | Check Edge as fallback |
Gives 0 of the 12 instructions most pdf office docs skills give
Counted across 635 of the 690 authors here whose files we hold, read 2026-08-06
- extract text using pdfplumberin 92 of 635, across 25 files
- create PDFs using reportlabin 83 of 635, across 16 files
- read FORMS.md to fill out PDF formsin 80 of 635, across 13 files
- OCR scanned PDFs using pytesseractin 77 of 635, across 10 files
- merge or split PDFs using qpdfin 70 of 635, across 3 files
- use Excel formulas instead of hardcoded calculated valuesin 68 of 635, across 12 files
- unpack edit xml and repack existing documentsin 63 of 635, across 8 files
- document sources for hardcoded valuesin 61 of 635, across 9 files
- write minimal python code without unnecessary commentsin 59 of 635, across 7 files
- run the recalculation script after adding or modifying formulasin 58 of 635, across 6 files
- fix all identified formula errors and recalculatein 58 of 635, across 6 files
- format years as text stringsin 57 of 635, across 5 files
Said here and by no other author read
- ask the user for the html file path and slide count
- render the HTML in headless Chrome at 1920x1080
- take a full page screenshot of the presentation
- freeze CSS animations and transitions before screenshotting
- hide fixed UI chrome elements before screenshotting
- slice the full page image into equal vertical strips
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once.