Skip to content

Starlight to PDF

Manuscrio reads a finished Astro Starlight build directory and exports it to publication-ready PDF manuals:

Terminal window
manuscrio-pdf inspect ./dist # what manuals does this site contain?
manuscrio-pdf export ./dist # one manual for the documentation edition

Both commands run end to end in a public example repository: Working Starlight integration on GitHub — manuscrio/starlight-pdf-export.

The framework is detected from the built pages, so the command names no framework at all; --framework starlight skips detection when you are diagnosing an unusual build.

It reads the build, not a URL. That is the operational difference from tools that crawl a served site: Manuscrio runs against a CI artifact, offline, on a build that was never published, with no preview server to start and no port to keep alive.

Three steps after the step that already builds your site. Starlight writes ./dist, and --logo supplies the mark the adapter cannot yet read from a Starlight build:

- run: npm ci && npm run build
- name: Export the docs to PDF
run: |
npx --yes [email protected] export dist \
--logo path/to/your-logo.svg \
--output-dir manuscrio-output
- uses: actions/upload-artifact@v7
with:
name: manual
path: manuscrio-output/*.pdf

Pin the version, as above: one manuscrio version resolves to exactly one image, so re-running an old pipeline renders what it rendered the first time. There is nothing to install in your site and no GitHub Action to add.

The complete workflow is in manuscrio/starlight-pdf-export, and Run in CI has the docker run form for runners without Node.

An edition is one plugin instance, one locale, and one version. Starlight has neither plugin instances nor versions, so those two thirds of the edition ID are the constants default and current. The locale still separates editions — the adapter groups pages by the rendered page’s lang attribute — so a multilingual site produces one edition per language, and a single-language site has exactly one, usually default:en:current.

Starlight’s navigation has no section level, so --scope section does not apply:

ScopeProduces
--scope editionone manual, sidebar roots as its top-level chapters
--scope sidebar-rootone manual per sidebar root
--scope sectionrefused — there is nothing to enumerate

The refusal names the scopes that work rather than failing obscurely:

Edition default:en:current has no documentation sections to export: this Site Build's navigation
has no section level. Use --scope edition for one manual, or --scope sidebar-root for one per
sidebar root.
A chapter opening in a manual exported from a Starlight build
StarlightAstro docs, How-to recipes · malachite · 135 pages

Logo discovery is not yet implemented for Starlight: inspect reports an empty logo, and the manual carries the Manuscrio wordmark unless you supply your own.

Terminal window
manuscrio-pdf export ./dist --logo brand/acme.svg

This is a gap in the adapter rather than a property of Starlight, and it is the one place a Starlight export needs an argument a Docusaurus export does not. See branding.

Starlight has no built-in Mermaid support, so you add a plugin — and the one you pick decides whether your diagrams reach the manual.

  • Rendered at build time (rehype-mermaid and similar) — the diagram is already in your HTML. Nothing to do.
  • Drawn in the browser (astro-mermaid and similar) — your build contains the diagram source, so the manual prints it as text in a code block.

To check which you have, look for the diagram in your built HTML: an <svg> is build-time, Mermaid source is browser-drawn.

For the second case, add --hydrate:

Terminal window
manuscrio-pdf export ./dist --hydrate --output-dir ./manuscrio-output

It is off by default because it runs your site’s own scripts, adds about a second per page, and does not produce byte-identical output between runs. Pages whose scripts fail to load are reported rather than exported without them.

A non-root base is detected automatically. Pass --base-path /docs only if that detection is ever wrong.

Starlight sidebars offer no stable identifier for a root, so Manuscrio numbers them by position — set-0-1, root-2. Those IDs shift when an entry is inserted above them, so read them from inspect at run time rather than pinning them in a pipeline. See manual IDs and output file names.

For Starlight, every sidebar appears under unassignedDocumentationSets and assignedPages reads 0. Those fields describe attribution to a navbar section, and Starlight has none — so nothing is wrong and nothing is excluded. The edition exports in full. The wording is Docusaurus-shaped and will improve.

Run the two commands at the top of this page against your own ./dist. Nothing is uploaded and there is no account: without a licence the export is still the complete manual at production rendering quality, with no page limit, carrying an evaluation watermark until a licence removes it.