deckzero is an opinionated, CSS-first design system for Reveal.js-style presentations.
It provides:
- a minimal token layer
- a small set of slide layout primitives
- bundled themes plus themeable typography and surface tokens
- a tiny runtime that reads slide hints and applies auto-layout heuristics
- a markdown-first demo workflow that compiles to standard HTML
dist/deckzero.css: base tokens, rhythm, and primitive stylingdist/deckzero.js: authoring hint parser and slide hydratordist/themes/light.css: light theme token overridedist/themes/hulk.css: hulk theme token overridesrc/compiler/: markdown compiler and demo build helpersdemo/src/: canonical markdown demo sourcedemo/vendor/: vendored Reveal runtime assets used during demo buildsdemo/dist/: generated browser-runnable demo deck
deckzero can be consumed as a package directly from its repository.
Example:
{
"dependencies": {
"deckzero": "github:nvictor/deckzero"
}
}Exposed package entry points:
deckzerodeckzero/compilerdeckzero/deckzero.cssdeckzero/deckzero.jsdeckzero/themes/light.cssdeckzero/themes/hulk.css
deckzero remains HTML-based at runtime, but the recommended authoring flow is markdown-first.
The compiler turns markdown into normal Reveal-style <section> markup, and the browser only consumes the generated HTML.
Recommended workflow:
- Edit
demo/src/deck.md. - Preserve
deckzerohints as HTML comments. - Run
npm run build. - Open
demo/dist/index.html.
Use HTML comments inside a slide section:
<!-- layout: split:text-image -->
<!-- accent: warning -->Supported layout hints:
titlestatementsplit:text-textsplit:text-imagesplit:image-textsplit:image-imagesplit:text-image:verticalcode-focusimage-captionstep
These map onto the core layout primitives: title, statement, split, code-focus, image-caption, and step.
Supported pane surface hints:
<!-- pane-surface: none -->Removes the pane background fill for split layouts while keeping spacing and sizing.
Deck-wide branding can be configured on the .reveal root:
<div
class="reveal"
data-dz-brand-src="assets/media/logo.svg"
data-dz-brand-style="tag"
data-dz-brand-position="bottom-left"
data-dz-brand-alt="Acme"
>data-dz-brand-src: image URL for the brand assetdata-dz-brand-style:logoortagdata-dz-brand-position:top-left,top-right,bottom-left, orbottom-rightdata-dz-brand-alt: optional accessible label for the image
Brandmark sizing and inset are controlled by tokens in deckzero.css:
:root {
--dz-brand-inset: clamp(1.5rem, 2.8vw, 2.25rem);
--dz-brand-width: min(28vw, 15rem);
--dz-brand-height: min(18vh, 8.5rem);
}logo mode renders the asset directly. tag mode wraps it in a rounded, bordered treatment for badge-style branding.
For split layouts, use two major content blocks. A common pattern is:
<!-- layout: split:text-image -->
## How It Works
<div>
<p>Explain the idea.</p>
<ul>
<li>One</li>
<li>Two</li>
</ul>
</div>
<div>
<img src="assets/media/default.svg" alt="Preview" />
</div>If a split slide omits heading or intro blocks and starts directly with the two panes, deckzero treats it as a full-canvas split and lets the panes occupy the full slide height.
If there is no explicit layout hint, deckzero applies simple heuristics:
- heading + paragraph => statement
- code block => code focus
- image + short caption => image caption
- fragments => step
- two top-level content blocks => split text-text
Alongside the slide layouts, deckzero also provides low-level styling primitives for repeated within-slide structures.
Use .dz-card-grid for repeated card collections:
<div class="dz-card-grid" data-dz-columns="3">
<div class="dz-card">
<strong>One</strong>
<small>Shared shell styling.</small>
</div>
</div>Supported column hints:
data-dz-columns="2"data-dz-columns="3"data-dz-columns="4"data-dz-columns="5"- omit the attribute for auto-fit card wrapping
Use .dz-card for bordered, compact panel content that repeats across a slide.
The shell provides shared padding, radius, surface treatment, and heading rhythm so deck-local CSS does not need to recreate the same panel pattern.
Use tone classes to map local meaning onto generic visual treatments:
.dz-tone-neutral.dz-tone-info.dz-tone-success.dz-tone-warning.dz-tone-danger
These work on .dz-card and .dz-sequence-node.
Use .dz-sequence and .dz-sequence-node for ordered journeys, reasoning chains, or staged workflows:
<div class="dz-sequence" data-dz-columns="4">
<article class="dz-sequence-node dz-tone-warning">
<span class="dz-step-badge">3</span>
<strong>Decide</strong>
<small>Pick the next branch.</small>
</article>
</div>sequence is intentionally generic enough to cover step chips, numbered paths, and investigation flows without shipping domain-specific class names.
The compiler intentionally allows raw HTML blocks inside markdown for cases where structured slide markup is clearer than inventing a second hint language, especially split panes and custom controls.
Current demo layout:
- source markdown:
demo/src/deck.md - source media:
demo/src/assets/media/ - vendored Reveal assets:
demo/vendor/reveal/ - generated output:
demo/dist/
Compiler code lives in src/compiler/, while scripts/ only provides thin command-line entry points.
Theme files should primarily override tokens, while deckzero.css keeps the shared layout system. Bundled themes may also include small, theme-scoped surface overrides for panes and code blocks.
Theme selection example:
<div class="reveal" data-dz-theme="light">If you want to switch between bundled themes at runtime, load the optional theme stylesheets you plan to toggle to. The dark theme is already covered by the base tokens in deckzero.css.
<link rel="stylesheet" href="assets/deckzero/deckzero.css" />
<link rel="stylesheet" href="assets/deckzero/themes/light.css" />
<link rel="stylesheet" href="assets/deckzero/themes/hulk.css" />
<script src="assets/deckzero/deckzero.js"></script>The base stylesheet exposes extra themeable typography tokens:
:root {
--dz-heading: var(--dz-fg);
--dz-emphasis: var(--dz-fg);
}Themes can point those at --dz-accent when they want headings and inline emphasis to share the accent color.
The bundled themes currently use those tokens like this:
dark: headings and emphasis inherit the dark foregroundlight: headings and emphasis inherit the light foregroundhulk: headings and emphasis use the hulk accent#16b61b
- Create or update
assets/deckzero/themes/<theme>.csswith your custom token overrides. - Adjust branding-oriented tokens such as accent color, heading color, emphasis color, text color, background color, muted color,
--dz-font-sans, and--dz-font-mono. - Add scoped surface overrides only when the default pane or code treatments do not fit the theme.
- Update
index.html:- Link to
assets/deckzero/themes/<theme>.css. - Set the default
.revealcontainer todata-dz-theme="<theme>". - Add a theme toggle control that can switch between the bundled themes and
<theme>.
- Link to
- Start from
lightif you want a bright theme, or from the base dark tokens indeckzero.cssif you want a darker direction.
Example theme file:
.reveal[data-dz-theme="<theme>"],
[data-dz-theme="<theme>"] .reveal {
--dz-bg: #f8fafc;
--dz-fg: #0f172a;
--dz-accent: #f97316;
--dz-muted: #94a3b8;
--dz-heading: var(--dz-accent);
--dz-emphasis: var(--dz-accent);
--dz-font-sans: "Avenir Next", "Segoe UI", sans-serif;
--dz-font-mono: "JetBrains Mono", ui-monospace, monospace;
}If you want a custom theme that behaves like hulk, start from the light-theme palette, point headings and inline emphasis at your accent, swap in your fonts, and set a default brandmark position on the .reveal root.
Example CSS:
.reveal[data-dz-theme="gamma"],
[data-dz-theme="gamma"] .reveal {
--dz-bg: #f8fafc;
--dz-fg: #0f172a;
--dz-accent: #7c3aed;
--dz-muted: #64748b;
--dz-heading: var(--dz-accent);
--dz-emphasis: var(--dz-accent);
--dz-font-sans: "Avenir Next", "Segoe UI", sans-serif;
--dz-font-mono: "JetBrains Mono", ui-monospace, monospace;
--dz-panel: rgba(255, 255, 255, 0.9);
--dz-panel-muted: rgba(241, 245, 249, 0.9);
--dz-shadow: 0 24px 80px rgba(15, 23, 42, 0.12);
}Example HTML defaults:
<div
class="reveal"
data-dz-theme="gamma"
data-dz-brand-src="assets/media/logo.svg"
data-dz-brand-style="tag"
data-dz-brand-position="bottom-left"
data-dz-brand-alt="Gamma"
>That setup gives you:
- a light-theme foundation
- accent-colored headers plus
b,strong, andem - custom sans and mono fonts
- a default brandmark placement without changing runtime code
Bundled themes now include:
dark(default base tokens indeckzero.css)lighthulkwith light-theme foundations and accent#16b61b
The generated demo at demo/dist/index.html still defaults to dark; light and hulk are available via the theme toggle.
The browser bundle exposes window.Deckzero with:
apply(root)parseBrandPosition(value)parseBrandStyle(value)parseLayoutHint(value)inferLayout(section)
The runtime auto-applies itself on DOMContentLoaded, and again on Reveal's ready and slidechanged events when Reveal is present.
- `npm run build`: compile `demo/src/deck.md` into `demo/dist/index.html`, then sync runtime assets
- `npm run sync`: copy `dist/` into `demo/dist/assets/deckzero`
- `npm test`: run runtime and compiler tests
The demo output includes vendored Reveal runtime assets plus local media, so users do not need to download anything before opening it.
To rebuild the demo:
- `npm run build`
To load the demo:
- Browser: open
demo/dist/index.html - GrandReveal: click
Open Deckand choosedeckzero/demo/distordeckzero/demo/dist/index.html