SuperAPI AI Directory

html-to-pdf

Office & productivity

View repository

Updated 10-31 08:32

About this skill

HTML to PDF

Chromium renders the file exactly as a browser would — @page, flexbox, grid, webfonts, SVG, @media print, and JavaScript all work — and writes a PDF.

Source: the option surface and troubleshooting come from html-to-pdf-skill; the deck capture from frontend-slides. See the plugin's NOTICE.md.

Pick the mode first

This is the only decision that matters, and getting it wrong produces a PDF that looks plausible in the file listing and is wrong when opened.

Input Mode
Report, one-pager, explainer, dashboard — anything that scrolls --mode page (default)
Slide deck whose slides carry class="slide" --mode slides

A deck's print stylesheet un-hides every slide and page-breaks between them, so --mode page does emit one page per slide — at paper size, in portrait, with a 1920x1080 composition squeezed into it, and with every slide but the one that was active rendered blank, because entrance animations key off a class the deck only sets on the current slide. Measured on a four-slide deck: A4 portrait pages, three of them empty.

--mode slides shows each slide in turn at stage resolution, pins the entrance animations to their finished state, captures each one and assembles the captures into a 16:9 PDF.

If the file's mode is not obvious, grep it: class="slide" on repeated elements means a deck.

Run it

node "${CLAUDE_PLUGIN_ROOT}/skills/html-to-pdf/scripts/html-to-pdf.mjs" report.html

Output defaults to the input path with a .pdf extension. Pass a second path to choose the output, or several .html inputs to convert them in one run.

First run installs Playwright into ~/.workhub/visuals-playwright, which downloads Chromium and takes about a minute. Nothing is installed into the project. Tell the user before starting so the pause is expected. If the automatic install fails, fall back to:

npm install -g playwright
npx playwright install chromium

Documents — --mode page

Read the file first. If it declares @page, honour it:

node "${CLAUDE_PLUGIN_ROOT}/skills/html-to-pdf/scripts/html-to-pdf.mjs" \
  --prefer-css-page-size --outline report.html report.pdf

--outline builds PDF bookmarks from the headings, which is what makes a long report navigable. Prefer it whenever the document has real heading structure. Chromium derives the outline from the tagged structure tree, so --outline turns --tagged on by itself; passing --outline alone to Playwright produces a PDF with no bookmarks and no warning.

Without @page in the CSS, set the paper explicitly:

node "${CLAUDE_PLUGIN_ROOT}/skills/html-to-pdf/scripts/html-to-pdf.mjs" \
  --format A4 --margin-top 20mm --margin-bottom 20mm \
  --margin-left 18mm --margin-right 18mm doc.html

Page numbers go in a footer template:

node "${CLAUDE_PLUGIN_ROOT}/skills/html-to-pdf/scripts/html-to-pdf.mjs" \
  --footer-template '<div style="font-size:9px;width:100%;text-align:center">Page <span class="pageNumber"></span> / <span class="totalPages"></span></div>' \
  doc.html

Wide tables read better rotated: --landscape.

Decks — --mode slides

node "${CLAUDE_PLUGIN_ROOT}/skills/html-to-pdf/scripts/html-to-pdf.mjs" \
  --mode slides deck.html deck.pdf

Each slide becomes one 1920x1080 page. Animation is flattened to its finished state — say so when handing the PDF over, so the user is not surprised that the motion is gone.

An 18-slide deck lands around 20MB. Past roughly 10MB, offer --compact (1280x720), which typically halves the size with no visible loss at reading distance.

Options

--mode page|slides        page (default) paginates; slides captures each .slide
--format FORMAT           A4 (default), Letter, Legal, A0-A6
--landscape               landscape orientation
--prefer-css-page-size    obey @page size and margins from the CSS
--margin-top|-right|-bottom|-left DIM    e.g. 20mm, 1in, 72pt
--outline                 PDF bookmarks from h1-h6
--tagged                  accessibility tags
--scale N                 zoom factor (default 1.0)
--no-background           omit background colours and images
--header-template HTML    page header (page mode)
--footer-template HTML    page footer (page mode)
--compact                 capture decks at 1280x720
--width N / --height N    explicit capture size (slides mode)
--quiet, -q               suppress progress output

Finish

Report the output path and size, and name anything that was flattened (animation, interactivity, the theme toggle). Do not open the PDF unless the user asked for it.

Troubleshooting

Symptom Cause Fix
Deck pages are portrait, and all but one are blank ran --mode page on a deck use --mode slides
"no .slide elements found" not a fixed-stage deck, or a different class name use --mode page, or rename the slide class
Background colours missing --no-background was passed, or the page has no print rules drop the flag; add print-color-adjust: exact to the CSS
@page rules ignored the flag was not passed add --prefer-css-page-size
Fonts look wrong the face is not installed locally use a webfont, or embed it with @font-face
Images missing absolute filesystem paths in src make the paths relative to the HTML; the script serves that directory over HTTP
Blank pages content renders after networkidle have the page finish its work on load rather than on a timer
Text not selectable the content is a raster image expected; only OCR changes that
Install fails behind a proxy npm or the Chromium download is blocked install Playwright manually on a network that allows it