MATES / Docs

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.html per route — first paint is instant, no JS required
  • sitemap.xml and robots.txt generated automatically
  • _redirects with 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):

mates-ssg.config.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.html aggressively 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.