How to Convert Jekyll Documentation to PDF with a Table of Contents
Build your Jekyll site first, then convert the generated HTML to a linked PDF with Prince, wkhtmltopdf, or a Jekyll plugin.
Direct answer: build your Jekyll documentation into HTML first, then give that generated site to a PDF engine. Use your sidebar or heading structure as the source for a clickable table of contents, apply a print layout that removes web navigation, and inspect the resulting PDF for links, images, page breaks and page numbers.
Jekyll converts Markdown pages with YAML front matter into HTML during a build; the generated files normally appear in _site unless your permalinks change their paths. A PDF converter consumes those HTML files, not your Markdown source directly. Jekyll’s documentation describes the build model, while Prince documents a complete Jekyll-to-PDF workflow with a full TOC, mini-TOCs, cross-reference page numbers and running headers and footers.
1. Choose the PDF workflow
| Workflow | Best when | TOC and layout control | Main trade-off |
|---|---|---|---|
| Prince | You need reliable print CSS, page references, headers, footers and a documentation-theme workflow | Strongest; can build a full TOC and mini-TOCs from sidebar metadata | Separate software and licensing to manage |
| wkhtmltopdf | You want an open-source command-line converter with outline and TOC switches | Good command-line controls for outlines, TOC, page offsets and print media | Modern CSS support can differ from a browser |
| jekyll-pdf plugin | You want PDF generation integrated into Jekyll pages or collections | Convenient; pages can opt in with pdf: true and wkhtmltopdf-compatible settings |
Adds a dependency whose maintenance should be checked |
For the most complete cited documentation-theme workflow, start with Prince. Choose wkhtmltopdf when its command-line behavior and plugin compatibility fit your build. A plugin reduces glue code but should be pinned and reviewed like any other gem.
2. Prepare the Jekyll source
- Keep Markdown files, YAML front matter, permalinks, sidebar URLs and assets consistent.
- Make every page that belongs in the manual discoverable from the sidebar or an explicit PDF input list.
- Check that heading levels are hierarchical: one
h1for the page title, thenh2andh3sections. - Use Bundler to pin Jekyll, themes and plugins. GitHub recommends Bundler to reduce dependency and environment errors.
bundle install
bundle exec jekyll build --config _config.yml
find _site -maxdepth 3 -type f | sort | head -50
Inspect _site before involving a PDF engine. Missing files at this stage become missing links, images or styles in the PDF.
3. Create a PDF-specific configuration
Keep web and print concerns separate. Copy your normal configuration to a file such as _config_pdf.yml, then set the print title and subtitle, identify the sidebar, select the site folder and mark the pages included in the manual. Documentation themes commonly use page metadata and sidebar entries to build the input list.
# _config_pdf.yml
url: "https://docs.example.com"
baseurl: ""
title: "Example Documentation"
subtitle: "Version 2.4"
# Keep the same collections, defaults and theme as the web build.
# Add the theme's PDF-specific settings here.
pdf:
title: "Example Documentation"
subtitle: "Version 2.4"
sidebar: "docs"
output: "_site-pdf"
The exact keys are theme-specific. Preserve the theme’s documented names rather than inventing new ones; the important pattern is a reproducible configuration that identifies the pages, assets and print layout used for the PDF.
4. Add a clickable table of contents
On-page kramdown TOC
For a TOC inside one page, put the marker where the list should appear:
---
layout: default
title: Installation
# Use the TOC front-matter setting required by your theme.
---
* TOC
{:toc}
## Install the CLI
## Configure authentication
### Environment variables
If the list is empty, verify the heading levels, the exact * TOC and {:toc} markers, and the front-matter setting required by your theme.
Whole-manual TOC
For a complete manual, let the PDF workflow derive entries from the sidebar or its equivalent input list. This preserves the documentation’s navigation order and can produce mini-TOCs for individual sections. Ensure every sidebar URL resolves to a generated file and that the PDF input list contains the intended pages only.
5. Build HTML before converting
Run the PDF configuration as an ordinary Jekyll build or server. A theme example explicitly requires an HTML web target before Prince runs.
bundle exec jekyll serve --config _config_pdf.yml
# Or create a static directory for CI:
bundle exec jekyll build --config _config_pdf.yml --destination _site-pdf
Open the generated HTML in a browser and check the navigation, heading order, code blocks, images, canonical links and internal anchors. A PDF converter cannot repair a broken Jekyll build.
6. Convert the generated HTML with Prince
Prince can consume a selected HTML entry point or a theme-generated list such as prince-list.txt. The exact command depends on the theme, but a simple single-entry conversion looks like this:
prince \
--media=print \
--javascript \
_site-pdf/index.html \
-o dist/documentation.pdf
For a documentation theme, use its supplied Prince command or input list so the sidebar order, cover, full TOC and section mini-TOCs are retained. Add print CSS for page size, margins, page breaks, running headers and footers. Prince’s documentation-theme workflow can include page numbers in cross references.
7. Convert with wkhtmltopdf
wkhtmltopdf provides command-line controls for outlines, TOC generation, page offsets and print-media selection. A basic conversion is:
wkhtmltopdf \
--print-media-type \
--outline \
--enable-local-file-access \
_site-pdf/index.html \
dist/documentation.pdf
When your project uses wkhtmltopdf’s generated TOC, consult its installed usage output for the version-specific switches and add the TOC input after the cover or title page. Test local asset access carefully; allowing local files is useful for a self-contained build but should match your CI security policy.
8. Use the jekyll-pdf plugin
A plugin can generate PDFs for pages or collections when pdf: true is set in front matter or defaults. It accepts wkhtmltopdf-compatible settings, so configure the page selection and converter options in the plugin’s documented format.
# _config.yml (illustrative structure; use the plugin's documented keys)
plugins:
- jekyll-pdf
defaults:
- scope:
path: "docs"
values:
pdf: true
Pin the plugin and converter versions in CI. A plugin is convenient, but it does not remove the need to verify page order, heading anchors, assets and print CSS.
9. Add print CSS for readable pages
Hide web-only controls and preserve content that matters on paper. Use a PDF layout or print stylesheet to remove navigation, sidebars, cookie notices, chat widgets and interactive controls.
@media print {
.site-nav,
.sidebar,
.edit-link,
.feedback-widget,
.cookie-banner {
display: none !important;
}
main {
max-width: none;
}
pre, blockquote, table, figure {
break-inside: avoid;
}
h1, h2, h3 {
break-after: avoid;
}
a[href^="http"]::after {
content: " (" attr(href) ")";
font-size: 0.85em;
}
}
@page {
size: A4;
margin: 20mm 16mm 18mm;
}
Use absolute or resolvable local paths for stylesheets, fonts and images. If your converter cannot resolve a relative URL from the generated HTML location, correct the Jekyll url/baseurl settings or copy the asset into the PDF output directory.
10. Verify the finished PDF
- Open the outline/bookmarks and confirm the expected section order.
- Click TOC entries and internal links.
- Check that images, fonts, code blocks and tables are present.
- Confirm navigation and web-only widgets are gone.
- Inspect page breaks around headings, long tables and code blocks.
- Search for the document title, version and generated date.
- Open the PDF in at least one browser viewer and one desktop PDF viewer.
11. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Prince stops before producing a PDF | Sidebar URL, permalink or asset is missing or misspelled | Inspect generated _site paths and the theme’s prince-list.txt or equivalent input list. |
| TOC is empty | Incorrect heading levels, missing kramdown markers or missing front matter | Check * TOC, {:toc}, heading hierarchy and the theme’s required TOC setting. |
| Web navigation appears in the PDF | The normal web layout is being printed | Use the PDF layout or load the print stylesheet with --media=print or --print-media-type. |
| Links or images are broken | Relative paths do not resolve from the generated HTML | Confirm files exist in _site, use correct url/baseurl, and configure local asset access when appropriate. |
| Pages are in the wrong order | Filesystem order differs from sidebar order | Use the theme’s sidebar metadata or an explicit PDF input list. |
| Styles work in a browser but not in the PDF | Converter CSS support differs from the browser | Prefer print CSS supported by your chosen engine, simplify layout rules and test a minimal page. |
| Build fails after a dependency update | Unpinned Jekyll, theme, plugin or converter versions | Use Bundler and lock versions; rebuild in the same CI image. |
12. Performance, reliability and cost
Build once and convert from the generated directory so Markdown processing and asset copying do not happen repeatedly. Keep the PDF input list limited to the manual’s pages, optimize very large images, and avoid unnecessary JavaScript. Cache Bundler dependencies in CI, but invalidate the cache when the lockfile changes.
Reliability comes from deterministic inputs: a locked dependency set, a dedicated PDF configuration, a fixed converter version, checked asset paths and a post-build link check. Store the PDF as a CI artifact and compare page count or extracted text between releases when documentation changes are important.
Prince licensing, wkhtmltopdf packaging and plugin maintenance are separate operational costs. Select an engine after checking its current license, supported platform and release activity. There are no general performance figures that apply to every Jekyll theme or document.
Or skip the browser setup
If your Jekyll site is published or reachable from your build, ScreenshotNeo can capture the rendered page through one API request. It accepts a URL and can return PNG, JPEG, WebP or PDF; PDF options include paper size, margins, landscape mode and page ranges. The API also supports full-page capture with lazy images loaded, custom CSS and JavaScript, waits for a selector, delay or network idle, and custom headers or cookies. See the ScreenshotNeo API documentation for the PDF parameters.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
In a PDF workflow, point url at the built documentation entry page and select the PDF output and layout options documented by ScreenshotNeo. Cookie and consent banners, newsletter popups and chat widgets are removed before the shot; bot checks, blank pages and failed loads are never billed. Response headers report the page verdict and whether the request was billed. An MCP server lets AI agents use take_screenshot, get_page_info and capture_pdf. The Free plan includes 1,000 screenshots per month with no card, and paid plans start at $5 for 3,000.
Create a free ScreenshotNeo account to try the PDF capture.
FAQ
Does Jekyll convert Markdown directly to PDF?
No. Jekyll first renders Markdown and front matter into HTML. Prince, wkhtmltopdf or a plugin then converts that HTML to PDF.
How do I make TOC entries clickable?
Generate entries from heading anchors or the documentation sidebar, then verify the links in a PDF viewer. For a single page, use kramdown’s * TOC and {:toc} markers.
Should I use Prince or wkhtmltopdf?
Use Prince when print CSS, page references and documentation-theme integration are priorities. Use wkhtmltopdf when its open-source command-line controls and existing plugin integration fit your project.
Why must I build an HTML target first?
The converter needs resolved HTML, styles and assets. Building first exposes broken permalinks and missing files before PDF generation.


