Slidev vs Reveal.js vs Marp vs Quarto decision matrix
| Authoring tool | Verified version | Publish artifact | Asset rule | Slidesfly path |
|---|---|---|---|---|
| Slidev | 52.18.1 | 49-file static build | Build with --base ./; patch the opaque-origin storage fallback. | Root-level Pro zip |
| Reveal.js | 6.0.1 | 46-file local runtime build | Reference dist/reveal.mjs, CSS, plugins, and media locally. | Root-level Pro zip |
| Marp CLI | 4.5.0 | One 110,832-byte HTML file | Embed the runtime; inspect images, fonts, and custom themes separately. | Anonymous or account single-file path, subject to size |
| Plain HTML | Browser-standard HTML, CSS, and JavaScript | One self-contained HTML file | Inline scripts and styles; no external script source. | Anonymous or account single-file path |
| Quarto Reveal.js | 1.10.18 | One 3,463,302-byte HTML file | Use embed-resources: true and html-math-method: plain, then inject the storage fallback and reader bridge. | Authenticated Free or Pro single-file path; over the anonymous size limit |
Live proof and reproducible source
| Framework | Built artifact | Index proof | Open or inspect |
|---|---|---|---|
| Slidev 52.18.1 | 49 files; 803,544 bytes | 3,596 bytes; 03e4d5ee614917178784854b1775c73066f4610127bdddbac022a1b1ef7fbad4 | Live reader · reader index · source |
| Reveal.js 6.0.1 | 46 files; 5,127,395 bytes | 1,654 bytes; c21712a5f88d90c5ad8c99292696c22dff6c69a7ba34550b1e7356e534a31bc3 | Live reader · reader index · source |
| Marp CLI 4.5.0 | One 110,832-byte HTML file | Byte-matched; bf620fb90c599ae6ca1188425e1d84033b1b8dcba2dffedfc5443a41a73f8521 | Live reader · reader index · source |
| Quarto Reveal.js 1.10.18 | One 3,463,302-byte HTML file; 5 slides | Byte-matched to production version 5; bc56b6fa5c214bf7d13658911c3e8e27dfb50e9d8c2eee1ecd55d6a9d2066313 | Live reader · reader index · source |
Build the four verified artifacts
Slidev 52.18.1
npm ci
npm run build
test -f dist/index.html
cd dist
zip -r ../slidev-deck.zip .
cd ..
slidesfly publish ./slidev-deck.zip --title "Slidev deck" --jsonThe source fixture's build script runs Slidev with --base ./ --out dist, then injects the Slidesfly storage fallback and reader-navigation bridge. Zip the contents of dist, not the directory itself.
Reveal.js 6.0.1
npm ci
npm run build
test -f build/index.html
cd build
zip -r ../revealjs-deck.zip .
cd ..
slidesfly publish ./revealjs-deck.zip --title "Reveal.js deck" --jsonThe fixture copies the installed reveal.js/dist directory beside index.html. Copy only the plugins and themes you use when reducing file count.
Marp CLI 4.5.0
npm ci
npm run build
test -f build/index.html
slidesfly publish ./build/index.html --title "Marp deck" --jsonThe fixture pins Marp CLI, exports one HTML file, and injects the reader-navigation bridge. It does not zip the output.
Quarto Reveal.js 1.10.18
quarto render slides.qmd --output-dir build
test -f build/index.html
node ../inject-slidesfly-reader-bridge.mjs build/index.html quarto
node validate.mjs build/index.html
node ../../skills/slidesfly/scripts/slidesfly.mjs publish \
./build/index.html \
--title "Quarto publishing example" \
--visibility public \
--jsonThe fixture renders one self-contained Reveal.js document, disables dynamic MathJax, injects an early storage fallback and the standard reader bridge, then rejects remote scripts or styles, leaked Slidesfly credentials, missing slides, and artifacts above the current Free 5 MB (5,000,000 bytes) limit.
Base paths and external resources
| Question | Answer | Failure signal |
|---|---|---|
Why does Slidev use --base ./? | The reader asset lives below a versioned path. Relative URLs stay below that path; root URLs such as /assets/app.js do not. | Blank deck and asset 404 responses. |
| Can Reveal.js load from a CDN? | No remote <script src> is accepted. Package the runtime and plugins as local relative files. | MALICIOUS_CONTENT during publish. |
| Is every Marp export self-contained? | The runtime is embedded, but remote images, fonts, and custom theme resources still require inspection. | Network dependency, missing media, or reader-policy mismatch. |
Does Quarto embed-resources: true make every feature portable? | It embeds the verified local presentation resources, but dynamically loaded features still need inspection. The fixture uses html-math-method: plain and excludes Chalkboard, multiplex, remote media, and speaker-view dependencies. | Remote MathJax request, missing advanced feature, or publish-policy rejection. |
Reader sandbox contract
sandbox="allow-scripts allow-popups allow-popups-to-escape-sandbox allow-forms"allow-same-origin and allow-top-navigation are absent. Cookies, localStorage, sessionStorage, and IndexedDB are not reliable persistence layers. Slidev and Quarto supply in-memory storage fallbacks; Reveal.js and Marp do not depend on persistent browser storage in these examples.
A Pro zip may contain at most 50 files and 50,000,000 uncompressed bytes under the current plan contract. Multi-file readers support public or unlisted visibility, not private visibility.
Failure and recovery matrix
| Failure | Likely cause | Safe recovery |
|---|---|---|
INVALID_HTML | Missing root index.html, unsafe path, unreadable zip, or too many files. | Inspect the archive, rebuild, then zip the output contents from inside the folder. |
MALICIOUS_CONTENT | A remote script or blocked resource was found. | Package required runtime code locally; use Report only for a reproducible false positive. |
FORBIDDEN | The account is not eligible for multi-file publishing or private was requested. | Use an eligible Pro account and public or unlisted visibility, or choose another host. |
| Reader is blank | Absolute asset paths, storage initialization, or an unbundled dependency failed. | Check the network panel, rebuild Slidev with --base ./, and apply the fixture helper. |
| Quarto logs a storage error or requests MathJax | Reveal.js touched sessionStorage in the opaque-origin reader, or the default math runtime was left enabled. | Set html-math-method: plain, run the shared Quarto injector after every render, then rerun the validator and browser checks before publishing. |
How this proof was checked
The repository fixtures were built from pinned versions and compared with their current reader indexes. Slidev and Marp advanced from slide 1 to slide 2 on 2026-08-01. Reveal.js production version 2 passed next, previous, first, and last navigation on 2026-08-03 and ignored unrecognized actions including constructor, toString, and __proto__. Quarto production version 5 rendered at desktop and 390x844 mobile sizes and advanced from slide 1 to slide 5 on 2026-08-03. Every deck-declared runtime request stayed on its versioned r.slidesfly.xyz path; no fixture loaded a remote runtime script. The Quarto fixture also disabled its dynamic MathJax request with html-math-method: plain.