Skip to content
Code Guide

PDF Generation with Claude Code

Confidence: Tier 2 — Based on production-tested workflow with Quarto/Typst stack.

Generate professional PDFs (documentation, whitepapers, reports) using Claude Code with modern typography and design.


  1. TL;DR
  2. When to Use
  3. Stack Overview
  4. Setup
  5. Workflow
  6. Integration with Claude Code
  7. Customization
  8. Troubleshooting
  9. See Also

Terminal window
# Install
brew install quarto # macOS
# Generate
quarto render document.qmd # → document.pdf
# Preview
quarto preview document.qmd # Hot-reload

Stack: Quarto (orchestration) + Typst (typography) + Pandoc (markdown)


Use CaseGood FitAlternative
Technical documentation
Whitepapers / Reports
API documentation⚠️OpenAPI + Redoc
Slides / Presentations⚠️Quarto Revealjs
Quick notesPlain Markdown
Collaborative editingGoogle Docs, Notion

Best for: Long-form technical content requiring professional layout, version control, and reproducibility.


┌─────────────────────────────────────────────────┐
│ Your .qmd File │
│ (Markdown + YAML frontmatter) │
└─────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────┐
│ Quarto │
│ (Document rendering engine) │
│ • Processes YAML metadata │
│ • Handles extensions │
│ • Manages output formats │
└─────────────────────────────────────────────────┘
┌─────────────┴─────────────┐
▼ ▼
┌─────────────────────┐ ┌─────────────────────┐
│ Pandoc │ │ Typst │
│ (MD → AST → ?) │ │ (Typography/PDF) │
│ • Markdown parser │ │ • Modern engine │
│ • AST transforms │ │ • Fast compilation │
│ • Format bridges │ │ • No LaTeX needed │
└─────────────────────┘ └─────────────────────┘
┌─────────────────────────────────────────────────┐
│ document.pdf │
│ (Professional typography output) │
└─────────────────────────────────────────────────┘
FORMAT COMMANDE SORTIE
────── ──────── ──────
PDF standard → quarto render doc.qmd doc.pdf
--to typst (sans template custom)
PDF stylé ✅ → quarto render doc.qmd doc.pdf
--to whitepaper-typst (~270K–1.7M, Bold Guy)
(format custom via _extensions/)
EPUB → quarto render doc.qmd doc.epub
--to epub
Preview → quarto preview doc.qmd hot-reload navigateur
_extensions/
└── whitepaper/
├── _extension.yml ← déclare le format "whitepaper-typst"
├── typst-template.typ ← design system (couleurs, typo, callouts)
└── typst-show.typ ← bridge Quarto → Typst
⚠️ Si tu maintiens des copies dans fr/ en/ et racine :
garder les 3 fichiers typst-template.typ synchronisés
SYMPTÔME CAUSE FIX
──────── ───── ───
PDF petit (~80-190K), non stylé --to pdf au lieu de Utiliser --to whitepaper-typst
--to whitepaper-typst
Erreur "bibliography" @ref dans titre callout Supprimer le @ du titre
→ interprété comme cit.
Table rendue comme code Backtick ``` non fermé Compter les ``` (doit être pair)
"Extension not found" Mauvais répertoire Vérifier _extensions/ path
ComponentVersionRole
Quarto≥1.4.0Orchestration, extensions, multi-format
Typst0.13.0Modern typography (replaces LaTeX)
Pandoc3.xMarkdown parsing (bundled with Quarto)

macOS:

Terminal window
brew install quarto

Linux (Debian/Ubuntu):

Terminal window
wget https://github.com/quarto-dev/quarto-cli/releases/download/v1.4.555/quarto-1.4.555-linux-amd64.deb
sudo dpkg -i quarto-1.4.555-linux-amd64.deb

Windows:

Terminal window
winget install Posit.Quarto

Verify:

Terminal window
quarto --version # Should be ≥1.4.0
project/
├── _extensions/ # Quarto extensions (templates)
│ └── custom-template/
│ ├── _extension.yml
│ ├── typst-template.typ
│ └── typst-show.typ
├── documents/
│ ├── guide.qmd # Source file
│ └── guide.pdf # Generated output
└── assets/
└── logo.png # Shared assets

Create document.qmd:

---
title: "My Document"
author: "Author Name"
date: 2026-01-17
format:
typst:
toc: true
lang: en
---
# Introduction
Your content here...
## Section 1
More content with **bold** and `code`.
```bash
echo "Code blocks work!"
Column AColumn B
Data 1Data 2
Generate:
```bash
quarto render document.qmd # Creates document.pdf

