Skip to content
Deckard
Esc
navigateopen⌘Jpreview
On this page

Deck config

Every field defineDeck accepts, what it resolves them into, and the markup the deck header and footer render inside the canvas.

defineDeck takes a DeckConfig and returns a resolved Deck. It resolves the canvas, resolves every slide into an id, a number, a URL and its chrome defaults, and validates the theme.

import { defineDeck } from "@thebuilder/deckard-core"
import { meridian } from "@thebuilder/deckard-themes"
import { slides } from "@/deck/slides"

export const deck = defineDeck({
  canvas: { fit: "contain", height: 1080, mode: "fixed", width: 1920 },
  description: "An engineering review built from editable slide patterns.",
  footer: { mode: "visible" },
  header: { brand: "Deckard", href: "/", meta: "March 2026", mode: "auto" },
  slides,
  theme: meridian,
  title: "Deckard",
})

DeckConfig

PropType
titlestring

The deck title. Used as the document title and in slide metadata.

Typestring
descriptionstring

One line describing the deck.

Typestring
slidesSlideDefinition[]

The deck, in order. Never reordered.

TypeSlideDefinition[]
headerDeckHeaderConfig

The header inside the canvas: brand, link, optional meta line, and the default header mode.

TypeDeckHeaderConfig
footerDeckFooterConfig

The footer inside the canvas: the default footer mode and whether the progress element exists.

TypeDeckFooterConfig
canvas?Partial<DeckCanvasConfig>

Overrides on the fixed coordinate space.

TypePartial<DeckCanvasConfig>
Default1920x1080, fit contain, margin 0
theme?SlideTheme

The theme object. A deck without one renders in neutral defaults.

TypeSlideTheme
motion?"auto" | "frozen"

The default every slide takes. "frozen" holds every motion background in the deck on one fixed frame. Reduced motion, the capture commands, and the presenter preview freeze one either way.

Type"auto" | "frozen"
Default"auto"
routes?DeckRoutesConfig

Route prefixes for slides and presenter mode. Set presenter to false when the deck has no presenter page.

TypeDeckRoutesConfig
Default{ slides: "/slides", presenter: "/presenter" }

canvas

PropType
mode?"fixed"

The only mode.

Type"fixed"
Default"fixed"
width?number

Logical pixels. Has to be positive.

Typenumber
Default1920
height?number

Logical pixels. Has to be positive.

Typenumber
Default1080
fit?"contain"

How the canvas fits the window.

Type"contain"
Default"contain"
margin?number

Browser pixels between the canvas and the window edge. Zero or more.

Typenumber
Default0

resolveCanvas throws naming the field when width or height is not a positive number, or when margin is negative.

PropType
brandstring

The name at the left of the header. Rendered as a link.

Typestring
hrefstring

Where the brand links to.

Typestring
mode"visible" | "hidden" | "auto"

The deck-wide default. A slide can override it.

Type"visible" | "hidden" | "auto"
meta?string

One line of standing detail at the right of the header, printed as written: "March 2026", "Rev. C", "Internal".

Typestring

"auto" renders the header in the default layout and hides it in a fullscreen layout.

PropType
mode"visible" | "hidden" | "counter"

The deck-wide default. A slide can override it.

Type"visible" | "hidden" | "counter"
progress?boolean

Whether the progress element exists at all. Setting false drops the element rather than hiding it, so no theme can paint it back.

Typeboolean
Defaulttrue

"counter" is a deprecated alias for "visible". A deck that sets it resolves to "visible".

footer: { mode: "visible", progress: false }

theme

See Themes for the full object. defineDeck validates it: defaultColorMode: "system" needs both modes in colorModes, and a theme listing one mode pins the canvas to it and hides the light/dark toggle.

routes

routes.slides sets the prefix used by every resolved slide URL and presenter preview. routes.presenter sets the popout destination; false removes the presenter control and keyboard shortcut. Paths start with / and cannot be the site root.

routes: { slides: "/example", presenter: false }

What defineDeck returns

Deck is DeckConfig with canvas, slides, and theme resolved. Each slide becomes a ResolvedSlide:

Field What it holds
id The URL segment: the slug, or the 1-based position.
href The configured slide path followed by the slide id.
index Zero-based position in the array.
number One-based position, what the counter shows.
title The authored title, or the generated Slide 4 fallback.
authoredTitle Set only when the author gave the slide a title. The fallback in title names a slide in chrome but must never render as its own heading.
header footer layout background motion The slide’s own value, or the deck default.
stepCount Defaults to 0.
notes slug sourcePath As authored.
body The slide’s React node.

Only SlideSummary (id, number, title, authoredTitle, href, stepCount) crosses into client components, because it has to survive BroadcastChannel serialization for presenter mode. The rendered slide body crosses only as children.

Deck chrome

The header and footer are painted inside the canvas, so they scale with the deck, print into the PDF, and show up in a presenter preview. The runtime renders the structure and the theme decides the look:

<header data-slide-header>
  <a data-slide-header-brand href="/">Deckard</a>
  <span data-slide-header-title>Themed chrome</span>
  <span data-slide-header-meta>March 2026</span>
</header>

<footer data-slide-footer>
  <div data-slide-progress style="--slide-progress: 0.25"></div>
  <p data-slide-counter>
    <span data-slide-counter-current>3</span>
    <span data-slide-counter-separator> of </span>
    <span data-slide-counter-total>12</span>
  </p>
</footer>

The title renders only for a slide that has one, and the meta line only when the deck sets header.meta. --slide-progress is the position in the deck as a fraction, which is what a theme reads to paint a bar, a row of dots, or nothing at all.

The header row is one line inside a canvas that cannot grow. Every part clips itself rather than running off the edge, and the slide title carries by far the largest shrink factor, so it truncates before the brand loses any of itself. Both overflow checks measure the header and footer alongside the frame, so a deck finds out when its chrome asks for more room than it has.

Was this page helpful?