markdown to slides · compared
Lutrin vs reveal.js
This is the least even comparison of the four, in both directions. On the web, reveal.js is not merely ahead — it is the thing the others are measured against. And there is no PowerPoint at the end of any reveal.js path, natively or planned. So the question is not which is better; it is whether what you owe somebody is a page or a file.
What reveal.js does better
Four of them, and they are not small. If your deck lives on a screen and its job is to be watched, this list is the answer and the rest of the page is beside the point.
Four things reveal.js does that Lutrin cannot
- Motion design between slides. Auto-Animate morphs
matching elements across two adjacent slides — position, size, colour,
spacing, essentially any animatable property — with per-slide easing
and
data-idto pair elements that do not match by content. A build-up where a headline shrinks into a corner while a chart grows into its place is reveal.js work. Lutrin reveals one block at a time and applies PowerPoint Morph only to the "(cont.)" pages its own pagination creates. - A real vocabulary for incremental reveal. Fragments ship more than a dozen named effects, explicit ordering by index, nesting so one element can fade in then turn red then fade out, custom effects declared in CSS, and events you can script against. Lutrin has four effects applied per block, chosen by the engine unless you name one, and no scripting hook at all.
- It is extensible, because it is a web page. Six bundled plugins, a documented plugin registry, a JS API, every theme variable exposed as a CSS custom property, and the freedom to drop an iframe, a video or a live D3 canvas into a slide. Lutrin refuses all of it by design — no coordinate, no CSS override, no JS hook.
- A reading mode that adapts to the viewport. Scroll view turns the same presentation into a scrollable page with fragments preserved, and auto-activates below a configurable viewport width so the deck stays readable on a phone. Lutrin's HTML is already a scrollable page — that is its default, and the slide-at-a-time mode is the opt-in, entered with P — but that page has no breakpoint of any kind. Every slide is scaled to the width of its container, so on a 390 px phone a 14 pt body set on a 1280 px grid comes out too small to read; the honest answer there is to turn the phone sideways and press P. What Lutrin lacks is the responsive switch, not the mode.
And the ecosystem gap is real. Around 72,000 GitHub stars, a community plugin catalogue and a decade of answers to every question you might have. Lutrin is a young project with one maintainer. A page that skipped this would be marketing.
Where Lutrin is different
- There is no PowerPoint at the end of any reveal.js
path. Its only built-in export is PDF, through a print
stylesheet and the browser's print dialog — the same mechanism
Lutrin's HTML uses, and on that one point the two are even. A feature request for
PowerPoint export has been open since January 2019 with no assignee, no
label and no linked pull request — that is an absence, not a refusal, and
it should not be described as one. Third-party converters and a PDF
round trip do exist; what they cost you is flattened slides and every
fragment and transition gone. Lutrin's primary output is a
.pptxof native text boxes, tables and shapes, with the fonts embedded. Charts, diagrams, equations and icons in that file are pictures, each carrying its vector as well as its raster — sharp at any zoom in PowerPoint 2019+, the raster everywhere else. The text, the tables and the layout were never pictures at all. - Who owns the page. In reveal.js the author owns everything: HTML, CSS custom properties, classes, free positioning. In Lutrin the author may not position anything; the engine infers the layout from the structure of the content and paginates the overflow. That is a loss of control traded for homogeneity, and it is written into the contributing contract rather than left as a gap to fill later.
- Validation that measures. reveal.js documents no
layout engine and no overflow detection — a slide that is too full simply
overflows or gets scaled.
lutrin validatereports measured overflow, under-resolved images and a better-suited layout, anchored to a source line and emitted as JSON;buildwrites no file while validation holds an error-severity diagnostic, short of an explicit--force. - Branding as data. A reveal.js theme is CSS — twelve built in, custom ones written as CSS or Sass — which is more expressive, and is also code you must review and maintain. A Lutrin kit is theme tokens, layouts, fonts and logos in an archive; installing one executes nothing and refuses any executable entry.
- How each is funded. Both are MIT and neither holds anything back. reveal.js is funded through Slides.com, a separate hosted editor by the same author; Lutrin is funded by nothing at all, which is a real difference in what you can count on and worth weighing.
Side by side
| reveal.js | Lutrin | |
|---|---|---|
| What you get out | A self-presenting web page you host, plus built-in PDF export. | An editable .pptx, one standalone HTML file, or a 16:9 PDF written by --pdf — one page per slide, with an outline reveal.js's print path does not produce. |
| PowerPoint path | None. No native PPTX export; the request has sat open and unassigned since 2019. Third-party converters and PDF→PPTX exist, and flatten the deck. | Native: text boxes, tables, shapes, notes and embedded fonts. |
| Who decides the layout | You — HTML, CSS, custom properties, free positioning. No layout engine or overflow detection documented. | The engine, always. No coordinate, no explicit column, no CSS override. |
| Authoring in Markdown | Fully supported — whole decks can live in an external .md, with configurable separators. Anything beyond plain Markdown rides in HTML-comment attributes. |
Markdown is the only surface, treated as a DSL. No HTML escape hatch. |
| Slide structure | Two-dimensional: horizontal slides with nested vertical stacks. | Linear only. |
| Overflowing content | Your problem — adjust the CSS or the content. | Measured, reported as a diagnostic before the build, and paginated. |
| Animation | Fragments with a dozen-plus effects, indexes, nesting, custom CSS effects, JS events; Auto-Animate morphing between slides. | Four effects, applied per block by the engine, from one table both outputs read — so a named effect means the same thing in the .pptx and in the HTML. |
| Presenter view | Notes, next-slide preview, elapsed timer, wall clock, optional pacing timer. Needs to be served from a local web server. | Built into the standalone HTML: notes, elapsed timer, wall clock, next slide, second window — and an overview grid on O. Native notes in the .pptx. Roughly parity; the pacing timer is the piece we do not have. |
| Reading it as a page | Scroll view — the same deck as a scrollable page, auto-activating on narrow viewports. | The default: every slide stacked in one scrolling page; presenting is the opt-in (P). No breakpoint, so a phone-width viewport shrinks the type rather than reflowing it. |
| Extensibility | Plugin API, JS API, bundled plugins, a community catalogue, an official React wrapper and TypeScript types. | Extension is data: kits, JSON themes, layout aliases. Installation executes nothing. |
| Setup | Download the ZIP and edit index.html, or install from npm. |
npx lutrin build deck.md -o deck.pptx, Node ≥ 22. |
| Licence and money | MIT, no paid tier, no watermark. Funded through a separate hosted product. | MIT, no paid tier, no watermark. Funded by nobody. |
| Maturity | 6.0.1, released 2026-04-11. ~72,000 stars, actively maintained. | Young, one maintainer. |
Run the comparison yourself
Only partly, and the honest version is worth more than a rigged one.
There is no import path: Lutrin's marp: true switch
reads Marp Markdown, not reveal.js Markdown, and reveal.js's fragment
classes and slide-attribute comments have no Lutrin equivalent — as
Lutrin's :::metric and ```chart blocks have no
reveal.js equivalent.
What does compile both ways is the plain subset: one H1 per slide,
--- splits, bullets, a table, a quote, speaker notes. Write
that once and feed it to both.
# reveal.js: load it with data-markdown, or point its Markdown plugin at the file
npx lutrin build plain.md -o lutrin.pptx
reveal.js hands you a folder to host, presenting a centred column that
scales or spills when a slide is too full, and a PDF if you print it.
Lutrin hands you a .pptx whose bullet slide became two
columns, whose table slide became a table, and whose overflowing slide
was split into a "(cont.)" page — every shape editable in PowerPoint.
Then try the reverse honestly: build a deck around an Auto-Animate build-up, and Lutrin cannot render it at all.
Every claim about reveal.js on this page was checked against its own current documentation and repository on 2026-07-30, against reveal.js 6.0.1 (released 2026-04-11). Note in particular that the common criticisms of this project are out of date: the build moved to Vite, TypeScript types ship in the package, and there is an official React wrapper, all as of 6.0.0. If a statement here has stopped being true, tell us. Sources: revealjs.com, Auto-Animate, scroll view, PDF export, issue #2310.