Skip to content

MDX slides

A deck is one MDX file. MDX is Markdown that can hold JSX, so everything Markdown does works, and any component the engine ships — or that you write — can sit between paragraphs.

---
title: My talk
theme: minimal
---
# The first slide
---
## The second slide, one column to the right
---
### A vertical slide, below the second
  • --- starts a new slide, one column to the right.
  • ---- starts a vertical slide beneath the previous one (reveal.js’s vertical stacks). Arrow keys walk the steps first, then the column; ↓/↑ move within a stack.

The YAML block at the very top is the headmatter: deck settings (title, author, theme, transition, slideNumber, defaultTiming, …) and, at the same time, the frontmatter of the first slide. deck.config.ts overrides the headmatter, which overrides the defaults; every option is in the configuration reference.

YAML between two --- separators is that slide’s frontmatter:

---
layout: two-cols
background: aurora
transition: fade
class: hero
---

Per-slide keys:

Key Meaning
layout the slide’s layout (below); the first slide defaults to cover, the rest to default
class CSS classes on the slide (a string or a list)
background a colour, a gradient, an image, a video, an iframe, or a background component — see Themes and backgrounds
transition, transitionSpeed, backgroundTransition override the deck’s transition for this slide
colorScheme dark or light: force tokens on this slide (a dark background under a light theme)
clicks the slide’s total steps, when it can’t be counted from its content
clicksStart the step the slide opens at
autoAnimate, autoAnimateId, autoAnimateRestart animate matching elements between consecutive slides
autoSlide milliseconds before this slide advances on its own
timing seconds this slide should take, for the pacing timer
hide leave the slide out of the deck (visibility: hidden does the same; visibility: uncounted keeps it but skips it in numbering)
hideInToc leave it out of <Toc>
zoom scale the slide’s content
state names added to the deck while this slide is shown
preload false to load the slide only when reached
poster, posterUrl, posterWait the stand-in image for an embedded page — see Export
terms false, or { skip: [...] }, for glossary linking on this slide

default, center, cover, intro, section, end, fact, quote, statement, full, none, two-cols, image, image-left, image-right, iframe, iframe-left, iframe-right.

Layouts with more than one region take slots. A line ::name:: starts the slot called name:

---
layout: two-cols
---
# Left column
The default slot.
::right::
# Right column

Register your own layouts in src/components.tsx with a layout: prefix — "layout:agenda": Agenda — and use them as layout: agenda.

<Notes>Start with the poll. [click] Then reveal the first point. [click] And the second.</Notes>

The presenter view splits notes at [click]: segment N is highlighted exactly when the slide is at step N, so the notes keep pace with your clicks. Notes are compiled to their own module and never load on the audience’s screens unless you share them.

Anything exported from src/components.tsx is available in deck.mdx without an import:

src/components.tsx
export const components = {
Price: ({ amount }: { amount: number }) => <strong className="price">${amount}</strong>,
};
It costs <Price amount={4} /> a month.

Cards that share a row share a height: a <Glass> or <Callout> that is the only thing in its <Col> fills the cell, unless the row says align="start". Give your own card component the deck-card class to join in.

Group Components
Layout Cols/Col, Grid, Absolute, Transform, FitText
Content Callout (kind="info" | "tip" | "warn" | "danger" | "note"), Badge, Kbd, Mark, Arrow, Toc, Qr
Motion Counter, Typewriter, Encrypted, FlipBoard, Motion, Confetti, Timer
Media image preview (click to enlarge), Youtube, Tweet, Iframe
Bling GradientText, Glass, Glow, Chip, Icon (any Lucide icon), Divider, Ribbon, Halo, Shimmer, Blob, Tilt
Live QrJoin, Presence, Reactions, Poll, WordCloud, Quiz, Leaderboard, Questions, Pace — see The live room

Bling components read the theme’s tokens and take a tone: accent, accent-2, good, warn, bad, info, neutral, purple, pink, amber, teal.

layout: iframe* and <Iframe> load a page when its slide shows and unload it when you leave. A “click to interact” shield keeps your keys driving the deck until you mean to use the page; Done hands the keyboard back. The next slide’s pages are already loading, hidden, so arriving there looks instant. <Iframe scale={0.5}> renders a page at twice the pane and shrinks it — a desktop layout in a small card.

The stage is authored at 1920 × 1080 (width/height) and scaled uniformly to every window: edge to edge on a 16:9 screen, centred between bars on a phone, a tall window or a 4:3 projector — never reflowed. A slide whose content overflows is scaled down to fit (autoFit, on by default).