Release Notes v0.2.0
Released: 2026-09-01
Prezzer grows from a deck renderer into a full presentation workflow: author slides in Markdown, run a real presenter console in a second window, export PDFs straight from the browser, and iterate with a proper dev server. The whole toolchain moves to Bun 1.4 with workspace dependency catalogs, and the deck-authoring skill gets a curated reference layer so coding agents can build decks without guessing.
🌟 Highlights
✨ Markdown decks
Author text-heavy slides as .md files and import them directly: import slides from './slides.md' feeds straight into <Deck slides={slides} />. The prezzer/bun-plugin loader parses at build time, renders HTML with Bun.markdown.html, and emits a module that calls markdownSlides() from prezzer/markdown. Slides split on ---, beats split on <!-- beat -->, and frontmatter carries id, title, act, transition, deep, badge, and notes. Dividers and beat markers inside fenced code blocks stay content, never boundaries. Markdown and JSX slides mix freely in the same array.
🎭 Presenter view
Press p to open the same artifact in a second window with ?presenter=1. The two windows sync over postMessage across the window.open pair rather than BroadcastChannel, so it works from file:// with no server. The console shows speaker notes, the next slide title, live previews of current and next slides, a click-to-reset timer, wall clock, and a sync indicator. Every presenter keypress dispatches a remote command back to the audience window, so the presenter is a true remote control and the deck window stays the source of truth.
🖨️ Print mode
Add ?print to the deck URL and the browser becomes the PDF exporter. Deck detects the query parameter and renders one 16:9 page per slide, each fully revealed at its final beat, with @page rules sized to the 1920×1080 canvas and zero margins. Entrance animations skip globally so nothing prints mid-transition. No import or separate build target: it is the same single HTML file.
⚡ prezzer dev
A real dev server with hot reload, built on Bun 1.4 directory routes. Defaults to http://127.0.0.1:1609 (loopback only), honors BUN_PORT / PORT / NODE_PORT, and walks up to 10 successive ports when the default is busy. Use --port and --host to override; an explicit --port fails fast instead of drifting. public/ is served in dev with ETag, 304, and Range support, plus symlink and traversal guards.
🤖 Agent-ready deck authoring
skills/prezzer/SKILL.md now sits on top of eight curated reference documents: api.md, authoring.md, chrome.md, markdown.md, motion.md, theming.md, verification.md, and widgets.md. The README gained an agent fast path, and AGENTS.md (symlinked as CLAUDE.md) documents the invariants that break silently, like the per-package bunfig.toml mirror every workspace member with tests needs.
✨ Engine
- Help overlay:
?opens anaria-modaldialog documenting the full key vocabulary: space/→/pgdn to advance,←/pgup to step back, shift to skip whole slides,1to9to jump, home/end for first/last,ggrid,nnotes,ffullscreen,ddeny mode,aautoplay,ppresenter,escto close. - Exclusive modals:
useKeyboardShortcutstakes amodalOpenflag. While an overlay owns the screen, deck keys are swallowed so a stray space cannot advance the deck behind a dialog. Onlyesc,g, and?pass through, so overlays can close or swap. - Beat audit:
BeatAuditplus theuseBeatAudithook wired intoBeatwarn when a mounted<Beat at={n}>exceeds the slide's declaredbeats, naming the slide and the count it should declare. Catches reveals that can never fire. - Grid overview keyboard navigation: arrow keys move between cards with row math derived from the live
auto-fitlayout, digit typeahead builds a slide number with a visible hint,enterjumps,goresccloses. Cards carryaria-current="page"and the dialog has a screen-reader-only heading. StaticDeckProvider: a frozen deck context with no-op navigation, exported fromprezzeralongsideDeckContextandDeckContextValue. It backs presenter previews and print pages, and is the composition surface for shells that source state outsideDeckProvider.hashSyncprop:DeckProvideracceptshashSync={false}to stop mirroring position intolocation.hashwhen embedding a deck in a host page.- Interactive element passthrough: links, buttons, form controls, media, and anything marked
data-prezzer-interactivekeep their own keyboard events instead of losing them to deck navigation. - History-safe deep links: position mirrors into
location.hashviahistory.replaceState, so presenting a long deck no longer buries the Back button under one history entry per beat, and a hand-typed hash that clamps rewrites to the position actually shown. Touch navigation ignores pinch gestures and pauses under open overlays, and fullscreen state reads throughuseSyncExternalStore.
🎨 Theme and chrome
withAlpha(color, alpha): new export fromprezzer/themethat derives translucent colors withcolor-mix(in srgb, ...). The old approach appended hex suffixes like${color}88, which silently broke on anything that was not a 6-digit hex. Chrome overlays now tint from the active theme instead of hardcoded values.- Display fonts: the scaffold template actually loads the SilkCircuit display faces now, and the demo deck self-hosts Clash Display, Satoshi, and Geist Mono so its offline claim holds.
SlideDef.badgetyped asRolloutStatus | (string & {}), giving autocomplete forGA,IN FLIGHT,COMING SOON,DEV ONLY, andNOT ROLLED OUTwhile still accepting any string.
🔧 CLI and build
- Trustworthy asset inlining: the bake matches
public/assets against literal paths in the output (including URL-encoded forms), replaces longest-token-first so/a.pngcannot corrupt/a.png.license, and consumes query strings rather than appending them to the data URI. - Honest warnings: the build warns when a
public/asset never appears literally in the output ("runtime-built paths break offline") and when the artifact still references remote stylesheets, scripts, or fonts. Hidden files and bundler-resolved imports are excluded, so the warning means something. - Build output: completion now reports the artifact path, size, duration, and whether it is truly offline:
✓ dist/index.html · 45.2 KB · 1.23s · one file, works offline. Colors are gated onBun.enableANSIColorsso piped output stays clean. --no-minifyonbuildfor readable output while diagnosing a bake;--outdirstill defaults todistwith guards against escaping the project or clobbering the deck entry.prezzer --version(also-vandversion) prints the engine version.
📝 Examples and docs
- Demo deck:
examples/demois Prezzer presenting itself, deployed to GitHub Pages by the new.github/workflows/pages.yml. Fonts are self-hosted underexamples/demo/public/fonts. - README rebuilt around the feature set, quick start, and the agent fast path, with screenshots of the hello deck in
docs/images/. - Several passes of adversarial and cross-model verification corrected claims in the README, the skill, and the audit docs so the documentation matches the shipped behavior, including hash indexing and act grouping.
👷 Toolchain
- Bun 1.4 is now the floor (
engines,packageManager, and every CI workflow pinned to1.4.0). - Dependency catalogs: the root
package.jsondeclares acatalogblock and every workspace member references"catalog:", so React, Motion, Tailwind, and TypeScript versions move in one place. - Isolated linker:
bunfig.tomlpins[install] linker = "isolated"for strict dependency isolation and faster warm installs. - Motion 13 with happy-dom 20 in tests.
test/setup.tssetsMotionGlobalConfig.skipAnimations = true, cutting the suite from roughly 20s to under a second and removing flakyAbortErrorrejections. - New tests cover the dev CLI, the markdown loader, print rendering, presenter sync, and publish manifests.
.editorconfig,.vscode/extensions.json, and aligned Biome and TypeScript configs round out the contributor setup.
🔥 Breaking changes
- Bun 1.4 required. Anything below
1.4.0will not install or build. Update local toolchains and CI images. - Five motion exports removed from
prezzer:slideTransitions,slideVariants,typewriter,toolBurst, andtoolStaggerContainer. These were fossils from the deck Prezzer was extracted from and had no replacements. Pick transitions per slide via thetransitionfield onSlideDef, and build custom variants in your own deck. - Hex-suffix alpha is gone from theme helpers. If you copied the
${color}40pattern out of engine internals, switch towithAlpha(color, 0.25).
📦 Upgrade notes
- Install Bun 1.4 or later, then reinstall:
bun install. The isolated linker changesnode_moduleslayout, so remove it first if the install behaves oddly. - Search your deck for
slideTransitions,slideVariants,typewriter,toolBurst, andtoolStaggerContainerand replace them before upgrading. - To author in Markdown, add
"prezzer/bun-plugin"topluginsin your deck'sbunfig.tomland declare*.mdinassets.d.tsas a default-exportedSlideDef[]. - If you have a workspace package with tests, mirror the two-line
bunfig.tomlpreload oftest/setup.tsor DOM access will fail. prezzer devbinds to127.0.0.1by default. Pass--host 0.0.0.0if you were relying on network access from another device.- Point coding agents at
skills/prezzer/SKILL.md; it links the reference layer covering the API, authoring, chrome, markdown, motion, theming, widgets, and verification.