Skip to content
Deckard
Esc
navigateopen⌘Jpreview
On this page

Requirements and compatibility

The Node, Next, React, and Tailwind versions a deck needs, which package managers work, what a presented deck asks of the browser, and which commands need Chromium.

A deck is a Next.js app with @thebuilder/deckard-core as a dependency. Everything below is what that app needs.

Versions

What Version Where it comes from
Node 20.9 or newer engines on all three packages, and the floor deckard doctor checks
Next.js 16 or newer peerDependencies on @thebuilder/deckard-core
React 19 or newer peerDependencies on @thebuilder/deckard-core
React DOM 19 or newer peerDependencies on @thebuilder/deckard-core
Tailwind CSS 4 @thebuilder/deckard-core/styles.css uses @source, which is v4 only

deckard init pins the versions the reference deck runs rather than the floors, so a deck generated today installs Next 16.3.3, React ^19.2.8, Tailwind ^4.3.3, and TypeScript ^7.0.2.

Tailwind is not a declared peer dependency of any Deckard package. The requirement arrives through the one stylesheet import:

@import "tailwindcss";
@import "@thebuilder/deckard-core/styles.css";

That second line carries the --slide-* tokens and registers the runtime’s own Tailwind source. Drop it and the deck renders unstyled. deckard doctor checks for it by name.

Package managers

bun, npm, pnpm, and yarn all work. Pass --package-manager <name> to deckard init, or let it use the one that invoked it.

A generated deck carries no packageManager field. Corepack reads that field as an enforcement lock, so writing it would refuse every other manager afterwards. Later deckard commands read the lockfile instead, walking up from the deck directory: pnpm-lock.yaml, bun.lock, bun.lockb, yarn.lock, package-lock.json.

That detection is what fills in the commands the CLI prints. A missing Chromium tells a pnpm deck to run pnpm exec playwright install chromium and an npm deck to run npm exec -- playwright install chromium.

init is covered by an automated smoke test on pnpm and npm. Yarn and bun are supported in the code and are not covered by that test.

Chromium

Four commands drive a real browser, so they need the Playwright Chromium binary on the machine:

Playwright and pdf-lib are dev dependencies of the deck, not of the CLI. deckard init writes both into the generated package.json, and the four commands above load them from the deck’s own node_modules. A deck built by hand adds them itself:

pnpm add -D playwright pdf-lib

The browser binary is a separate download on top of the package:

pnpm exec playwright install chromium

Without the package those four commands fail naming it and printing the install line; without the binary they fail with Failed to launch Chromium and the download line for your package manager. deckard doctor reports both packages under tooling. Nothing else in the CLI needs a browser: init, validate, doctor, add, and eject do not, and npx @thebuilder/deckard-cli init downloads neither.

check-overflow, screenshots, and export pdf also run next build and next start before they capture, so they need a machine that can build and serve the deck. contact-sheet needs the browser but neither the build nor the server, because it composes PNGs that screenshots already wrote.

Browsers for a presented deck

The runtime is tested on Chromium, Firefox, and WebKit. Those three are what pnpm test runs the browser suite against, and they are the closest thing to a support matrix the repository states.

There is no browserslist in the repository and no configured build target, so the shipped bundle takes Next 16’s defaults. That means there is no minimum browser version to quote here.

What the deck uses that a browser has to support:

  • oklch() colours and color-mix(), in the token contract and every theme
  • Tailwind v4 cascade layers
  • svh units for the shell height
  • ResizeObserver, for measuring the canvas fit
  • BroadcastChannel, for presenter sync
  • The inert attribute, on unrevealed step content

ResizeObserver is used without a fallback, so a browser without it will not scale the canvas. BroadcastChannel is checked before use: a browser without it runs the deck normally and the presenter window never syncs.

The canvas scale is measured in JavaScript and published as --deckard-scale rather than divided in CSS, because Firefox before 155 has no typed CSS arithmetic. That is the one engine difference the runtime works around by design.

Edge runtime

Not established, and nothing in the repository claims it either way. There is no export const runtime anywhere, no middleware, and no test that runs a deck on Edge.

What is true: the route adapters in @thebuilder/deckard-core/next import no Node APIs, and the slide route reads nothing from the request. @thebuilder/deckard-core/code-block is the part to check first if you try it, because shiki loads a WebAssembly regex engine there.

Treat Edge as untested rather than as supported or unsupported.

Static export

output: "export" works, with two changes to the app.

Force the sitemap static

Without this the build fails with export const dynamic = "force-static"/export const revalidate not configured on route "/sitemap.xml" with "output: export".

import { createDeckSitemap } from "@thebuilder/deckard-core/next"
import { deck } from "@/deck/deck"

export const dynamic = "force-static"

export default createDeckSitemap(deck)

Turn off image optimization

The media blocks use next/image. Left alone, the export emits /_next/image?... URLs, which need the optimizer a static host does not run, so every image 404s.

const nextConfig: NextConfig = {
  images: { unoptimized: true },
  output: "export",
}

Every slide, the presenter page, and the sitemap prerender. One thing changes: / becomes a page that redirects to the first slide once it loads in the browser, rather than a server 307.

The capture commands do not work against a static export. They run next start, which output: "export" disables. Build twice, or run the captures before you switch the config.

Deploying covers the rest of getting a built deck in front of an audience.

Was this page helpful?