PDF Author Skill
A skill for generating professional PDFs using Typst with proper Chinese font support and code block handling, with built-in validation using multimodal capabilities.
Purpose
Generate PDF documents with:
- Proper Chinese character rendering (Source Han Serif/Sans fonts)
- Syntax-highlighted code blocks with frames
- Breakable code blocks that span multiple pages
- Visual validation by converting to PNG and inspecting
Usage
When the user requests PDF generation with Chinese content or code examples, use this skill to:
- Create/update Typst (.typ) files with proper configuration
- Compile to PDF using Docker
- Convert PDF to PNG for validation
- Inspect the rendered output to verify quality
Typst Template Configuration
Quick Start
A complete template is available at .claude/skills/pdf-author/template.typ that you can copy and modify.
Required Setup
Always include this header in Typst files for Chinese support and proper code block styling:
#set page(paper: "a4", margin: 2.5cm)
#set text(font: "Source Han Serif SC", lang: "zh")
// Code block styling with breakable frames
#show raw.where(block: true): it => block(
width: 100%,
fill: luma(245),
stroke: 1pt + luma(180),
radius: 4pt,
inset: 10pt,
breakable: true
)[#it]
Font Options
- Source Han Serif SC (思源宋体): Serif font with traditional decorative strokes
- Source Han Sans SC (思源黑体): Modern sans-serif font
Including External Code Files
Instead of inline code blocks, use external file inclusion:
// For any programming language
#raw(read("example.py"), lang: "python", block: true)
#raw(read("script.sh"), lang: "bash", block: true)
#raw(read("main.cpp"), lang: "cpp", block: true)
Workflow
Step 1: Create Typst Document
Create a .typ file with:
- Proper page and font settings
- Code block styling (breakable frames)
- Content structure using headings, paragraphs, code examples
Step 2: Compile to PDF
Use the Docker-based compilation:
docker run -v $(CURDIR):/workspace -w /workspace typst_cn typst compile <filename>.typ
Or if a Makefile exists with a compile target:
make compile
Step 3: Convert PDF to PNG
Convert the PDF to PNG images for visual inspection:
docker run --rm -v /home/wr/tmp/try_typst:/workspace -w /workspace minidocks/poppler pdftoppm <filename>.pdf output-page -png
Important: Use the full absolute path for the volume mount, not $(CURDIR) which doesn't work in bash.
Step 4: Validate Output
Read the generated PNG files using the Read tool to visually inspect:
- Chinese character rendering quality
- Code block frames and formatting
- Page breaks and content flow
- Syntax highlighting
Check for common issues:
- Blank pages (indicates non-breakable blocks)
- Missing borders on code blocks
- Poor Chinese font rendering
- Code blocks not breaking across pages properly
Step 5: Iterate if Needed
If issues are found:
- Adjust the Typst configuration
- Recompile
- Re-validate
Common Patterns
Creating a Multi-Section Document
= Section Title
Regular paragraph content with 中文支持.
== Subsection with Code
#raw(read("example.py"), lang: "python", block: true)
== Another Subsection
More content here.
Mixing Chinese and English
Typst handles mixed content automatically when lang: "zh" is set.
Math Formulas
数学公式测试:$E = m c^2$
Lists
- 项目一 (Item 1)
- 项目二 (Item 2)
- 项目三 (Item 3)
Docker Images Required
typst_cn: Custom image with Typst and Chinese fonts
- Build from Dockerfile in this skills folder
- Contains Source Han Serif and Sans fonts
- Build command:
docker build -t typst_cn -f .claude/skills/pdf-author/Dockerfile . - Or use Makefile:
make build_docker(if Makefile exists)
minidocks/poppler: For PDF to PNG conversion
- Pulled automatically when first used
- Provides
pdftoppmutility
Building the Typst Docker Image
The Dockerfile in this skills folder creates an Alpine-based image with:
- Typst v0.12.0 compiler
- Source Han Sans SC fonts (思源黑体)
- Source Han Serif SC fonts (思源宋体)
- Required font rendering libraries
To build:
docker build -t typst_cn -f .claude/skills/pdf-author/Dockerfile .
Or if a Makefile with build_docker target exists:
make build_docker
Troubleshooting
Issue: Blank pages before long code blocks
Cause: Using rect() instead of block(breakable: true)
Solution: Ensure the show rule uses:
#show raw.where(block: true): it => block(
breakable: true,
...
)[#it]
Issue: Chinese characters not rendering
Cause: Missing fonts in Docker image or wrong font name
Solution:
- Verify Docker image includes Source Han fonts
- Check font name spelling: "Source Han Serif SC" (exact case)
Issue: Code has no frame/background
Cause: Show rule not applied or incorrect
Solution: Ensure show rule is defined before any content
Issue: PDF not updating
Cause: Docker volume mount issue or compilation error
Solution:
- Check Docker volume path is absolute
- Look for Typst compilation errors in output
Best Practices
- Always validate visually: Don't trust that compilation succeeded - actually look at the PNG output
- Use external files for code: Easier to maintain than inline code blocks
- Test with long content: Generate at least one long code file (300+ lines) to verify page breaks
- Specify absolute paths: When using Docker, always use full paths for volume mounts
- Check multiple pages: Don't just look at page 1 - check pages where content should break
Example Complete Workflow
# 1. Create document
# (Use Write tool to create .typ file with proper header)
# 2. Create code examples
# (Use Write tool to create external .py, .sh, .cpp files)
# 3. Compile
make compile
# 4. Convert to PNG
docker run --rm -v /home/wr/tmp/try_typst:/workspace -w /workspace minidocks/poppler pdftoppm output.pdf page -png
# 5. Validate
# (Use Read tool on page-01.png, page-02.png, etc.)
# 6. Report findings to user
Success Criteria
A successful PDF generation includes:
- ✓ Chinese characters render clearly with proper fonts
- ✓ Code blocks have visible frames with gray background
- ✓ Long code blocks break across pages naturally
- ✓ Syntax highlighting is applied
- ✓ No unexpected blank pages
- ✓ Headers, sections, and content flow logically
- ✓ Mixed Chinese/English content renders correctly