PDF Production
A PDF is the only deliverable format whose defects are invisible in the
source. Text that fits in Markdown clips in a PDF. A table that renders on
screen breaks across a page. A font that displays correctly in the editor
drops accented capitals in the output.
Therefore the rule that governs this skill: a generated PDF is not a
finished PDF until the rendered pages have been inspected. Not the source.
The pages.
Governed by document-core for content and document-design for layout.
This skill owns the engine, the pipeline and the verification.
1. Engine selection
There is no correct default. Choose from the document.
| Engine |
Strong at |
Weak at |
Choose when |
| Headless Chromium |
HTML and CSS fidelity, web fonts, complex layout, SVG, charts |
large documents, memory, reproducibility across versions |
the document is already HTML, or the layout is complex |
| WeasyPrint |
CSS Paged Media, running headers, page counters, reproducibility |
very recent CSS, JavaScript |
a paginated document from HTML, deterministic output wanted |
| Typst |
typography, tables, references, fast compilation, readable source |
ecosystem maturity, unusual layouts |
a structured technical or report document, produced repeatedly |
| LaTeX |
mathematics, long-document typography, bibliographies |
learning cost, toolchain size, debugging |
mathematics, or a house template already exists |
| Markdown via a converter |
speed, simple documents |
pagination control, precise layout |
a short internal document where layout is not a requirement |
| A library building the PDF directly |
exact placement, forms, filling an existing template |
everything else, including changing the design later |
filling a fixed form, or stamping an existing PDF |
Decision procedure:
- Is the source already HTML, or does it need CSS layout? Chromium or
WeasyPrint.
- Does it need running headers, page counters or precise pagination?
WeasyPrint or Typst, not a Markdown converter.
- Is it mathematics? LaTeX.
- Is it produced repeatedly and reviewed in version control? Prefer a text
source: Typst, LaTeX or HTML, not a binary or a manual process.
- Is it a fixed official form? A library, filling fields.
Constraints that override preference:
- Verify the engine exists before promising a PDF. Check the command runs.
A pipeline that assumes an engine is a pipeline that fails on someone else's
machine.
- Prefer what the project already uses. A second engine is a second set of
fonts, a second CSS dialect and a second class of bug.
- Prefer an engine installable without a browser or a full distribution when
the document is simple. Do not install 300MB to produce a two-page letter.
- Record the engine and its version in the recipe. The same source with a
different version does not produce the same pages.
2. Structure
| Element |
Rule |
| Cover |
title, subtitle, version, date, author or organisation, recipient; no header or footer, not counted in the numbering the reader sees |
| Metadata |
title, author, subject, keywords, language; set in the document, not left to the exporter |
| Table of contents |
generated from the headings, never typed; page numbers regenerated after the final edit |
| Sections |
starting on a new page for formal deliverables, and on an odd page for double-sided printing |
| Page breaks |
controlled: never immediately after a heading, never separating a caption from its object |
| Headers |
document title and current section; suppressed on the cover |
| Footers |
page number, version, date |
| Page numbers |
n of N where the document may be printed and separated |
| Annexes |
numbered separately, listed in the contents |
Typography and layout are decided by document-design and applied here. This
skill does not re-decide them.
3. Font embedding
The most common silent PDF defect.
- Every font is embedded. A PDF referencing a font the reader lacks is
substituted, and the substitution changes the pagination.
- Every font contains every glyph of the output language. Verify by rendering
a sample containing the accented characters, capitals included, the currency
symbols and any special punctuation, then looking at it.
- A missing glyph renders as a box, a blank or a substituted character. All
three are invisible in the source and obvious in the render.
- Where the document mixes scripts, verify each script separately.
pdffonts document.pdf
Every row must show an embedded font. Any row showing a non-embedded font is a
defect, not a warning.
4. Verification
Mandatory. Automated checks first, then the eyes, because the eyes catch what
no check describes.
Automated
pdfinfo document.pdf # pages, size, title, author, language
pdffonts document.pdf # every font embedded
pdftotext document.pdf - | head -50 # text extractable, reading order sane
qpdf --check document.pdf # structural integrity
Checks:
Visual
Automated checks pass on documents that are visibly broken. Render the pages
and look at them.
pdftoppm -png -r 110 document.pdf page # one image per page
Then inspect every page, or every page of a long document's first twenty plus
a systematic sample plus every page containing a table or a figure.
| Defect |
What it looks like |
| Clipped text |
a line cut at the margin, or a descender shaved |
| Overflow |
text past the margin, or into the header or footer |
| Orphan heading |
a heading alone at the foot of a page |
| Widow line |
one line of a paragraph alone at the top of a page |
| Broken table |
header on one page, rows on the next with no header |
| Empty page |
an unintended blank, usually from a forced break |
| Missing glyph |
a box, a blank, or a wrong character in accented text |
| Wrong page numbers |
contents disagreeing with the pages |
| Inconsistent typography |
one heading at the wrong size, usually the last one edited |
| Broken image |
absent, stretched, pixelated, or cropped |
| Unreadable content |
a table shrunk to fit, a caption at 6pt |
| Overlap |
a figure over text, a footer over the last line |
| Wrong cover |
the previous version's date, or a placeholder never replaced |
Print
For anything that will be printed:
Where printing is impossible, render at print resolution, convert to
greyscale, and inspect. State that this was done instead of a physical print,
rather than implying a print check that did not happen.
5. Reproducibility
A PDF produced once by hand is a PDF nobody can correct.
- The source is text and lives in version control. The PDF is an artefact.
- Generation is one command, recorded in the recipe.
- The recipe records the engine, its version, the fonts and the command.
- Regenerating from an unchanged source produces the same pages. Where the
engine embeds a timestamp, the byte output differs and the pages do not;
compare rendered pages, not bytes.
- Never edit the PDF by hand. Edit the source and regenerate, or the next
regeneration silently discards the correction.
## Generation recipe
Engine: weasyprint 62.3
Fonts: Source Serif 4 2.100, Source Sans 3 2.045, both embedded
Source: docs/handover.md, docs/print.css
Command: make handover.pdf
Verified: 2026-08-11, 34 pages, all fonts embedded, pages rendered and inspected
6. Accessibility and size
- Set the document language. Without it, a screen reader guesses.
- Reading order must match visual order; verify by extracting the text.
- Images that carry information need alternative text where the engine
supports it, and a caption in every case.
- Never distribute a scanned image of text as a document. It is unsearchable,
inaccessible and unquotable.
- Compress images to their display size. A 4000px screenshot on a 600px column
is 40 times the necessary bytes.
- Keep the file small enough to email. Where it cannot be, split it or link the
annexes.
7. Protocol
- Confirm the content passed the
document-core gate and the layout passed
document-design.
- Select the engine with section 1. Verify it is installed and record its
version.
- Verify font glyph coverage for the output language by rendering a sample
and looking at it.
- Build the structure of section 2 and set the metadata.
- Generate.
- Run the automated checks of section 4.
- Render the pages to images and inspect them. This step is not optional and
is not replaced by the automated checks.
- Fix defects in the source, never in the PDF, and regenerate.
- Re-inspect the pages the fixes touched, plus the pages after them, because
a pagination fix moves everything downstream.
- Perform the print check where the document will be printed.
- Record the recipe and the verification report.
- Name the file as an index entry and deliver.
8. Auto-critique
Score 0 to 5: engine chosen from the document and verified installed, fonts
embedded and glyph coverage checked by rendering, structure complete, metadata
correct, automated checks run, pages rendered and actually inspected, defects
fixed in the source, re-inspection after pagination changes, print check where
applicable, recipe recorded and reproducible.
Threshold: no axis below 3, average at least 4. For a document leaving the
organisation, average at least 4.3.
Automatic failure: delivering a PDF whose pages were never rendered and
looked at, a non-embedded font, a hand edit to the PDF, or a contents page
whose numbers were not regenerated after the final edit.
9. Interfaces
- Upstream:
document-design, technical-writing, user-documentation,
report-writing, administrative-writing.
- Downstream:
self-critique, client-handover.
- Related:
document-core section 7 gates 9 to 11 are executed here.
1---2name: pdf-production3description: PDF Production4---56# PDF Production78A PDF is the only deliverable format whose defects are invisible in the9source. Text that fits in Markdown clips in a PDF. A table that renders on10screen breaks across a page. A font that displays correctly in the editor11drops accented capitals in the output.1213Therefore the rule that governs this skill: **a generated PDF is not a14finished PDF until the rendered pages have been inspected.** Not the source.15The pages.1617Governed by `document-core` for content and `document-design` for layout.18This skill owns the engine, the pipeline and the verification.1920## 1. Engine selection2122There is no correct default. Choose from the document.2324| Engine | Strong at | Weak at | Choose when |25|---|---|---|---|26| Headless Chromium | HTML and CSS fidelity, web fonts, complex layout, SVG, charts | large documents, memory, reproducibility across versions | the document is already HTML, or the layout is complex |27| WeasyPrint | CSS Paged Media, running headers, page counters, reproducibility | very recent CSS, JavaScript | a paginated document from HTML, deterministic output wanted |28| Typst | typography, tables, references, fast compilation, readable source | ecosystem maturity, unusual layouts | a structured technical or report document, produced repeatedly |29| LaTeX | mathematics, long-document typography, bibliographies | learning cost, toolchain size, debugging | mathematics, or a house template already exists |30| Markdown via a converter | speed, simple documents | pagination control, precise layout | a short internal document where layout is not a requirement |31| A library building the PDF directly | exact placement, forms, filling an existing template | everything else, including changing the design later | filling a fixed form, or stamping an existing PDF |3233Decision procedure:34351. Is the source already HTML, or does it need CSS layout? Chromium or36 WeasyPrint.372. Does it need running headers, page counters or precise pagination?38 WeasyPrint or Typst, not a Markdown converter.393. Is it mathematics? LaTeX.404. Is it produced repeatedly and reviewed in version control? Prefer a text41 source: Typst, LaTeX or HTML, not a binary or a manual process.425. Is it a fixed official form? A library, filling fields.4344Constraints that override preference:4546- **Verify the engine exists before promising a PDF.** Check the command runs.47 A pipeline that assumes an engine is a pipeline that fails on someone else's48 machine.49- Prefer what the project already uses. A second engine is a second set of50 fonts, a second CSS dialect and a second class of bug.51- Prefer an engine installable without a browser or a full distribution when52 the document is simple. Do not install 300MB to produce a two-page letter.53- Record the engine and its version in the recipe. The same source with a54 different version does not produce the same pages.5556## 2. Structure5758| Element | Rule |59|---|---|60| Cover | title, subtitle, version, date, author or organisation, recipient; no header or footer, not counted in the numbering the reader sees |61| Metadata | title, author, subject, keywords, language; set in the document, not left to the exporter |62| Table of contents | generated from the headings, never typed; page numbers regenerated after the final edit |63| Sections | starting on a new page for formal deliverables, and on an odd page for double-sided printing |64| Page breaks | controlled: never immediately after a heading, never separating a caption from its object |65| Headers | document title and current section; suppressed on the cover |66| Footers | page number, version, date |67| Page numbers | `n of N` where the document may be printed and separated |68| Annexes | numbered separately, listed in the contents |6970Typography and layout are decided by `document-design` and applied here. This71skill does not re-decide them.7273## 3. Font embedding7475The most common silent PDF defect.7677- Every font is embedded. A PDF referencing a font the reader lacks is78 substituted, and the substitution changes the pagination.79- Every font contains every glyph of the output language. Verify by rendering80 a sample containing the accented characters, capitals included, the currency81 symbols and any special punctuation, then looking at it.82- A missing glyph renders as a box, a blank or a substituted character. All83 three are invisible in the source and obvious in the render.84- Where the document mixes scripts, verify each script separately.8586```bash87pdffonts document.pdf88```8990Every row must show an embedded font. Any row showing a non-embedded font is a91defect, not a warning.9293## 4. Verification9495Mandatory. Automated checks first, then the eyes, because the eyes catch what96no check describes.9798### Automated99100```bash101pdfinfo document.pdf # pages, size, title, author, language102pdffonts document.pdf # every font embedded103pdftotext document.pdf - | head -50 # text extractable, reading order sane104qpdf --check document.pdf # structural integrity105```106107Checks:108109- [ ] Page count matches expectation. An unexpected extra page is a defect.110- [ ] Metadata present and correct: title is the title, not the filename.111- [ ] Language set, so screen readers pronounce correctly.112- [ ] Every font embedded.113- [ ] Text extractable. Nothing that should be text is an image.114- [ ] Extraction order matches reading order.115- [ ] File size proportionate. A 40MB text document means unoptimised images.116- [ ] Structure valid.117118### Visual119120Automated checks pass on documents that are visibly broken. Render the pages121and look at them.122123```bash124pdftoppm -png -r 110 document.pdf page # one image per page125```126127Then inspect every page, or every page of a long document's first twenty plus128a systematic sample plus every page containing a table or a figure.129130| Defect | What it looks like |131|---|---|132| Clipped text | a line cut at the margin, or a descender shaved |133| Overflow | text past the margin, or into the header or footer |134| Orphan heading | a heading alone at the foot of a page |135| Widow line | one line of a paragraph alone at the top of a page |136| Broken table | header on one page, rows on the next with no header |137| Empty page | an unintended blank, usually from a forced break |138| Missing glyph | a box, a blank, or a wrong character in accented text |139| Wrong page numbers | contents disagreeing with the pages |140| Inconsistent typography | one heading at the wrong size, usually the last one edited |141| Broken image | absent, stretched, pixelated, or cropped |142| Unreadable content | a table shrunk to fit, a caption at 6pt |143| Overlap | a figure over text, a footer over the last line |144| Wrong cover | the previous version's date, or a placeholder never replaced |145146### Print147148For anything that will be printed:149150- [ ] Printed in greyscale, on paper, and read. Every distinction survives.151- [ ] Nothing enters the binding margin or the unprintable edge.152- [ ] Links show their target in a footnote or an annex.153- [ ] Double-sided pagination correct: sections start where intended.154155Where printing is impossible, render at print resolution, convert to156greyscale, and inspect. State that this was done instead of a physical print,157rather than implying a print check that did not happen.158159## 5. Reproducibility160161A PDF produced once by hand is a PDF nobody can correct.162163- The source is text and lives in version control. The PDF is an artefact.164- Generation is one command, recorded in the recipe.165- The recipe records the engine, its version, the fonts and the command.166- Regenerating from an unchanged source produces the same pages. Where the167 engine embeds a timestamp, the byte output differs and the pages do not;168 compare rendered pages, not bytes.169- Never edit the PDF by hand. Edit the source and regenerate, or the next170 regeneration silently discards the correction.171172```markdown173## Generation recipe174Engine: weasyprint 62.3175Fonts: Source Serif 4 2.100, Source Sans 3 2.045, both embedded176Source: docs/handover.md, docs/print.css177Command: make handover.pdf178Verified: 2026-08-11, 34 pages, all fonts embedded, pages rendered and inspected179```180181## 6. Accessibility and size182183- Set the document language. Without it, a screen reader guesses.184- Reading order must match visual order; verify by extracting the text.185- Images that carry information need alternative text where the engine186 supports it, and a caption in every case.187- Never distribute a scanned image of text as a document. It is unsearchable,188 inaccessible and unquotable.189- Compress images to their display size. A 4000px screenshot on a 600px column190 is 40 times the necessary bytes.191- Keep the file small enough to email. Where it cannot be, split it or link the192 annexes.193194## 7. Protocol1951961. Confirm the content passed the `document-core` gate and the layout passed197 `document-design`.1982. Select the engine with section 1. Verify it is installed and record its199 version.2003. Verify font glyph coverage for the output language by rendering a sample201 and looking at it.2024. Build the structure of section 2 and set the metadata.2035. Generate.2046. Run the automated checks of section 4.2057. Render the pages to images and inspect them. This step is not optional and206 is not replaced by the automated checks.2078. Fix defects in the source, never in the PDF, and regenerate.2089. Re-inspect the pages the fixes touched, plus the pages after them, because209 a pagination fix moves everything downstream.21010. Perform the print check where the document will be printed.21111. Record the recipe and the verification report.21212. Name the file as an index entry and deliver.213214## 8. Auto-critique215216Score 0 to 5: engine chosen from the document and verified installed, fonts217embedded and glyph coverage checked by rendering, structure complete, metadata218correct, automated checks run, pages rendered and actually inspected, defects219fixed in the source, re-inspection after pagination changes, print check where220applicable, recipe recorded and reproducible.221222Threshold: no axis below 3, average at least 4. For a document leaving the223organisation, average at least 4.3.224225Automatic failure: delivering a PDF whose pages were never rendered and226looked at, a non-embedded font, a hand edit to the PDF, or a contents page227whose numbers were not regenerated after the final edit.228229## 9. Interfaces230231- Upstream: `document-design`, `technical-writing`, `user-documentation`,232 `report-writing`, `administrative-writing`.233- Downstream: `self-critique`, `client-handover`.234- Related: `document-core` section 7 gates 9 to 11 are executed here.