SPA mode & error pages
Serve /index.html for unmatched routes so client-side routers work, and map status codes to your own pages.
read as markdownTwo options cover the common routing cases for static sites.
Single-page apps
Add --spa and any path that doesn’t match a file is served /index.html with
a 200 — so client-side routers (React Router, Vue Router, TanStack Router)
handle deep links instead of returning a 404.
$ one9x pages release ./dist --site myapp --spa --deploy✓ Live · unknown routes → /index.htmlThis is the flag that decides whether an app works. Without it, the first
visitor who hard-refreshes on /settings or follows a shared deep link gets a
404 — the app is fine, the routing never got a chance to run.
You need it for a client-rendered app (Vite + React Router, Vue Router, Create
React App). You don’t need it for a static site generator that writes a real
HTML file per route — Astro, Hugo, Eleventy, Next.js output: 'export' — where
an unmatched path genuinely is a 404 and should say so. Frameworks
has the per-framework answer.
--spaand--indexare the same slot and conflict.--indexnames a different fallback document;--spais the shorthand for--index /index.html. Pass one or the other.
Custom error pages
Map a status code to a page in your build with --error code:path. The flag
repeats, so you can set as many as you need.
$ one9x pages release ./dist --site mysite --deploy \ --error 404:/404.html \ --error 403:/403.html✓ Live · custom 404, 403The path is a path within the release — it has to be a file the build actually
produced, at the exact path it lives at. --error 404:/404.html with the file
at /404/index.html maps to nothing.
Error pages and --spa interact the way you would want: with --spa on, an
unmatched route is not an error at all, so the 404 page is only reached when the
app itself asks for it.