plugins/technical-writer/skills/pdf-generation/SKILL.md
This skill should be used when the user asks to "generate a PDF from markdown", "create a printable book", "convert documentation to PDF", or "export chapters as a PDF". Automatically activates when producing a PDF from a directory of ordered markdown chapters using pandoc and weasyprint. Not for single-file markdown-to-PDF conversion or non-documentation use cases.
npx skillsauth add sjungling/sjungling-claude-plugins pdf-generationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Converts a directory of ordered markdown chapters into a single, styled PDF book with table of contents, page numbers, and resolved inter-chapter links.
Core principle: The markdown files are the source of truth. The PDF is a derived artifact -- never edit the PDF directly.
Automatically activates when:
technical-overview or similar multi-chapter doc set is ready for exportThree tools must be installed before generation can proceed:
| Tool | Install command | Purpose |
|------|----------------|---------|
| pandoc | brew install pandoc | Markdown to HTML conversion |
| weasyprint | uv tool install weasyprint | HTML to PDF rendering |
| pango | brew install pango | Text layout (weasyprint dependency) |
Before running the script, verify availability:
command -v pandoc >/dev/null 2>&1 || echo "Missing: pandoc (brew install pandoc)"
command -v weasyprint >/dev/null 2>&1 || echo "Missing: weasyprint (uv tool install weasyprint)"
If either tool is missing, install it and retry. The script itself checks for dependencies and exits with a clear error message.
The generation pipeline has four stages:
README.md first, then 00-*.md through 99-*.md, then appendix-*.md.md links (e.g., [architecture](01-architecture.md)) are rewritten to internal #anchor links so they work within the single documentRun the generation script using $CLAUDE_PLUGIN_ROOT:
${CLAUDE_PLUGIN_ROOT}/skills/pdf-generation/scripts/generate-pdf.sh <input-dir> [output.pdf]
input-dir -- Directory containing the ordered markdown chaptersoutput.pdf -- Optional output path (defaults to <input-dir>/technical-overview.pdf)If $CLAUDE_PLUGIN_ROOT is not set (e.g., running outside a plugin context), locate the script manually:
# Fallback: find the script in the plugin installation directory
SCRIPT_PATH=$(find ~/.claude/plugins -path "*/pdf-generation/scripts/generate-pdf.sh" 2>/dev/null | head -1)
if [ -z "$SCRIPT_PATH" ]; then
echo "Error: generate-pdf.sh not found. Ensure the technical-writer plugin is installed."
exit 1
fi
"$SCRIPT_PATH" <input-dir> [output.pdf]
The input directory must contain ordered markdown files following this naming convention:
docs/technical-overview/
├── README.md # Title page and introduction (always first)
├── 00-getting-started.md # Numbered chapters in sequence
├── 01-architecture.md
├── 02-data-model.md
├── 03-api-reference.md
├── 04-deployment.md
├── appendix-a-glossary.md # Appendices after numbered chapters
└── appendix-b-faq.md
Expected output:
docs/technical-overview/
├── ... (source files unchanged)
└── technical-overview.pdf # Generated PDF (default output location)
The PDF includes:
# heading in README.md (or the directory name as fallback)For the PDF to have working internal links, the source markdown must follow these rules:
[architecture overview](01-architecture.md)[the store layer](03-data-layer.md#store)# heading -- this is used to resolve link targets.md links it cannot resolveCommon linking mistakes:
| Mistake | Fix |
|---------|-----|
| Absolute paths (/docs/01-arch.md) | Use relative paths (01-arch.md) |
| Missing # heading in chapter | Add exactly one h1 heading per chapter |
| Link to file not in input directory | Ensure all linked files are in the same directory |
The script embeds a print-optimized CSS stylesheet with sensible defaults:
For detailed CSS customization options (fonts, colors, page sizes, themes), see ./references/css-customization.md.
| Symptom | Cause | Fix |
|---------|-------|-----|
| "Error: 'pandoc' is not installed" | Missing dependency | brew install pandoc |
| "Error: 'weasyprint' is not installed" | Missing dependency | uv tool install weasyprint && brew install pango |
| Warning about unresolved .md links | Chapter heading does not match filename pattern | Ensure each chapter has a # heading and the link target filename is correct |
| PDF renders but fonts look wrong | Missing system fonts | weasyprint uses system fonts; install desired fonts via Font Book |
| Empty PDF or no chapters found | Files not matching naming convention | Verify files follow README.md, 00-*.md through 99-*.md, appendix-*.md pattern |
| CLAUDE_PLUGIN_ROOT is empty | Running outside plugin context | Use the fallback script discovery method described above |
| Long code blocks overflow margins | Default CSS handles this | Verify overflow-wrap: break-word and white-space: pre-wrap in CSS |
./references/css-customization.md -- Detailed CSS customization options for fonts, page sizes, colors, and themes./scripts/generate-pdf.sh -- The generation script (inspect for advanced modification)testing
This skill should be used when the user asks to "start a service in tmux", "check tmux pane output", "manage background processes", or "run a server in a pane". Automatically activates when running in a TMUX session (detected by SessionStart hook). Not for one-off commands that do not need a persistent pane.
development
This skill should be used when the user asks to "write a README", "create API documentation", "draft release notes", "write a tutorial", "structure documentation", or "review docs for clarity". Automatically activates when working with .md files in docs/ directories, README files, or when discussing documentation structure, style guides, or content organization. Not for creative/marketing writing, academic papers, code comments/docstrings, or internal chat.
documentation
This skill should be used when the user asks to "manage Obsidian vault", "create a daily note", "move notes without breaking links", "search vault content", or "organize Obsidian notes". Automatically activates when working with Obsidian vaults, markdown notes with [[wiki-links]], daily notes, templates, or tags. Not for general markdown editing outside Obsidian vaults.
development
This skill should be used when the user asks to "build an iOS app", "create a SwiftUI view", "fix Xcode build errors", "implement Core Data", "design app architecture", or "optimize Swift performance". Automatically activates when working with .swift files, Xcode projects (.xcodeproj, .xcworkspace), SwiftUI interfaces, or Apple platform frameworks (UIKit, Core Data, Combine, WidgetKit, App Intents). Not for cross-platform frameworks (React Native, Flutter), non-Apple platforms, or backend server development.