Skip to content
brought to you byVoidZero

Static Site Generation (SSG) ​

Set output: "static" in void.config.ts to prerender all pages at build time:

json
{
  "output": "static"
}

When output is "static":

  • Pages default to prerender = true and are written as HTML files to dist/client/.
  • Use export const prerender = false in a page's .server.ts to opt out. That page will be server-rendered on request.
  • Dynamic pages without getPrerenderPaths() are implicitly not prerendered (the paths aren't known at build time).
  • The build output is self-contained and works for direct Cloudflare deployment, self-hosting, or void deploy.

Per-page overrides ​

Individual pages can opt out of prerendering:

ts
// pages/dashboard.server.ts
export const prerender = false;

Dynamic pages with getPrerenderPaths() are prerendered for the returned param combinations:

ts
// pages/blog/[slug].server.ts
export async function getPrerenderPaths() {
  return [{ slug: 'hello-world' }, { slug: 'getting-started' }];
}

404 pages ​

Static builds that prerender at least one page include a default 404.html in dist/client/. To provide your own, add public/404.html or prerender a page at /404.

Fully static Void deployments serve this page for missing URLs with an HTTP 404 status by default. You can override this with routing.notFound. Hybrid deployments handle missing URLs in the Worker.

When hosting dist/client/ yourself, configure your host to serve 404.html with a 404 status for missing pages.

Comparison with edge prerendering ​

output valueDefault prerenderPer-page overridePrerender timing
"server" (default)falseexport const prerender = trueDeploy-time (platform ISR)
"static"trueexport const prerender = falseBuild or deploy post-build

With the default output: "server", use export const prerender = true for deploy-time edge prerendering.

Deployment behavior ​

void deploy chooses the deployment automatically:

  • Fully static: if every page is prerendered and there are no API routes, middleware, cron jobs, or queues, Void deploys the built files as a static site. With --platform cloudflare, pages and files are served without running a Worker. If you use edge rules (routing headers, redirects, rewrites, fallbacks, or alwaysUseHttps) or a _headers or _redirects file in public/, a small Worker runs on every request to apply them.
  • Hybrid: if any pages are not prerenderable, such as dynamic pages without getPrerenderPaths() or pages with export const prerender = false, a Worker is deployed to handle those routes at runtime. With --platform cloudflare, prerendered pages without a .server.ts file are served as static files without running the Worker. API routes, pages with a .server.ts file, and dynamic pages run in the Worker. Every page runs through the Worker when the app uses middleware, auth, live updates, edge rules (including a _headers or _redirects file in public/), a custom Vite base, a routing.notFound setting other than "none", or a dynamic page at the top level of pages/, such as pages/[slug].vue.

Relationship to inference.appType: "static" ​

The inference.appType field describes app type (SPA, static, void), while output controls rendering strategy:

inference.appType: "static"output: "static"
WhatDeploy a pre-built static site (no Void plugin)Prerender a Void app at build time
WorkerNone (static assets only)Only for server code and edge rules
Use caseVitePress, plain HTML, external SSG toolsVoid apps with mostly or fully static content