- Markdown slides — write slide content in markdown; structure is carried by
greppable
<!-- hyperdeck:... -->comment markers, so every deck stays valid, readable markdown on disk. - Per-slide and deck-wide CSS — style individual slides or the whole deck with plain CSS. What you style is exactly what renders.
- Editor, Stage, and Presenter views — edit decks in a Monaco-powered editor, render them on a stage, or run them in a dedicated presenter view.
- Local-first storage — decks are stored in the browser via IndexedDB (Dexie); no server or account required.
- Backendless share links — any deck compresses into a URL fragment
(
#share=…), so a deck travels inside the link itself. Opening a share link imports the deck as a local copy; stage links (#share=…&stage) — and the<iframe>embeds built on them — present straight from the URL and save nothing to the viewer's library. No server or account involved. - Light/dark theme — respects your system preference, with a manual toggle and no flash of the wrong scheme on load.
- Single-file interchange — a deck serializes to one plain-markdown file
(
<!-- hyperdeck:deck "..." -->,<!-- hyperdeck:slide "..." -->,<!-- hyperdeck:css -->), easy to diff, script, or hand to an agent.
| Layer | Tool |
|---|---|
| Runtime | Bun |
| Bundler | Vite 6 |
| UI | Preact + @preact/signals |
| Styling | Tailwind CSS 4 |
| Editor | Monaco Editor |
| Markdown | marked + highlight.js |
| Storage | Dexie (IndexedDB) |
| Lint/Fmt | oxlint / oxfmt |
Requires mise — this repo ships a mise.toml that pins
Bun and defines all tasks. (With Bun installed directly,
the equivalent bun run <name> commands also work.)
bun install # install dependencies
mise run dev # start the dev serverOpen the printed URL. Decks are stored in your browser's IndexedDB.
mise run build # production build to dist/
mise run preview # preview the production build
mise run lint # lint with oxlint
mise run fmt # format with oxfmt (writes)
mise run fmt:check # check formatting without writing├── index.html # entry document, theme bootstrap
├── vite.config.ts # Vite + Preact + Tailwind config
├── package.json # scripts, dependencies
├── tsconfig.json # TypeScript and JSX compiler options
├── bun.lock # lockfile
└── src
├── main.tsx # mount point
├── app.tsx # hash-based routing (dashboard / editor / stage / presenter)
├── state.ts # signals-based app state
├── components # Dashboard, Editor, Stage, Presenter, CodeEditor, ...
├── lib # deck markdown format, layouts, themes, sync, templates
├── db # Dexie schema and repository
└── styles # global CSS
A deck round-trips through a single markdown file:
<!-- hyperdeck:deck "Deck title" -->
<!-- hyperdeck:global-css -->
...deck-wide stylesheet...
<!-- hyperdeck:slide "Slide name" -->
...slide markdown...
<!-- hyperdeck:css -->
...slide stylesheet...The markers are HTML comments, so the file renders as a normal document in any markdown viewer while remaining trivially parseable by scripts.
See CONTRIBUTING.md for the development workflow, commit message conventions, and pull request guidelines.