
Pdf Generation
- 437 installs
- 339 repo stars
- Updated August 4, 2026
- glebis/claude-skills
pdf-generation is a Claude Code skill that generates polished PDF reports, invoices, and export packs from markdown, HTML, or structured data for developers automating customer-facing document output during feature work.
About
pdf-generation is a document automation skill from glebis/claude-skills that produces polished PDF reports, invoices, and export packs from markdown, HTML, or structured JSON and CSV data. The skill guides layout, typography, headers, tables, and pagination choices so generated PDFs are suitable for customer delivery rather than raw print-to-PDF dumps. Developers reach for pdf-generation when building SaaS billing exports, monthly analytics reports, compliance document packs, or automated invoice attachments in API backends. Output includes PDF files plus the generating script or template using common Node.js, Python, or headless browser tooling patterns that can be integrated into CI or on-demand API endpoints.
- Markdown or HTML to PDF pipelines
- Page layout, margins, and header/footer control
- Table and image embedding in exports
- Batch document generation from templates
- Suitable for invoices, reports, and handoffs
Pdf Generation by the numbers
- 437 all-time installs (skills.sh)
- Ranked #162 of 688 Office & Documents skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/glebis/claude-skills --skill pdf-generationAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 437 |
|---|---|
| repo stars | ★ 339 |
| Last updated | August 4, 2026 |
| Repository | glebis/claude-skills ↗ |
How do you generate PDF reports from markdown?
Generate polished PDF reports, invoices, and export packs from markdown, HTML, or structured data during feature work and customer-facing document automation.
Who is it for?
Full-stack developers automating invoices, analytics reports, or compliance export packs in SaaS APIs.
Skip if: Interactive PDF form filling, digital signatures, or complex print-layout design in InDesign.
When should I use this skill?
User asks to generate PDF reports, invoices, export packs, or convert markdown or HTML to PDF programmatically.
What you get
Polished PDF files with layout templates and generating script or API integration
Files
PDF Generation
Overview
Generate professional PDFs from markdown files using Pandoc with Eisvogel template styling. Supports English and Russian documents with customizable themes, table of contents, and professional typography including EB Garamond font for Russian text.
Quick Start
Basic commands:
# Desktop/Print PDF (A4 format)
pandoc doc.md -o doc.pdf --pdf-engine=xelatex --toc --toc-depth=2 -V geometry:margin=2.5cm -V fontsize=11pt -V documentclass=article
# Mobile-friendly PDF (6x9 phone screen optimized)
pandoc doc.md -o doc-mobile.pdf --pdf-engine=xelatex --toc --toc-depth=2 -V geometry:paperwidth=6in -V geometry:paperheight=9in -V geometry:margin=0.5in -V fontsize=10pt -V linestretch=1.2
# Russian PDF with EB Garamond
pandoc doc-ru.md -o doc.pdf --pdf-engine=xelatex --toc --toc-depth=2 -V geometry:margin=2.5cm -V fontsize=11pt -V documentclass=article -V mainfont="EB Garamond"
# Russian Mobile PDF
pandoc doc-ru.md -o doc-mobile.pdf --pdf-engine=xelatex --toc --toc-depth=2 -V geometry:paperwidth=6in -V geometry:paperheight=9in -V geometry:margin=0.5in -V fontsize=10pt -V linestretch=1.2 -V mainfont="EB Garamond"Document Theme Colors
- White Papers - Blue (1e3a8a)
- Marketing - Green (059669)
- Research - Purple (7c3aed)
- Technical - Gray (374151)
YAML Frontmatter Example
---
title: "Document Title"
subtitle: "Subtitle"
author: "Author"
date: "2025-11-18"
titlepage: true
titlepage-color: "1e3a8a"
titlepage-text-color: "ffffff"
book: true
---See references/frontmatter_templates.md for complete templates.
Markdown Formatting Best Practices
For optimal PDF rendering, ensure:
1. Blank lines before lists - Required for proper list rendering 2. Blank lines after headings - Improves spacing 3. Nested list indentation - Use 3 spaces for sub-items
Common Claude Code Pattern
Lists after colons need blank lines:
Your data spans 9 years with complete tracking:
- Item 1
- Item 2Without blank line after colon, renders as inline text.
Automatic Fix
Use preprocessing script:
scripts/fix_markdown.py input.md output.mdAutomatically detects and fixes:
- Lists after colons (Claude Code format)
- Lists after headings
- Nested list spacing
Layout Options
Desktop/Print Layout (A4)
- Paper: 210mm x 297mm (A4)
- Margins: 2.5cm
- Font size: 11pt
- Best for: Printing, reading on large screens, archival
Mobile Layout (Phone-optimized)
- Paper: 6in x 9in (phone aspect ratio)
- Margins: 0.5in (minimal for screen space)
- Font size: 10pt with 1.2 line spacing
- Best for: Phone/tablet reading, Telegram/messaging apps
Default for Telegram Bot: Use mobile layout for all PDFs sent via Telegram unless user explicitly requests print/desktop version.
Generation Workflows
Workflow 1: Simple PDF
1. Check context (Telegram = mobile, otherwise desktop) 2. Check if Russian (use EB Garamond if yes) 3. Run appropriate pandoc command 4. Verify output
Workflow 2: Professional Title Page
1. Add YAML frontmatter with theme color 2. Include metadata (title, author, date) 3. Choose layout (mobile vs desktop) 4. Generate with xelatex
Workflow 3: Using Script
scripts/generate_pdf.py doc.md -t white-paper
scripts/generate_pdf.py doc.md -t marketing --russian
scripts/generate_pdf.py doc.md --mobile # Mobile layoutResources
- scripts/generate_pdf.py - Automated generation
- references/frontmatter_templates.md - YAML templates
- references/pandoc_reference.md - Command reference
Troubleshooting
Install pandoc: brew install pandoc Install LaTeX: brew install --cask mactex
Mobile-Friendly PDFs
For phone and tablet reading, use the mobile layout option:
# Using script (recommended)
scripts/generate_pdf.py doc.md --mobile
# Direct pandoc command
pandoc doc.md -o doc-mobile.pdf \
--pdf-engine=xelatex \
--toc --toc-depth=2 \
-V geometry:paperwidth=6in \
-V geometry:paperheight=9in \
-V geometry:margin=0.5in \
-V fontsize=10pt \
-V linestretch=1.2 \
-V colorlinks=true \
-V linkcolor=blue \
-V urlcolor=blueMobile layout features:
- 6x9 inch page size (optimal for mobile screens)
- 10pt font (readable on smaller screens)
- 0.5in margins (maximizes content area)
- 1.2 line spacing (improved readability)
- Auto-generated
-mobile.pdffilename suffix
When to use mobile layout:
- Sharing research via Telegram/messaging apps
- Reading on phones or tablets
- Creating portable reference documents
- Quick consumption on the go
Default context: Mobile layout is used by default when generating PDFs through the Telegram bot for optimal mobile reading experience.
{
"name": "pdf-generation",
"description": "Professional PDF generation from markdown using Pandoc with Eisvogel template and EB Garamond fonts. Use when converting",
"author": {
"name": "Gleb Kalinin"
},
"repository": "https://github.com/glebis/claude-skills",
"license": "MIT"
}PDF Generation Skill
Professional PDF generation from markdown using Pandoc with Eisvogel template and EB Garamond fonts.
Overview
This skill enables Claude to generate professional PDFs from markdown files with:
- Professional title pages with color-coded themes
- English and Russian language support with proper typography
- Automatic table of contents generation
- Theme-based styling for different document types
- Markdown preprocessing to fix common formatting issues
Installation
1. Download pdf-generation.zip 2. Extract to ~/.claude/skills/pdf-generation/ 3. Ensure dependencies installed:
# macOS
brew install pandoc
brew install --cask mactex
# Verify installation
pandoc --version
xelatex --versionQuick Start
Basic Usage
# Simple English PDF
pandoc document.md -o document.pdf --pdf-engine=xelatex --toc --toc-depth=2 \
-V geometry:margin=2.5cm -V fontsize=11pt -V documentclass=article
# Russian PDF with EB Garamond
pandoc document-ru.md -o document.pdf --pdf-engine=xelatex --toc --toc-depth=2 \
-V geometry:margin=2.5cm -V fontsize=11pt -V documentclass=article \
-V mainfont="EB Garamond"Using the Generation Script
# White paper (blue theme)
scripts/generate_pdf.py report.md -t white-paper
# Marketing material (green theme)
scripts/generate_pdf.py marketing.md -t marketing
# Russian research paper (purple theme)
scripts/generate_pdf.py research-ru.md -t research --russian
# Custom output path
scripts/generate_pdf.py input.md -o custom/path/output.pdfDocument Themes
Different document types use specific color schemes:
| Theme | Color | Use Case |
|---|---|---|
white-paper | Blue (1e3a8a) | White papers, reports |
marketing | Green (059669) | Marketing materials |
research | Purple (7c3aed) | Research papers, analysis |
technical | Gray (374151) | Technical documentation |
YAML Frontmatter
Add frontmatter to markdown files for professional title pages:
---
title: "Document Title"
subtitle: "Document Subtitle"
author: "Author Name"
date: "2025-11-18"
titlepage: true
titlepage-color: "1e3a8a"
titlepage-text-color: "ffffff"
titlepage-rule-color: "ffffff"
titlepage-rule-height: 2
book: true
classoption: oneside
toc: true
toc-depth: 2
---See references/frontmatter_templates.md for complete examples.
Markdown Formatting
For proper list rendering, ensure blank lines before lists:
### Section Title
This is a paragraph.
- List item 1
- List item 2
1. Numbered item 1
- Nested item (3 spaces indent)
- Nested itemFix formatting automatically:
scripts/fix_markdown.py input.md output.mdSkill Structure
pdf-generation/
├── SKILL.md # Main skill definition
├── README.md # This file
├── scripts/
│ ├── generate_pdf.py # Automated PDF generation
│ └── fix_markdown.py # Markdown preprocessing
└── references/
├── frontmatter_templates.md # YAML frontmatter examples
└── pandoc_reference.md # Pandoc command referenceScript Options
generate_pdf.py
Options:
-t, --theme Document theme (white-paper, marketing, research, technical)
-r, --russian Enable EB Garamond font for Russian text
-o, --output Custom output path
--no-toc Disable table of contents
--toc-depth TOC depth (default: 2)
--margin Page margin (default: 2.5cm)
--fontsize Font size (default: 11pt)fix_markdown.py
Usage: fix_markdown.py <input.md> [output.md]
Fixes:
- Adds blank lines before lists
- Handles lists after colons (Claude Code format)
- Handles nested list formatting
- Ensures proper spacing after headings
Example - Claude Code pattern:
"text with colon:"
"- list item" → Auto-adds blank lineTroubleshooting
Pandoc not found
brew install pandoc # macOS
sudo apt-get install pandoc # LinuxXeLaTeX not found
brew install --cask mactex # macOS
sudo apt-get install texlive-xetex # LinuxLists rendering as inline text
Run markdown preprocessor:
scripts/fix_markdown.py input.md fixed.md
pandoc fixed.md -o output.pdf --pdf-engine=xelatexRussian text not rendering
Ensure EB Garamond font installed and specify:
pandoc input.md -o output.pdf -V mainfont="EB Garamond"Unicode characters missing (▬, ✓)
These are warnings, not errors. Content renders correctly. To eliminate warnings, use standard ASCII alternatives in source markdown.
Examples
Example 1: White Paper
---
title: "Product Strategy 2025"
subtitle: "Market Analysis and Roadmap"
author: "Strategy Team"
date: "November 2025"
titlepage: true
titlepage-color: "1e3a8a"
titlepage-text-color: "ffffff"
book: true
toc: true
---
# Executive Summary
Key findings from market analysis...scripts/generate_pdf.py strategy.md -t white-paperExample 2: Russian Research Paper
---
title: "Анализ данных здоровья"
subtitle: "Кардиоваскулярные метрики"
author: "Исследовательская группа"
date: "Ноябрь 2025"
titlepage: true
titlepage-color: "7c3aed"
titlepage-text-color: "ffffff"
book: true
toc: true
---
# Введение
Анализ показателей здоровья...scripts/generate_pdf.py research-ru.md -t research --russianDependencies
- Pandoc (>=2.0) - Document converter
- XeLaTeX (TeX Live) - PDF engine
- Python 3 (>=3.6) - For scripts
- EB Garamond font (optional) - For Russian documents
License
MIT
Contributing
Issues and improvements welcome at your GitHub repository.
Version
1.0.0 - Initial release with Eisvogel styling, Russian support, and markdown preprocessing
YAML Frontmatter Templates
English White Paper
--- title: "Document Title" subtitle: "Subtitle" author: "Author" date: "2025-11-18" titlepage: true titlepage-color: "1e3a8a" titlepage-text-color: "ffffff" book: true ---
Theme Colors
- White Papers: 1e3a8a (Blue)
- Marketing: 059669 (Green)
- Research: 7c3aed (Purple)
- Technical: 374151 (Gray)
Pandoc Commands Reference
Basic PDF Generation
pandoc input.md -o output.pdf --pdf-engine=xelatex
With Table of Contents
pandoc input.md -o output.pdf --pdf-engine=xelatex --toc --toc-depth=2
Russian Documents (EB Garamond)
pandoc input-ru.md -o output.pdf --pdf-engine=xelatex -V mainfont="EB Garamond"
Full Command Template
pandoc input.md -o output.pdf \ --pdf-engine=xelatex \ --toc \ --toc-depth=2 \ -V geometry:margin=2.5cm \ -V fontsize=11pt \ -V documentclass=article
#!/usr/bin/env python3
"""
Fix common markdown formatting issues for better PDF rendering.
Handles Claude Code generated markdown including lists after colons.
"""
import re
import sys
from pathlib import Path
def fix_markdown_lists(content):
"""
Add blank lines before lists that don't have them.
Handles multiple patterns:
1. Lists after text with colon (Claude Code pattern)
2. Lists after headings
3. Nested lists
"""
lines = content.split('\n')
fixed_lines = []
for i, line in enumerate(lines):
# Check if this is a list item (numbered or bullet)
is_list = re.match(r'^(\s*)([-*+]|\d+\.)\s', line)
if is_list:
indent = len(is_list.group(1))
prev_line = lines[i-1] if i > 0 else ''
# Check if previous line exists and is not blank
if prev_line.strip():
prev_is_list = re.match(r'^(\s*)([-*+]|\d+\.)\s', prev_line)
# Pattern 1: Previous line ends with colon (Claude Code format)
# "text with colon:"
# "- list item"
if prev_line.rstrip().endswith(':') and indent == 0:
fixed_lines.append('')
# Pattern 2: Not a list item and not indented
elif not prev_is_list and indent == 0:
# Check if we already added a blank line
if not (i > 0 and not lines[i-1].strip()):
fixed_lines.append('')
fixed_lines.append(line)
return '\n'.join(fixed_lines)
def main():
if len(sys.argv) < 2:
print("Usage: fix_markdown.py <input.md> [output.md]", file=sys.stderr)
print("\nFixes common markdown formatting issues:")
print(" - Adds blank lines before lists")
print(" - Handles lists after colons (Claude Code format)")
print(" - Fixes nested list spacing")
sys.exit(1)
input_file = Path(sys.argv[1])
output_file = Path(sys.argv[2]) if len(sys.argv) > 2 else input_file
if not input_file.exists():
print(f"Error: {input_file} not found", file=sys.stderr)
sys.exit(1)
content = input_file.read_text()
fixed_content = fix_markdown_lists(content)
output_file.write_text(fixed_content)
print(f"✓ Fixed markdown formatting: {output_file}")
if __name__ == '__main__':
main()
#!/usr/bin/env python3
"""
Professional PDF generation script using Pandoc with Eisvogel template.
Supports both English and Russian documents with proper typography.
Includes mobile-friendly layout option for phone/tablet reading.
"""
import argparse
import subprocess
import sys
from pathlib import Path
# Color themes for different document types
THEMES = {
'white-paper': '1e3a8a', # Blue
'marketing': '059669', # Green
'research': '7c3aed', # Purple
'technical': '374151', # Gray
}
def generate_pdf(
input_file: str,
output_file: str = None,
theme: str = 'white-paper',
russian: bool = False,
toc: bool = True,
toc_depth: int = 2,
margin: str = '2.5cm',
fontsize: str = '11pt',
mobile: bool = False
):
"""
Generate PDF from markdown using Pandoc.
Args:
input_file: Path to input markdown file
output_file: Path to output PDF file (auto-generated if not provided)
theme: Document theme (white-paper, marketing, research, technical)
russian: Use EB Garamond font for Russian text
toc: Include table of contents
toc_depth: Depth of table of contents
margin: Page margin size
fontsize: Base font size
mobile: Generate mobile-optimized PDF (6x9in, smaller margins, 10pt font)
"""
input_path = Path(input_file)
if not input_path.exists():
print(f"Error: Input file '{input_file}' not found", file=sys.stderr)
sys.exit(1)
# Auto-generate output filename if not provided
if output_file is None:
if mobile:
output_file = input_path.stem + '-mobile.pdf'
else:
output_file = str(input_path.with_suffix('.pdf'))
# Override settings for mobile layout
if mobile:
margin = '0.5in'
fontsize = '10pt'
# Build pandoc command
cmd = [
'pandoc',
str(input_file),
'-o', str(output_file),
'--pdf-engine=xelatex',
'-V', f'geometry:margin={margin}',
'-V', f'fontsize={fontsize}',
'-V', 'documentclass=article',
'-V', 'colorlinks=true',
'-V', 'linkcolor=blue',
'-V', 'urlcolor=blue',
]
# Add mobile-specific geometry
if mobile:
cmd.extend([
'-V', 'geometry:paperwidth=6in',
'-V', 'geometry:paperheight=9in',
'-V', 'linestretch=1.2'
])
# Add table of contents
if toc:
cmd.extend(['--toc', f'--toc-depth={toc_depth}'])
# Add Russian font support
if russian:
cmd.extend(['-V', 'mainfont=EB Garamond'])
# Execute pandoc
try:
layout_type = "Mobile (6x9in)" if mobile else "Desktop (Letter)"
print(f"Generating PDF: {output_file}")
print(f"Layout: {layout_type}")
print(f"Theme: {theme} ({THEMES.get(theme, 'custom')})")
print(f"Russian font: {'Yes (EB Garamond)' if russian else 'No'}")
result = subprocess.run(cmd, check=True, capture_output=True, text=True)
print(f"✅ Success: PDF generated at {output_file}")
return 0
except subprocess.CalledProcessError as e:
print(f"❌ Error generating PDF:", file=sys.stderr)
print(e.stderr, file=sys.stderr)
return 1
except FileNotFoundError:
print("Error: pandoc not found. Install with: brew install pandoc", file=sys.stderr)
return 1
def main():
parser = argparse.ArgumentParser(
description='Generate professional PDFs from markdown'
)
parser.add_argument('input', help='Input markdown file')
parser.add_argument('-o', '--output', help='Output PDF file')
parser.add_argument(
'-t', '--theme',
choices=list(THEMES.keys()),
default='white-paper',
help='Document theme'
)
parser.add_argument('-r', '--russian', action='store_true', help='Use EB Garamond for Russian')
parser.add_argument('-m', '--mobile', action='store_true', help='Generate mobile-friendly layout (6x9in, 10pt)')
parser.add_argument('--no-toc', action='store_true', help='Disable table of contents')
parser.add_argument('--toc-depth', type=int, default=2, help='TOC depth (default: 2)')
parser.add_argument('--margin', default='2.5cm', help='Page margin (overridden by --mobile)')
parser.add_argument('--fontsize', default='11pt', help='Font size (overridden by --mobile)')
args = parser.parse_args()
return generate_pdf(
input_file=args.input,
output_file=args.output,
theme=args.theme,
russian=args.russian,
toc=not args.no_toc,
toc_depth=args.toc_depth,
margin=args.margin,
fontsize=args.fontsize,
mobile=args.mobile
)
if __name__ == '__main__':
sys.exit(main())
Related skills
How it compares
Pick pdf-generation for programmatic report and invoice PDFs; use design tools when pixel-perfect marketing collateral layout is the primary goal.
FAQ
What inputs does pdf-generation accept?
pdf-generation accepts markdown, HTML, and structured data such as JSON or CSV to produce polished PDF reports, invoices, and export packs. Output includes the PDF file and integration code for API or batch workflows.
When should developers use pdf-generation?
pdf-generation fits SaaS billing invoices, monthly analytics exports, and compliance document packs that must render consistently for customers. Skip it for interactive PDF forms or digital signature workflows.