Pdf onepager
Use when creating a printable PDF one-pager, lead magnet, worksheet, survey template, cheat sheet, or downloadable framework asset for ANY organization. Generates brand-aligned, print-safe, AI-citation-ready TAGGED PDFs (US Letter + A4) from HTML/CSS via WeasyPrint, with a setup script, a render driver, and a QA verifier. Ships a neutral default plus example brand presets. Triggers: "make/build/generate/create a PDF", "downloadable template", "printable worksheet", "PDF lead magnet", "one-pager PDF", "PDF cheat sheet".From its SKILL.md
npx -y skills add FeedbackPulseApp/hr-skills --skill pdf-onepagerAssembled 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.
- 2 stars2 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.
SKILL.md
8.0 KB, ~2.1k tokens by cl100k_base, as published. Nobody here has run it
pdf-onepager
Produces high-craft, print-safe, AI-citation-ready one/two-page PDFs from
HTML + print CSS rendered by WeasyPrint — not a design tool, not a flattened
image. You edit a content HTML file; gen.py renders it to a tagged PDF in both
US Letter and A4 plus a PNG preview; verify.py gates the citation/utility
checklist before you ship.
Why this approach: the asset's whole value is that its text is selectable, its metadata is set, and its source URL is live in the document — the citation infrastructure that makes ChatGPT, Perplexity, and Google AI Overview cite it. WeasyPrint emits tagged PDF/UA from clean HTML, and CSS handles the layout math (centering, columns, page breaks) for you.
It works for any brand out of the box: a neutral default preset plus two
worked examples (feedbackpulse, enpstools). Make your own by copying one
file. Paths below are relative to the skill directory (where this file lives).
Setup (one-time)
cd <skill-dir> # the folder containing this SKILL.md
./setup.sh # installs native deps hint, builds .venv, smoke-renders
setup.sh is idempotent. It needs system libraries for WeasyPrint; if they are
missing it prints the exact install line for your OS:
- macOS:
brew install pango cairo gdk-pixbuf libffi poppler - Debian/Ubuntu:
sudo apt-get install -y libpango-1.0-0 libpangocairo-1.0-0 libgdk-pixbuf-2.0-0 libffi-dev poppler-utils
If the skill is installed read-only via the plugin marketplace, copy gen.py,
verify.py, setup.sh, requirements.txt, styles/, templates/, fonts/
into your project (or clone the repo) and run there, so the .venv and out/
have a writable home.
Run (agent path) — render + verify
cd <skill-dir>
# Neutral default brand (Atkinson Hyperlegible + indigo), Letter + A4 + preview:
./.venv/bin/python gen.py templates/starter.html
# A real example, branded, one flag to swap brand:
./.venv/bin/python gen.py templates/example-sbi.html --brand feedbackpulse
# QA against the citation checklist (exit 0 = ship-able):
./.venv/bin/python verify.py out/starter.pdf --source yourdomain.com/your-source-page
gen.py writes <stem>.pdf (Letter), <stem>-a4.pdf (A4), and
<stem>-preview.png (page-1 render) into --out (default out/). Open the
preview and actually look at it — verify.py checks structure, not whether the
layout looks good.
verify.py FAILs (blocking) on: missing Title/Author/Subject/Keywords/Creator,
no /Lang, untagged PDF (no StructTreeRoot), any page without selectable text,
or the --source URL missing from the text. WARNs on file size over 600 KB.
Authoring a NEW asset
- Copy the starter, keep the structure, replace every
[bracketed]placeholder:cp templates/starter.html templates/<your-slug>.html - Set the metadata in
<head>—<title>,<meta name="author|description| keywords|generator">, and<html lang>. WeasyPrint reads these into the PDF properties; they are how AI engines identify the document. Do not leave blank. - Set the running-footer URL — the one per-document override:
body { string-set: docsource "yourdomain.com/the-page"; }. Put the same URL in the masthead link and the.docfootso the citation appears three times. - Use the components in
styles/base.css:.definition(tinted intro),.framework/.col(equal columns with rules),.callout-key(the single loudest element — make it the memorable hook),.worksheet/.fill(dotted fill-in lines),.cols2,.checklist,.page-2(back of the one-pager). - Render + verify + LOOK. If page 1 overflows, adjust margins/font-size in
the HTML's
<style>or base.css; WeasyPrint reflows, so don't fight pixels. - Manual AI test (required, can't be automated): drag the PDF into both ChatGPT and Claude and ask "What is this document and where can I read more?" The answer must name the topic and surface your source URL. If not, the metadata or footer URL is wrong — fix and re-render.
- Ship to a STABLE URL. Host at
/assets/downloads/<slug>.pdf(and-a4.pdf), publicly (not behind a form). When you update, replace the file at the same URL — never version the path, or backlinks and AI citations break. Optionally addDigitalDocumentJSON-LD on the page that links it.
Make it your brand
Only colors and fonts are brand-specific; layout is shared. To add a brand:
cp styles/brand-template.css styles/brand-acme.css # then fill in colors/fonts
./.venv/bin/python gen.py templates/starter.html --brand acme
brand-template.css is fully commented. The one rule that matters is contrast:
--accent is your vivid color for fills/rules; --accent-deep is for accent
text on white and must clear 4.5:1; --callout-bg/--on-callout is the loudest
block and must also clear 4.5:1 (if your brand color is too light for white text,
use a navy/near-black there — see brand-enpstools.css, where teal fails so the
callout is navy). Drop brand .ttf files into fonts/ and wire @font-face as
shown in the template.
What makes these good (encoded in base.css)
- One loud element.
.callout-keyis the highest-contrast block; everything else is calm. White background, no full-bleed color, no gradients/shadows — it must read as a tool, not a flyer. - Brand via presets, never hardcoded. Every color/font is a CSS variable in
styles/brand-*.css;base.cssconsumes them. - Contrast enforced by variable split (
--accentvs--accent-deep,--callout-bg/--on-callout) — see "Make it your brand". - No em dashes in copy. They read as an AI tell; write them out (period/comma/colon). The templates are already clean.
- Dual page size from one template.
base.csssets margins but not size;gen.pyinjects@page { size: letter | A4 }per build.
Gotchas
- Use the venv's python, every time. System
python3lacks WeasyPrint;./.venv/bin/pythonhas it. The #1 "module not found" cause. - Native libs are a real dependency. If
import weasyprintfails, you are missing the OS packages — re-run./setup.shand follow its install line. On macOS Homebrew,DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/libresolves rare dylib-lookup failures. - Fonts are bundled (OFL) in
fonts/and embedded+subsetted into the PDF, so output is identical on every machine. To use your own brand font, add the.ttfand wire@font-facein your brand CSS. Variable fonts work — declarefont-weight: 100 900on the@font-face(seebrand-feedbackpulse.css). pdf/ua-1needs a<title>and<html lang>. Both are in the templates; deleting them degrades the tagged-PDF output.- Keep it under 600 KB.
optimize_images=Trueis on; don't embed large rasters. The asset should be email-attachable and fast to crawl. - Put the key points as text on the download page too, so AI has the "answer key" without parsing the PDF.
References
- Example brand presets:
styles/brand-feedbackpulse.css(Product Bridge Blue) andstyles/brand-enpstools.css(navy/teal, the clearest contrast demo). - Sample output: regenerate any time with
gen.pyintoout/. - Bundled fonts:
fonts/with the OFL license text for each family. - Deeper PDF/UA validation (optional): run the file through veraPDF for a
formal accessibility conformance claim;
verify.pychecks the structural markers (tags, metadata, selectable text), not full PDF/UA conformance.
What ships with it: 19 files
392.8 KB alongside SKILL.md, 3 of them executable
fonts/
- AtkinsonHyperlegible-Bold.ttf54.0 KB
- AtkinsonHyperlegible-Regular.ttf53.1 KB
- Figtree-Variable.ttf61.2 KB
- OFL-AtkinsonHyperlegible.txt4.3 KB
- OFL-Figtree.txt4.3 KB
- OFL-PlusJakartaSans.txt4.3 KB
- PlusJakartaSans-Variable.ttf172.2 KB
styles/
- base.css6.0 KB
- brand-default.css1.8 KB
- brand-enpstools.css2.3 KB
- brand-feedbackpulse.css1.9 KB
- brand-template.css2.9 KB
templates/
- example-sbi.html8.4 KB
- starter.html5.7 KB
- gen.pyruns4.7 KB
- .gitignore46 B
- requirements.txt176 B
- setup.shruns2.5 KB
- verify.pyruns3.3 KB
Gives 0 of the 12 instructions most pdf office docs skills give in ~2.1k tokens
Counted across 569 of the 585 authors here whose files we hold, read 2026-09-06
- Ensure every slide fits inside one viewportin 20 of 569, across 11 files
- Check for product marketing context firstin 15 of 569, across 5 files
- Ask for the minimum neededin 15 of 569, across 5 files
- Set the API key environment variablein 15 of 569, across 10 files
- Support keyboard and touch navigationin 14 of 569, across 5 files
- Match the buyer stagein 13 of 569, across 3 files
- Split overflowing content into multiple slidesin 12 of 569, across 3 files
- Set page size explicitly for consistent resultsin 12 of 569, across 5 files
- Convert documents to markdown using pandocin 12 of 569, across 6 files
- Read STYLE_PRESETS.md before generatingin 12 of 569, across 7 files
- Send multipart POST requests to the APIin 12 of 569, across 7 files
- Use smart quotes for new contentin 11 of 569, across 4 files
Said here and by no other author read
- Copy the starter template and replace placeholders
- Set the metadata in head
- Set the running-footer URL
- Use the components in styles/base.css
- Test the PDF with ChatGPT and Claude
- Ship to a stable URL
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.