Skip to content

Static Site Generators

Any static site generator works with Evolving Edge: build your site, then deploy the output folder (dist/, public/, build/ and so on) as a workload. Most sites need nothing else. This page covers the few settings that depend on how your generator names its pages and assets.

Two optional files in the root of your build output control this. Each generator copies its static folder (usually public/ or static/) into the output unchanged, so put the files there:

  • _redirects holds redirect and rewrite rules, plus the two routing settings below. It applies to Level 0 sites.
  • _headers sets response headers. It applies to Level 0 and Level 2 sites, not Level 1. Cache-Control from it takes effect on Level 0 only: Level 2 content is always served no-cache.

Both use the same format as Netlify, so a file you already have for Netlify usually works unchanged.

Many generators write each page as a folder with an index.html inside: about/index.html, served at /about/. By default /about (no slash) is a 404. To redirect it to /about/, add this line to _redirects:

# ee:trailing-slash on

It’s a comment, so the file still works on other hosts. With Astro, set trailingSlash: 'always' and build: { format: 'directory' } in astro.config.mjs and add the line.

Some generators write flat files (about.html) but link to /about: Quartz, Observable Framework, Hono’s SSG helper, vite-ssg, Silex, îles and Emanote by default, and VitePress, Rspress, VuePress and HonKit when their cleanUrls option is on. For these, add:

# ee:clean-urls on

/about is then served from about.html, and the address bar stays on /about. Because about.html now counts as the page at /about, a rule of your own for /about applies only if you force it with ! (see below). With both lines present, a page served from a .html file wins, and the trailing-slash redirect applies only when there isn’t one.

Under the setting lines, add one rule per line: from to [status]. The status defaults to 301; 302, 200 (rewrite) and 404 also work. Add a ! after the status (for example 301!) to make a rule apply even when a file exists at that path.

# ee:trailing-slash on
/old-blog/* /blog/:splat 301
/docs /docs/intro/ 302

A 404.html in the root of your output is served, with a 404 status, for any path that doesn’t exist.

By default, HTML is revalidated on every request, a few well-known build folders (_astro/, _next/static/, _nuxt/, _app/immutable/, _assets/) are cached for a year, and everything else is cached for an hour.

Most generators put content-hashed files (index-CAoPt-vL.js) in a folder of their own. A file there never changes without its name changing, so you can cache the whole folder for a year in _headers. Only do this if every file in that folder is hashed, in every build. A browser that has cached a file for a year won’t fetch it again. Check that nothing in your static folder copies an unhashed file into the hashed folder (for example public/assets/logo.png in a Vite project).

Vite, VitePress, Docusaurus:

/assets/*
Cache-Control: public, max-age=31536000, immutable

Qwik City (static adapter):

/build/*
Cache-Control: public, max-age=31536000, immutable

Gatsby. page-data/ must be revalidated on every request, or a new deploy can serve old page data next to new JavaScript:

/page-data/*
Cache-Control: public, max-age=0, must-revalidate
/static/*
Cache-Control: public, max-age=31536000, immutable
/app-*.js
Cache-Control: public, max-age=31536000, immutable
/framework-*.js
Cache-Control: public, max-age=31536000, immutable
/webpack-runtime-*.js
Cache-Control: public, max-age=31536000, immutable
/component---*.js
Cache-Control: public, max-age=31536000, immutable
/styles.*.css
Cache-Control: public, max-age=31536000, immutable

Gatsby writes these files to the root of the site, beside anything from your static/ folder. Don’t give your own files names that match the patterns above, like app-config.js.

Hugo mixes fingerprinted files with the files static/ copies, so no folder is safe by default. Keep fingerprinted resources in a folder of their own (for example assets/fp/, piped through fingerprint, which publishes to /fp/), then:

/fp/*
Cache-Control: public, max-age=31536000, immutable

These rules take effect on Level 0 sites. Level 1 and Level 2 content is always served no-cache.

Next: Integration & API >