Skip to content

Chromium setup

Viewing, authoring, and live-presenting a deck need only a normal browser. A few build-time features render slides headlessly, and those need a real Chromium binary. Chromium is optional: if you never use those features, you never need it.

FeatureCommand / APIWithout Chromium
Slide thumbnails (overview grid)liebstoeckel build, liebstoeckel live, buildDeck()Skips the capture and keeps building. The deck works; the overview grid falls back to a live render.
Regenerate thumbnailsliebstoeckel thumbsFails with an error.
Export to PNG or PDFliebstoeckel exportFails with an error.

The split is deliberate. build and live treat thumbnails as a best-effort enhancement, so a missing browser never blocks a build. thumbs and export exist only to produce that output, so they fail loudly instead of writing nothing.

liebstoeckel doctor reports your build environment (Bun version, whether a Chromium was found, and where its path is recorded):

Terminal window
liebstoeckel doctor # human summary; --json for the machine-readable form

If a Chrome or Chromium is already on the machine, liebstoeckel usually finds it on its own (see Resolution order), you may not need to do anything.

If doctor reports none, any of these works.

Let liebstoeckel install and remember Playwright’s Chromium for you:

Terminal window
liebstoeckel doctor --install-chromium # installs, then records the path in your config

Or install it yourself (liebstoeckel ships playwright-core, which has no browser of its own):

Terminal window
bunx playwright install chromium

Or point LIEBSTOECKEL_CHROMIUM at a Chrome or Chromium you already have:

Terminal window
export LIEBSTOECKEL_CHROMIUM=/usr/bin/chromium # or a full path to Chrome
liebstoeckel build my-talk

When a feature needs a browser, liebstoeckel looks in this order and uses the first binary that exists on disk:

  1. An explicit executablePath passed to the thumbnails/export API.
  2. The LIEBSTOECKEL_CHROMIUM environment variable — including the path doctor records in your config (~/.config/liebstoeckel/config.json), which the CLI loads into this variable when you haven’t set it yourself. Surrounding quotes and whitespace are stripped (a common artifact of set VAR="C:\..." on Windows), and a configured path that doesn’t exist prints a warning before falling back to auto-detection.
  3. A system Chrome/Chromium: PUPPETEER_EXECUTABLE_PATH / CHROME_PATH, Puppeteer’s install cache, google-chrome / chromium / chromium-browser / chrome on PATH, the standard macOS and Windows install locations (including per-user installs and 32-bit/64-bit Program Files variants), and on Windows the registry’s App Paths entry, which finds Chrome wherever the installer put it.
  4. On Windows, Microsoft Edge as a last resort — it is preinstalled everywhere and uses the same engine, so capture output is identical.
  5. The Chromium installed by Playwright.

The existence check matters: Playwright reports a computed path even when nothing is installed, so liebstoeckel verifies the file is really there before trusting it. This keeps the “no Chromium” path honest in CI. When nothing is found, liebstoeckel doctor lists every location it probed.

On Linux and macOS the browser launches headless with container-friendly flags (--no-sandbox --disable-gpu --disable-dev-shm-usage --renderer-process-limit=1), chosen so capture works in sandboxes and CI without a GPU or user namespaces; Windows uses the stock process model. The GPU thread deliberately stays in its own process: on machines where software GL cannot initialize, an in-browser GPU thread would crash the browser, while a separate GPU process falls back to software compositing. If a Chrome update or an unusual environment makes those defaults crash, the LIEBSTOECKEL_CHROMIUM_ARGS environment variable replaces the whole list (whitespace-separated), so you can also remove a default flag, not just add:

Terminal window
export LIEBSTOECKEL_CHROMIUM_ARGS="--no-sandbox --disable-gpu --disable-dev-shm-usage"

Capture launches Chromium with container-friendly flags so it runs without a GPU or user namespace (see Launch flags above for the list and the LIEBSTOECKEL_CHROMIUM_ARGS override).

In a container image, either run bunx playwright install chromium during the build, or install your distro’s Chromium package and set LIEBSTOECKEL_CHROMIUM to it.

On Windows, liebstoeckel drives the browser over the Chrome DevTools Protocol directly (it launches Chrome with a DevTools port and connects with a native WebSocket) instead of Playwright’s usual transports, which do not work under Bun on Windows. This is automatic and produces identical output. Setting LIEBSTOECKEL_CDP_DRIVER=1 forces the same transport on any platform, useful when debugging capture issues.

The “no Chromium found” message is expected if you never installed one. What follows depends on the command:

  • liebstoeckel build and liebstoeckel live log a note that thumbnails were skipped and finish normally. Run liebstoeckel doctor --install-chromium (or provide a browser as above) to get the overview thumbnails back.
  • liebstoeckel thumbs and liebstoeckel export stop with an error that names the fixes (liebstoeckel doctor --install-chromium, or set LIEBSTOECKEL_CHROMIUM).

To build without thumbnails even when a browser is present, set LIEBSTOECKEL_NO_THUMBS:

Terminal window
LIEBSTOECKEL_NO_THUMBS=1 liebstoeckel build my-talk

Comments

liebstoeckel

Code-first presentations your agent can author. One file out, no server.

© 2026 Leon Kaucher