# Common LaTeX Layout Issues and Fixes in the AI Job Search Framework

> Fix common LaTeX layout issues like overflows and font mismatches in the AI Job Search framework. Learn how automated compilation and validation ensure perfect PDF outputs for ATS.

- Repository: [Mads Lorentzen/ai-job-search](https://github.com/MadsLorentzen/ai-job-search)
- Tags: how-to-guide
- Published: 2026-09-03

---

**The AI Job Search framework prevents orphaned headings, page overflows, font mismatches, and ATS extraction errors by automating LaTeX compilation with `lualatex` and `xelatex`, injecting `\needspace` commands, and running [`verify_pdf.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/verify_pdf.py) to validate page counts and text layers.**

The `MadsLorentzen/ai-job-search` repository provides a fully automated pipeline for generating job application documents, but LaTeX rendering can diverge significantly between source `.tex` files and the resulting PDF output. To ensure consistent, ATS-friendly results, the framework anticipates recurring LaTeX layout issues and applies concrete remedies through automated checks and source code modifications.

## Orphaned Headings and Section Breaks

A common LaTeX problem occurs when a section heading lands at the bottom of a page while its content starts on the next page, creating visual orphans. The framework fixes this by pre-emptively reserving vertical space before critical headings.

In `cv/main_example.tex`, the template injects `\needspace{<n>}{<heading>}` to force a page break when insufficient space remains:

```latex
\needspace{3\baselineskip}
\section{Professional Experience}

```

This command ensures that if a heading cannot fit with at least three lines of following content, LaTeX breaks the page before the heading rather than after it.

## CV Page Overflow Control

The default moderncv layout has no built-in enforcement for the two-page limit common in industry standards. Without intervention, bullet points and experience entries accumulate until the CV spills onto a third page.

The framework solves this through **relevance-weighted CV cutting**. The `/apply` workflow runs [`tools/verify_pdf.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/verify_pdf.py), which parses the compiled PDF, counts pages, and automatically rewrites the LaTeX source to drop or shrink the lowest-scoring lines when the document exceeds two pages. This validation step ensures the final output strictly adheres to the two-page constraint regardless of input length.

## Cover Letter Length Management

The custom `cover.cls` class is designed for a single-page cover letter, but long paragraphs can push content onto a second page due to fixed-height headers and generous margins.

The framework addresses this in `cover_letters/cover.cls` by strategically applying `\enlargethispage{<len>}` to add extra capacity when needed:

```latex
\enlargethispage{2\baselineskip}

```

When [`verify_pdf.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/verify_pdf.py) detects a two-page cover letter during the verification step, it automatically triggers space adjustments or content trimming to compress the letter back to a single page.

## Font Mismatches and Missing Glyphs

Font handling represents a critical LaTeX layout issue, particularly when using `fontawesome5` icons for contact information. On standard PDFLaTeX installations, OpenType icon glyphs may not embed properly, resulting in blank symbols in the final PDF.

The framework mandates specific Unicode-aware engines to resolve this:

- **CV compilation** uses **lualatex** (required for `moderncv` with `fontawesome5`)
- **Cover letter compilation** uses **xelatex** (required for `fontspec` and custom Lato/Raleway fonts)

The README specifies these prerequisites explicitly, ensuring proper Unicode handling for icon fonts and preventing glyph substitution failures across different TeX installations.

## Missing Package Dependencies

Minimal TeX distributions such as TinyTeX or BasicTeX ship only core packages, causing compilation failures when `moderncv`, `fontawesome5`, or `fontspec` are missing.

The framework mitigates this through preventive documentation and CI validation. The README lists exact extra packages to install, while [`.github/workflows/ci.yml`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.github/workflows/ci.yml) runs smoke-compilation tests to catch missing dependencies early in the development cycle. This ensures that environment setup issues surface before job application deadlines.

## ATS Text Extraction Validation

PDF text layers can contain invisible control characters or render glyphs as images rather than searchable text, breaking keyword matching in Applicant Tracking Systems (ATS).

After compilation, [`tools/verify_pdf.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/verify_pdf.py) validates extractability using `pdftotext` (with `pypdf` as fallback):

```python
from pathlib import Path
from pypdf import PdfReader

pdf = PdfReader(Path("output.pdf"))
assert len(pdf.pages) == 2  # CV must be 2 pages

text = "\n".join(page.extract_text() for page in pdf.pages)
assert "email@example.com" in text.lower()

```

This verification extracts the text layer, validates contact fields, and flags any non-extractable content before the application is submitted.

## The Automated /apply Workflow

All LaTeX layout safeguards integrate into a single command flow that iteratively refines the output:

1. **Compile**: Draft LaTeX processes through `lualatex` (CV) or `xelatex` (cover letter)
2. **Verify**: [`tools/verify_pdf.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/verify_pdf.py) extracts page counts and text layers, detecting layout anomalies
3. **Rewrite**: If problems exist, the workflow automatically modifies source code (adding `\needspace`, trimming low-score lines, inserting `\enlargethispage`)
4. **Recompile**: The PDF rebuilds until the CV is exactly **2 pages** and the cover letter **1 page** with clean text extraction

This loop ensures reliable output across different TeX installations while guaranteeing ATS compatibility.

## Summary

- **Orphaned headings** are prevented using `\needspace` commands in `cv/main_example.tex` to keep headings with their content blocks
- **Page overflow** is managed by [`verify_pdf.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/verify_pdf.py), which automatically trims low-relevance content to enforce strict two-page CV and one-page cover letter limits
- **Font issues** are eliminated by compiling with `lualatex` (CV) and `xelatex` (cover letter) rather than standard PDFLaTeX
- **Missing packages** are caught early through CI smoke tests in [`.github/workflows/ci.yml`](https://github.com/MadsLorentzen/ai-job-search/blob/main/.github/workflows/ci.yml) and explicit README documentation
- **ATS compatibility** is verified by extracting text layers with `pypdf` to ensure searchable content and proper glyph embedding

## Frequently Asked Questions

### Why does the framework use different LaTeX engines for the CV and cover letter?

The CV requires **lualatex** because the `moderncv` class with `fontawesome5` icons needs Unicode-aware font handling that PDFLaTeX cannot provide. The cover letter uses **xelatex** because the custom `cover.cls` relies on `fontspec` to load system fonts like Lato and Raleway. Using the correct engine prevents blank glyphs and ensures consistent font rendering across operating systems.

### How does the framework prevent the CV from exceeding two pages?

The [`tools/verify_pdf.py`](https://github.com/MadsLorentzen/ai-job-search/blob/main/tools/verify_pdf.py) script parses the compiled PDF to count pages. If the CV exceeds two pages, the framework automatically rewrites the LaTeX source to remove or shrink the lowest-scoring experience bullets based on relevance weighting. This process repeats until the document fits the two-page constraint without manual editing.

### What causes font icons to appear blank in the PDF, and how is it fixed?

Blank icons occur when the TeX engine cannot embed OpenType glyphs from `fontawesome5`. The framework fixes this by mandating `lualatex` for CV compilation, which properly handles Unicode icon fonts. Additionally, the README documents all required font packages to ensure they are installed before compilation begins.

### How does verify_pdf.py ensure ATS compatibility?

The script extracts the PDF text layer using `pdftotext` or the `pypdf` library, then validates that contact information and key terms are searchable and not rendered as images. It asserts specific page counts (two for CV, one for cover letter) and verifies that extracted text contains expected content, flagging any non-extractable glyphs or invisible control characters that could break keyword matching.