How to Compile and Inspect Final PDFs in AI Job Search: A Complete Guide

Compile AI Job Search PDFs using lualatex for CVs and xelatex for cover letters, then verify ATS compliance with tools/verify_pdf.py.

The MadsLorentzen/ai-job-search framework automates LaTeX generation for job applications. After running the /apply command, you must compile the generated sources and inspect the final PDFs to ensure they are ATS-ready. This guide covers the exact steps to compile and inspect final PDFs based on the source code implementation.

Step 1: Generate LaTeX Sources with /apply

The workflow begins with the application command. Running /apply <job_url> creates two LaTeX files:

  • CV: cv/main_<company>_<role>.tex
  • Cover letter: cover_letters/cover_<company>_<role>.tex

According to SETUP.md (lines 88-96), this step populates templates with your profile data and the parsed job description. The files are ready for compilation immediately after generation.

Step 2: Compile the CV with lualatex

The CV template uses the moderncv document class. The source code specifies LuaLaTeX as the required compiler—pdflatex frequently fails on newer MiKTeX installations due to font handling differences.

From SETUP.md (lines 45-53), run:

cd cv
lualatex -interaction=nonstopmode -halt-on-error main_<company>_<role>.tex
cd ..

The nonstopmode and halt-on-error flags ensure the process exits cleanly on compilation failures, making this suitable for automation pipelines.

Step 3: Compile the Cover Letter with xelatex

The cover letter template (cover_letters/cover.cls) requires XeLaTeX due to custom font dependencies. As documented in SETUP.md (lines 45-53):

cd cover_letters
xelatex -interaction=nonstopmode -halt-on-error cover_<company>_<role>.tex
cd ..

Critical distinction: The CV and cover letter use different compilers. Mixing these causes font substitution errors or compilation failures.

Step 4: Verify ATS Compliance with verify_pdf.py

After compilation, inspect final PDFs using the built-in verification tool at tools/verify_pdf.py. This script performs text-layer extraction and validation checks.

Extraction Engine

The extract_text_layer() function (lines 4-86 in tools/verify_pdf.py) implements a fallback strategy:

  1. Primary: pypdf — pure Python, no external dependencies
  2. Fallback: Poppler's pdftotext — command-line utility for complex PDFs

Validation Checks

The script verifies:

  • Page count — ensures the document is not unexpectedly truncated
  • Character count — flags near-empty PDFs (common LaTeX rendering failures)
  • Required keywords — confirms sections like "Professional Experience" are present

Run the verification:

python3 tools/verify_pdf.py path/to/your_cv.pdf

Interpreting Output

Successful verification produces:


Verified cv/main_example.pdf (extractor: pypdf, pages: 2)

Failures raise a VerificationError with specific details:

  • Missing required text segments
  • Insufficient character count
  • Wrong page count

Step 5: Debug Text Layer Extraction

To manually inspect the extracted content, invoke the extraction function directly:

python3 -c "from tools.verify_pdf import extract_text_layer; \
text, pages, src = extract_text_layer('path/to/your_cv.pdf'); \
print(f'Extractor: {src}\nPages: {pages}\n---\n{text[:500]}')"

This reveals the actual text layer that ATS systems parse—distinct from the visual PDF rendering. Use this when verification fails to identify encoding issues or missing content.

Complete Workflow Example


# 1. Generate LaTeX sources

/apply https://jobindex.dk/job/1234567

# 2. Compile CV

cd cv
lualatex -interaction=nonstopmode -halt-on-error main_example.tex
cd ..

# 3. Compile cover letter

cd cover_letters
xelatex -interaction=nonstopmode -halt-on-error cover_example.tex
cd ..

# 4. Verify both PDFs

python3 tools/verify_pdf.py cv/main_example.pdf
python3 tools/verify_pdf.py cover_letters/cover_example.pdf

Key Implementation Files

File Purpose
tools/verify_pdf.py PDF text extraction and ATS validation logic
cv/main_example.tex Stock CV template (LuaLaTeX / moderncv)
cover_letters/cover.cls Cover letter class (XeLaTeX, custom fonts)
SETUP.md Compilation workflow documentation

Summary

  • /apply generates LaTeX sources in cv/ and cover_letters/ directories
  • CV compilation requires lualatex due to moderncv font requirements
  • Cover letter compilation requires xelatex for custom font handling in cover.cls
  • tools/verify_pdf.py validates PDFs using pypdf with pdftotext fallback
  • Verification checks page count, character count, and required keyword presence

Frequently Asked Questions

Why does the CV require LuaLaTeX instead of pdfLaTeX?

The moderncv document class uses modern font handling that conflicts with pdfLaTeX on current MiKTeX distributions. The ai-job-search source code in SETUP.md explicitly recommends lualatex to avoid compilation failures related to font substitution and encoding.

What happens if verify_pdf.py cannot extract text from my PDF?

The extract_text_layer() function in tools/verify_pdf.py first attempts extraction with pypdf. If that returns empty or garbled text, it automatically falls back to Poppler's pdftotext command-line tool. Both extractors are attempted before raising a VerificationError.

Can I automate the entire compile-and-inspect pipeline?

Yes. The nonstopmode and halt-on-error flags make both lualatex and xelatex suitable for scripting. Chain the commands and add python3 tools/verify_pdf.py calls to create a fully automated workflow that fails fast on compilation or validation errors.

How do I fix a "missing required text" verification error?

Open the .tex source and verify that standard section names like "Professional Experience" are spelled exactly as expected by verify_pdf.py. Re-compile after corrections. Alternatively, use the direct extraction debug command to see exactly which text was detected in the PDF layer.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →