Comprehensive PDF creation, editing, manipulation, and analysis skill focused on producing professional, beautifully designed PDF documents. Use when: (1) creating new PDF reports, proposals, letters, certificates, or any styled document, (2) merging or splitting PDFs, (3) adding watermarks, headers, or footers, (4) converting HTML/markdown to PDF, (5) filling PDF forms, (6) extracting text or tables from PDFs, (7) any task involving .pdf files. This skill should be used whenever the user mentions PDF, wants to generate a printable document, needs a polished report output, or wants to convert content to PDF format — even if they don't explicitly say "PDF." If the output should look like a professional printed document, use this skill.
Create professional, beautifully designed PDF documents using an HTML+CSS-to-PDF workflow. This approach gives you full control over typography, layout, colors, and page structure using familiar web technologies — producing results that rival professional typesetting.
The primary engine is WeasyPrint (HTML/CSS to PDF), which supports CSS Paged Media for headers, footers, page numbers, margins, and multi-column layouts. For programmatic needs, reportlab is available. For manipulation (merge, split, rotate), use pypdf.
Use the "HTML-to-PDF" workflow below — this is the primary and recommended approach. It produces the highest quality output with the most design control.
Use pdfplumber for text and table extraction.
Use pypdf — see "PDF Manipulation" section.
Use pypdf — see "Form Filling" section.
soffice --headless --convert-to pdf document.docxThis is the recommended approach for creating professional PDFs. You write styled HTML, then WeasyPrint converts it to a pixel-perfect PDF with proper page breaks, headers, footers, and print-quality typography.
CSS gives you precise control over everything that matters in a professional document: page size, margins, fonts, colors, tables, headers/footers, page numbers, columns, and decorative elements. WeasyPrint faithfully renders CSS Paged Media, which was designed specifically for print layout.
Write a single HTML file with <style> containing your CSS. Structure the document
with semantic HTML (<header>, <section>, <table>, <footer>, etc.).
Critical CSS patterns for PDF:
@page {
size: letter; /* or A4, legal, letter landscape */
margin: 1in 0.75in; /* top/bottom left/right */
@top-center {
content: "Document Title";
font-family: 'Inter', sans-serif;
font-size: 8pt;
color: #666;
}
@bottom-right {
content: "Page " counter(page) " of " counter(pages);
font-family: 'Inter', sans-serif;
font-size: 8pt;
color: #666;
}
}
/* First page often has different margins/no header */
@page :first {
margin-top: 0;
@top-center { content: none; }
}
body {
font-family: 'Inter', sans-serif;
font-size: 10pt;
line-height: 1.4;
color: #1a1a1a;
}
Every PDF must include these table rules. Without them, tables overflow the page and columns get cut off.
/* MANDATORY — prevents table overflow */
table {
width: 100%;
max-width: 100%;
table-layout: fixed; /* NEVER use 'auto' — causes page overflow */
border-collapse: collapse;
word-wrap: break-word;
overflow-wrap: break-word;
overflow: hidden;
font-size: 9pt;
}
td, th {
overflow: hidden;
word-wrap: break-word;
overflow-wrap: break-word;
padding: 4px 6px;
}
Never use table-layout: auto — it lets cell content push columns beyond the printable area. With fixed, columns share width equally and content wraps.
Never use ASCII art or monospace code-block flowcharts in PDFs. They look unprofessional.
Render all diagrams as images:
.mmd file)npx -y @mermaid-js/mermaid-cli mmdc -i diagram.mmd -o diagram.png -t neutral -b transparent -w 1200<img> in the HTMLIf Mermaid CLI is unavailable, use styled HTML/CSS divs or the /designer skill.
Control page flow precisely:
/* Force page break before element */
.page-break { page-break-before: always; }
/* Prevent break inside element */
table, figure { page-break-inside: avoid; }
/* Keep heading with next content */
h1, h2, h3 { page-break-after: avoid; }
cd "${GEMINI_SKILL_DIR}"
source venv/bin/activate
python scripts/create_pdf.py input.html output.pdf
Or use WeasyPrint directly in a Python script:
from weasyprint import HTML
HTML('document.html').write_pdf('output.pdf')
WeasyPrint can use system fonts or fonts loaded via CSS @font-face. For Google Fonts
or custom fonts, download the font files and reference them:
@font-face {
font-family: 'Inter';
src: url('path/to/Inter-Regular.woff2') format('woff2');
font-weight: 400;
}
@font-face {
font-family: 'Inter';
src: url('path/to/Inter-Bold.woff2') format('woff2');
font-weight: 700;
}
If Inter is installed on the system, just use font-family: 'Inter', sans-serif;.
Professional PDFs need intentional design. Before writing code, consider:
Good typography makes documents look professional without effort:
Restraint is key. A professional palette uses 2-3 colors:
See references/design-guide.md for color palettes and layout templates.
<!DOCTYPE html>
<html>
<head>
<style>
@page {
size: letter;
margin: 1in 0.75in 1in 0.75in;
@bottom-center {
content: counter(page);
font-family: 'Inter', sans-serif;
font-size: 8pt;
color: #888;
}
}
@page :first {
@bottom-center { content: none; }
}
body {
font-family: 'Inter', sans-serif;
font-size: 10pt;
line-height: 1.5;
color: #1a1a1a;
}
.cover {
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
padding: 2in 0;
}
.cover h1 {
font-size: 28pt;
font-weight: 700;
color: #0f4c81;
margin-bottom: 0.5em;
border-bottom: 3pt solid #0f4c81;
padding-bottom: 0.5em;
}
.cover .subtitle {
font-size: 14pt;
color: #555;
margin-top: 0.5em;
}
.cover .meta {
margin-top: 2em;
font-size: 10pt;
color: #666;
}
h2 {
font-size: 16pt;
color: #0f4c81;
border-bottom: 1pt solid #ddd;
padding-bottom: 4pt;
margin-top: 1.5em;
}
h3 {
font-size: 12pt;
color: #333;
margin-top: 1.2em;
}
table {
width: 100%;
border-collapse: collapse;
margin: 1em 0;
font-size: 9pt;
page-break-inside: avoid;
}
th {
background: #0f4c81;
color: white;
padding: 8pt 10pt;
text-align: left;
font-weight: 600;
}
td {
padding: 6pt 10pt;
border-bottom: 0.5pt solid #ddd;
}