1. Write content in Markdown (.qmd)
2. Add YAML frontmatter for metadata
3. Preview with hot-reload
4. Generate final PDF
5. Version control both source and PDF
ParameterTypeDescriptionExample
titlestringMain title"Technical Guide"
subtitlestringSecondary title"v2.0 Edition"
authorstring/arrayAuthor(s)"John Doe"
datedateDocument date2026-01-17
date-formatstringDisplay format"MMMM YYYY"
tocbooleanTable of contentstrue
toc-depthnumberTOC levels (1-3)2
langstringLanguagefr or en
section-numberingstringNumber format"1.1"

Page Breaks:

{{< pagebreak >}}

Code Blocks (with syntax highlighting):

```typescript
function hello(): string {
return "world";
}
```

Tables:

| Feature | Supported |
|---------|-----------|
| Tables | ✅ |
| Images | ✅ |
| Links | ✅ |

Images:

![Alt text](path/to/image.png){width=50%}

Invoke the skill for guided PDF generation:

/pdf-generator

The skill provides:

  • Template with YAML frontmatter
  • Design system configuration
  • Common troubleshooting fixes
  • Generation commands

Generate documentation:

Create a technical guide for our API as a Quarto document.
Use the Typst format with a table of contents.
Include sections for: Authentication, Endpoints, Error Codes.

Convert existing Markdown:

Convert README.md to a professional PDF.
Add a cover page with title and date.
Use Quarto/Typst format.

Create template:

Create a Quarto extension for our company's document style:
- Logo in header
- Custom colors: primary #0f172a, accent #6366f1
- Inter font for body, JetBrains Mono for code

For complex documents:

[Press Shift+Tab to enter Plan Mode]
I need to create a series of 5 technical whitepapers.
Plan the structure:
1. Common template/extension
2. Shared assets
3. Build automation
4. Version management

Auto-generate PDF after edits using a PostToolUse hook:

// In .claude/settings.json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"command": "if echo \"$TOOL_INPUT\" | grep -q '.qmd'; then quarto render \"$FILE\"; fi"
}
]
}
}

Create _extensions/mytemplate/_extension.yml:

title: My Template
author: Your Name
version: 1.0.0
contributes:
formats:
typst:
template: typst-template.typ
template-partials:
- typst-show.typ

In typst-template.typ:

// Colors
#let primary = rgb("#0f172a") // Dark text
#let secondary = rgb("#334155") // Lighter text
#let accent = rgb("#6366f1") // Highlights
// Typography
#set text(
font: ("Inter", "Helvetica Neue", "Arial"),
size: 11pt,
)
#set par(
leading: 0.75em, // Line height
justify: true,
)
// Code blocks
#show raw.where(block: true): it => {
block(
fill: rgb("#f8fafc"),
stroke: (left: 3pt + accent),
inset: 10pt,
radius: 4pt,
it,
)
}

Define in template:

#let info(title: "Note", body) = {
block(
fill: rgb("#E0F2FE"),
stroke: (left: 3pt + rgb("#0284C7")),
inset: 12pt,
radius: 4pt,
[*#title*: #body]
)
}
#let warning(title: "Warning", body) = { ... }
#let success(title: "Success", body) = { ... }
#let danger(title: "Danger", body) = { ... }

Use in document:

#info[This is an informational note.]
#warning(title: "Attention")[Check your configuration.]

Terminal window
# Verify Quarto
quarto --version
# Check extension exists
ls _extensions/*/
# Validate code block pairs (must be even)
grep -c '^```' document.qmd
# Check encoding
file -i document.qmd # Should show utf-8
IssueSymptomFix
Nested code blocksContent escapes blockUse 4+ backticks for outer block
Tables as codeGrey backgroundCheck unmatched ``` above
Missing extension”Extension not found”Verify _extensions/ path
Font warnings”unknown font family”Normal; uses fallbacks
Special chars broken? or garbledConvert to UTF-8

Problem: Inner code block closes outer block prematurely.

Solution: Use more backticks for outer block:

````markdown
# Outer block with 4 backticks
```bash
echo "Inner block with 3 backticks"
```
Outer block continues...
````
validate-qmd.sh
#!/bin/bash
for f in *.qmd; do
count=$(grep -c '^```' "$f")
if [ $((count % 2)) -ne 0 ]; then
echo "ERROR: $f has odd code block count ($count)"
fi
done