3. Shipping a Slidev Deck, and the Default Build That Publishes Your Speaker Notes
We built our Slidev talk into a 6.7 MB site in 1.95 seconds, then found the default build lets anyone read the speaker notes at /presenter/. We also exported without the 554 MB Chromium download.
The WJS Desk
Sep 24, 2026 ยท 8 min read

Our nine slide talk from Part 2 now exists in six forms: a static website that builds in about 2 seconds, the same site under a sub-path, a PDF, two kinds of PowerPoint, and a folder of PNGs. We also found a way to export all of them without the 554 MB Chromium download from Part 1, which is the single most useful thing in this course.
We also found the thing that should stop you publishing a deck before reading this: by default, the built website ships your speaker notes, and anyone who adds /presenter/3 to the address can read them.
What we shipped, in numbers
Every output below came from the same slides.md on the same Apple M4 Pro, Slidev 53.0.0. Times are wall clock for the whole command.
| Output | Command time | Size | Text selectable | Keeps clicks |
|---|---|---|---|---|
| Static site | 1.95 to 3.08 s | 6.7 MB, 142 files | yes | yes |
| 6.21 s | 550 KB, 9 pages | yes | no, unless --with-clicks | |
| PPTX | 7.20 s | 2.93 MB, 20 slides | no, images | yes, as extra slides |
| Editable PPTX | 3.78 s | 1.88 MB, 20 slides | yes | yes, as extra slides |
| PNG | 5.19 s | 2.1 MB, 9 files | no | no |
The static site is the only format that keeps the talk as you built it. Everything else is a snapshot of it, and each snapshot loses something different.
Prerequisites
The Part 2 project: @slidev/cli, @slidev/theme-default, and playwright-chromium for the export formats. Python 3 for a throwaway static server (macOS ships it). About 30 minutes. We did not deploy to a real host for this part. Every hosting test below ran against local servers configured to behave like the hosts they stand in for, and we say which.
Step 1: build the website
npx slidev build
Three runs took 3.08, 1.96 and 1.95 seconds. The dist folder was 6.7 MB and 142 files, 125 of them JavaScript totalling 1.74 MB gzipped. For comparison, the starter tour from Part 1 built to 36 MB, because it uses the Monaco code editor and that ships its language workers. Our talk does not, so they are not included.
The folder contains index.html, 404.html, an assets folder, our photo, and a one line _redirects file:
/* /index.html 200
That file matters more than it looks. The deck is a single page app: /3 is not a real file, the JavaScript works out that it means slide 3. The _redirects line tells a host to answer every path with index.html. Netlify and Cloudflare Pages read that file. A plain file server does not.
Step 2: the refresh that kills your talk
We served dist with the simplest static server there is:
cd dist
python3 -m http.server 8801
Then we drove it with a headless browser: open the deck, press the right arrow three times, reload. The first load worked and the arrows moved us to /3?clicks=1. The reload returned the server's Error response page with a 404. On stage that is the moment you press Cmd+R because a video stalled, and the deck is gone.
The docs recommend testing with Vite's preview server, which does fall back to index.html. With that, a direct request for /5 returned 200. So "it worked when I tested it" and "it breaks on my host" can both be true. If your host does not understand _redirects (plain S3, a university web folder, an nginx box you do not control), use hash routing:
npx slidev build --router-mode hash
URLs become /#/3, the server only ever sees /, and our reload test landed back on slide 3 with its heading on screen.
Step 3: hosting under a sub-path
GitHub Pages puts a project at username.github.io/repo-name/, so the deck lives under a folder, not at the root. We copied the default build into a talk folder under the static server and opened /talk/. We got a blank page and 12 failed requests, every one of them to /assets/ at the site root instead of /talk/assets/. The fix is to tell the build where it will live:
npx slidev build --base /talk/
That took 2.50 seconds and the deck loaded at /talk/1. A refresh on a plain server still returned 404, so for a dumb host under a sub-path you want both flags:
npx slidev build --base /talk/ --router-mode hash
In Part 2 we told you to keep the leading slash on image paths because this is where relative paths would bite. We tested it, and we were wrong to expect trouble. Both image: /terminal.jpg and image: terminal.jpg were rewritten to /talk/terminal.jpg and loaded with a 200. The slash is still the form the docs use, but it is style, not a fix.
The hosting docs include a complete GitHub Actions workflow that builds with --base /${{github.event.repository.name}}/. We read it but did not run it, because it needs a real repository with Pages enabled and we test locally.
Step 4: strip your speaker notes before you publish
We opened /presenter/3 on the built site, the same address a presenter uses. It worked with no password, and the notes pane showed our note for that slide: "Click through one line at a time. The punchline is line 3: GNU never left." The note text also sits in plain text inside dist/assets/index-*.js, where grep found it.
Notes are often where people put the things they would not put on a slide. The fix is one flag, and the hosting docs do mention it:
npx slidev build --without-notes
After that, grep found nothing and the presenter pane said "No notes." The presenter view itself is still reachable, it just has nothing to show.
Gotcha: the website build flag for the output folder is --out (or -o), not --output. slidev build also accepts --output without complaint, because it is one of the export options, and ignores it for the folder. We ran npx slidev build --without-notes --output dist-nonotes, and it quietly overwrote our main dist with a notes-free build. We spent a round of contradictory test results on it before we read --help properly.
Step 5: PowerPoint, twice
For the colleague who needs a .pptx:
npx slidev export --format pptx --output talk
7.20 seconds, 2.93 MB. We unzipped it: 20 slides, 21 media files, 20 notes pages, and the word "SIGSEGV" appears nowhere in the slide XML. Each slide is a picture. Clicks are on by default for this format, so our 9 slides became 20. The notes did come across, which is the redeeming feature.
53.0.0 also has an editable format:
npx slidev export --format pptx-editable --output talk-editable
3.78 seconds, 1.88 MB, 20 slides, only 3 media files, and "SIGSEGV" is real, searchable text on 2 slides. We opened it by converting it through LibreOffice, and it held up: tables, the two columns, the photo, the dimmed code lines. One flaw: code is set in Fira Code, which this Mac does not have installed. LibreOffice fell back to a proportional font and the columns of our dpkg listing no longer lined up. Anyone opening it without Fira Code will see the same. We did not open either file in PowerPoint or Keynote, only LibreOffice.
Step 6: skip the 554 MB download
Every export so far needed Playwright's own Chromium. The export command has a flag, --executable-path, that points it at a browser you already have. We tested it properly: new folder, install without the browser download, then move Playwright's cached Chromium out of the way so it could not be quietly reused.
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm i -D @slidev/cli @slidev/theme-default playwright-chromium
That install took 38.65 seconds on a warm npm cache, with no browser download. A normal export then failed as it should, exit 1, browserType.launch: Executable doesn't exist. Then:
npx slidev export --executable-path "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
5.90 seconds, 9 pages, 550,044 bytes, against 549,946 bytes from Playwright's Chromium. Same deck, 98 bytes apart, with Chrome 153.0.8010.53. We restored the cache afterwards.
Confirmed: if you have Google Chrome installed, you do not need the 5 minute 29 second, 554 MB download from Part 1. Skip it at install time and pass --executable-path.
We only tested Google Chrome at that one version. We did not try Edge, Brave or Arc.
What broke
Most of this part's failures are listed where they happened, so here they are together:
- Refresh on a plain server: 404 on any slide but the first. Fix:
--router-mode hash, or a host that reads_redirects. - Sub-path without
--base: blank page, 12 failed asset requests. Fix:--base /your-path/, with slashes at both ends. - Notes published by default: readable at
/presenter/and in the JavaScript. Fix:--without-notes. - Our own
--outputmistake: accepted silently, wrote to the wrong folder. The tool was fine. It just did not warn us. - Editable PPTX without Fira Code: misaligned code columns in LibreOffice.
One thing that did not break: we blocked every request that was not to our local server and reloaded the deck, to simulate a venue with no Wi-Fi. Exactly one request failed, the Google Fonts stylesheet. Code fell back to the system monospace font with its columns intact, and headings did not change, because the default theme prefers Avenir Next, which is installed on macOS, and only fetches Nunito Sans from Google when Avenir is missing. On Windows or Linux the offline result will look different, and we did not test either.
Common mistakes
- Testing with
vite previewand deploying to a host that does not rewrite paths. - Forgetting the trailing slash: the docs say
--basemust begin and end with/. - Sending the image PPTX to someone who needs to edit it. Use
pptx-editable, and warn them about the code font. - Publishing the default build of a talk whose notes say anything you would not say on stage.
- Assuming a PDF has your clicks. It has the final state of each slide, as Part 2 showed.
What we did not test
No real deploy to GitHub Pages, Netlify, Vercel or Cloudflare Pages: those were simulated with local servers. No Windows or Linux. No PowerPoint or Keynote, only LibreOffice. No browser exporter at /export, only the CLI. No --dark, --with-toc or --per-slide exports. Timings are from one machine and single digit runs, so treat differences under a second as noise.
Next
Part 4 is the verdict. We put the same talk through Marp, the closest alternative, with a stopwatch on both, and give you a straight answer on who should adopt Slidev and who should not.


