Back to projects
WebSource available

Case study

Reveal Decks

A local-first TypeScript workspace for authoring, organizing, presenting, and reliably printing independent reveal.js decks.

Reveal Decks library showing presentation cards, search, tag filters, and the new-deck command

Project overview

Category
Web

Technology

  • TypeScript
  • Vite
  • reveal.js
  • Vitest
  • GitHub

Project links

Inside the project

Context

Presentation repositories tend to become a collection of disconnected HTML files with repeated setup and no useful overview. I built Reveal Decks as a single source-controlled workspace where every presentation owns its slides, theme, and assets while remaining easy to discover, launch, and export from a shared library.

Role

I designed and built the product end to end: the authoring convention, typed deck contract, Vite-based discovery, searchable library, deck generator, validation layer, print pipeline, documentation, tests, and release workflow.

Constraints

The application had to remain static and local-first, with no database or backend. Deck styles needed to stay isolated, local assets had to survive production fingerprinting, and routing had to work under a GitHub Pages repository subpath. Authors also needed to retain direct access to reveal.js HTML instead of learning a custom slide format.

PDF export introduced a different browser constraint. Large Eraser diagrams were hybrid SVG files containing dense vector content and embedded raster data. They remained smooth during a live presentation, but passing repeated copies directly to Chromium's PDF renderer produced slow, unstable documents. Several slides also reused one source diagram with different CSS zoom and clipping states, so replacing the source file with one generic bitmap would have changed the story.

Approach

Vite discovers deck definitions with `import.meta.glob`, then a typed contract and runtime validation turn them into a reliable catalogue. Each deck lives in its own folder, and a guarded `pnpm create:deck` command generates its metadata, slides, theme, and cover from a kebab-case slug. The library adds search and tag filters, while deck controls cover keyboard, touch, fullscreen, and reduced-motion use. Heavy reveal.js core, notes, and syntax-highlighting modules are loaded only when a presentation opens.

The print route waits for the theme, images, fonts, and reveal.js `pdf-ready` event before inspecting the deck. SVG assets of at least 200 KB are rasterized separately for every rendered occurrence. The capture uses the image's final bounding box relative to its clipping container, preserving the exact CSS zoom and crop shown on that slide, and replaces only the print DOM with a 2× PNG. The live presentation therefore keeps its responsive vector assets and smooth navigation. Authors can force, skip, or define a custom viewport for rasterization with data attributes.

Outcome

The result is a polished library with two example decks, one-command scaffolding, runtime metadata checks, and 16 automated tests alongside lint, type-check, and production-build gates. Lazy-loading keeps the library entry bundle at roughly 36 KB even after adding the print workflow. In a 30-page real-world deck, the preparation step converted all 14 large diagram views, preserved their individual crops, produced the expected page count, and completed without browser warnings. The repository is public under the MIT license and documented for straightforward personal use.

Lessons

A small convention becomes durable when it is reinforced by generation and validation instead of documentation alone. The project also confirmed the value of deferring specialist dependencies until they are needed and of testing static-hosting paths as a first-class production concern.

Print output is its own rendering target rather than a passive snapshot of the live interface. Waiting for deterministic layout state and capturing each visible viewport proved more reliable than optimizing source assets in isolation—especially when one diagram carries several narrative zoom states.

A local-first TypeScript workspace for authoring, organizing, presenting, and reliably printing independent reveal.js decks.

Explore all projects