Static site
The files a build writes, served by nginx with nothing running behind it
A static site is the files a build writes — Astro, Hugo, Eleventy, Jekyll, a Vite or React single-page application — served by nginx, with nothing running behind it: no PHP, no server of your own, no database. Choose Static site as the application when you order, and the machines run nginx alone. In front of it is the platform's proxy, which terminates TLS and routes the hostname, and the CDN where the environment has one.
What it serves
The release's public/ directory, read-only:
- a path is a file, a directory's
index.html, or the page of that name:/aboutservesabout.htmlorabout/index.html; - any other path is a 404, with your own
404.htmlwherepublic/has one; - styles, scripts, images and fonts go out with a year's
ExpiresandCache-Control: public, so build them with hashed names, as every bundler does.NGINX_STATIC_EXPIRESshortens it.
A generator that writes somewhere else — dist/ for Vite and Astro, _site/
for Jekyll and Eleventy, out/ for a Next.js export — has its last build step
move it there: mv dist public.
A static site
vallic.yaml at the root of the repository:
version: 1
type: static
runtime:
nginx: '1.31'
services:
- node: '26'
build:
steps:
- name: Site
image: node
run: npm ci && npm run build && rm -rf public && mv dist public && rm -rf node_modules
health:
path: /
The build runs in Node.js, a build tool that never runs beside
the site. A site committed as files needs no build at all: put them in
public/ and leave build out.
No cache, and node_modules removed. Whatever is in the checkout when the
build ends is the release, copied to every machine, and nothing in a static
site's release runs its node_modules. npm's downloads are kept between builds
for you, so npm ci installs from them without going to the network.
runtime.nginx is the version of nginx that serves it, matched to the current
build of it the way a language version is. There is no start and no port:
nginx is the server, on its own port.
A redirect, a header or a location of your own goes in
.vallic/nginx/server.conf: see Rules of your own.
A single-page application
An application that routes in the browser — React Router, Vue Router — wants
every path that is not a file to load its index.html and answer 200, so that
the router draws the page. Say so in the server's settings:
services:
- static:
version: '1.31'
environment:
NGINX_HTML_FALLBACK: index.html
Every entry under services needs a version, and which nginx runs is still
runtime.nginx, so keep the two the same. Without the setting, a path with no
file is a 404.
Deploy steps, jobs and the shell
Deploy steps, scheduled jobs and vallic ssh run in nginx's
container, which has sh, curl and wget and nothing to build with. That is
enough to empty the CDN after a release, which is what a static site's deploy
usually does: see Clearing the cache from your code.
A release goes live without nginx restarting, so no request is dropped.
No database, cache, search engine, queue or mail relay is offered to a static site: nothing behind nginx would ever reach one. A site that needs any of them is an application of its own — Node.js, PHP or another — rather than a static site. The type is chosen when the project is bought, and changing it once a release is serving is a migration rather than a setting; see Configuration.
Versions
| Version | Status |
|---|---|
1.31 |
Supported, and the default |
1.30 |
Supported |
Pin the version, not the build: name 1.31 and the platform matches it to the
current build, so a security rebuild reaches you without anybody editing a
repository.
What you can change
In vallic.yaml — what each one does is on Service settings:
services:
- static:
version: '1.31'
environment:
NGINX_KEEPALIVE_TIMEOUT: …
NGINX_GZIP_COMP_LEVEL: …
NGINX_STATIC_EXPIRES: …
NGINX_ERROR_LOG_LEVEL: …
NGINX_INDEX_FILE: …
NGINX_HTML_FALLBACK: …
Anything not on this list refuses the deploy, naming the variable — rather than being accepted and quietly ignored.