Deployment
Ship a Mates SPA anywhere static files are served — and prerender routes with mates-ssg for instant first paint and SEO.
What you're shipping
A client-only Mates app is a standard Vite SPA: vite build produces a self-contained dist/ with no Node runtime. Add an SPA fallback so deep links work, then optionally prerender with mates-ssg for SEO and first paint. Fullstack apps (RPC, auth, document SSR) deploy as a Node service — their guide lives on mates-fullstack-home.
The build
npm run build # → dist/
Point any static host at dist/ and add one thing: an SPA fallback so deep links like /docs/router serve the app shell instead of a 404.
SPA fallback per host
|
Host
|
How
|
|---|---|
| Netlify |
_redirects file: /* /index.html 200
|
| Vercel |
vercel.json rewrite: { "source": "/((?!assets/).*)", "destination": "/index.html" }
|
| Cloudflare Pages |
Add a _redirects file (same syntax as Netlify) to the output directory
|
| nginx |
try_files $uri $uri/ /index.html; in your location block
|
| GitHub Pages |
Copy index.html to 404.html as a fallback
|
Prerendering with mates-ssg
SPA fallbacks work, but crawlers and slow devices pay the full JS cost before seeing content. mates-ssg prerenders every route to real HTML: it builds your SPA, serves it locally, crawls the routes from rendered <a href> links in headless Chrome, and writes one index.html per route. This very site is built with it.
npm install -D mates-ssg
npx mates-ssg build
- One
index.htmlper route — first paint is instant, no JS required sitemap.xmlandrobots.txtgenerated automatically_redirectswith an SPA fallback for routes discovered later- A clean shell (
__spa__.html) kept for unknown routes
The site origin for sitemap and canonicals comes from the SITE_URL env, --site-url, or the homepage field in package.json. Options go in a mates-ssg.config.json (or a "mates-ssg" key in package.json):
{
"concurrency": 12,
"seo": {
"extraRedirects": [
"/old-path https://example.com/new-path 301"
]
}
}
Caching
- Hashed assets (
/assets/*) — cache forever:Cache-Control: public, max-age=31536000, immutable - Per-route
index.html— short TTL so deploys propagate:max-age=0, must-revalidate - Never cache
index.htmlaggressively at the CDN — it references the hashed bundle
Fullstack apps
Mates fullstack apps (RPC server, auth, document SSR via useSSR()) deploy as a Node service, not a static site. Scaffold with create-mates (Fullstack SPA or Fullstack SSR), then follow deployment guides in mates-fullstack-home.