Skip to content
Deckard
Esc
navigateopen⌘Jpreview
On this page

Exporting

PDF handouts, per-slide screenshots, and the contact sheet. All three run the deck in a browser at canvas scale.

PDF export and screenshots build the app, serve it on a spare port, and open a browser at canvas scale. The contact-sheet command arranges screenshots that already exist.

PDF

pnpm exec playwright install chromium
deckard export pdf

One page per slide at the deck’s canvas size, captured from the canvas element. 1920x1080 becomes 1440x810pt, which is the same thing at 96dpi. The page size comes from the canvas config in deck/deck.ts, the same config the deck renders with.

Output lands at out/slides.pdf in the deck’s own directory.

Flag Default What it does
--dark off, so the export is light Export the dark deck instead.
--skip-build off Reuse whatever is in .next.
--port <n> 3410, or PDF_EXPORT_PORT Move the temporary server off a busy port.

Pass --dark when the PDF is for a screen rather than for print.

In export mode the build runs with NEXT_PUBLIC_PDF_EXPORT=1, which:

  • disables animations and transitions
  • drops the deck controls
  • keeps the deck header and footer, exactly as each slide’s own modes say

Set PDF_EXPORT_OUTPUT to write somewhere other than out/slides.pdf. It resolves against the deck directory.

Screenshots

deckard screenshots
deckard screenshots --light --max 5

One PNG per slide at canvas size, written to out/screenshots/<id>.png, plus a manifest.json recording the canvas size, the color mode, and every slide’s file, id, number, and title.

Flag Default What it does
--light off, so dark Capture light mode.
--max <n> all Stop after n slides.
--skip-build off Reuse whatever is in .next.
--port <n> 3411 Move the temporary server off a busy port.

The directory is wiped and recreated on each run, so the manifest and the PNGs never disagree.

Every capture asserts the applied color mode matches the one requested, and throws naming the slide rather than writing a mislabelled PNG. A theme that pins itself to dark still shoots light when you ask, because the harness seeds the color-mode storage key before the page loads.

Contact sheet

deckard screenshots
deckard contact-sheet --columns 5

Composes the existing screenshots into out/contact-sheet.png, a labelled grid of the whole deck. It does not build or serve anything; it reads out/screenshots/manifest.json and fails telling you to run the screenshots first if that file is missing. The color mode comes from the manifest.

--columns <n> sets the grid width and defaults to 4.

Three slides in a row that all end above the halfway line, or the same numbered list twice back to back, are invisible one slide at a time and obvious in a grid.

Build reuse

The screenshot, overflow, and PDF commands share one harness. It stamps .next/deckard-build.json after a build and compares that timestamp against the newest file under app/, assets/, components/, deck/, hooks/, lib/, and public/, plus components.json, next.config.*, package.json, postcss.config.*, tsconfig.json, and the resolved @thebuilder/deckard-core and its src/. A stale stamp triggers next build.

--skip-build reuses whatever is there regardless. --port <n> moves off the default when something else has the port; the harness refuses to start if anything already answers on it.

Slide discovery

The harness reads slide ids from the app’s own /sitemap.xml, which is app/sitemap.ts re-exporting createDeckSitemap(deck). Export and screenshots stay aligned with your published slide paths, and an app that dropped that route gets an error naming it.

Was this page helpful?