slipway.yaml
publish
Required. The directory your build writes, relative torootDir.
slipway.yaml
Getting this wrong is the most common way a static site fails: the deploy goes green and
the URL returns 404. The build log reports how many files were uploaded, and the service’s
Files view lists exactly what is there.
The build
rootDir is where the build runs, defaulting to the repository root. buildCommand is
what it runs, and needs runtime to say what to run it in.
slipway.yaml
buildCommand runs, from whichever lockfile the project
commits: npm ci, pnpm install or yarn install for Node, pip install for Python,
bundle install for Ruby. The build command is only the build. Writing npm ci && npm run build still works, it just installs twice.
All four settings can be changed later from the site’s Settings tab, under Build.
Saving rebuilds and republishes the site. A site that deploys from a committed
slipway.yaml shows the file’s values there, and is changed in the file.
Omit buildCommand when the files are already committed and need no build:
slipway.yaml
dockerfilePath, dockerContext, dockerTarget and image are all rejected on a static
service. No image is built and none is pulled.Uploading a build instead
A static site is the one thing slipway serves with no repository, because the artifact is the whole input. In New → Static site, switch the source to Upload a build and drop a.zip of your build output.
Re-upload at any time to publish a new version. Each upload replaces the last, and
deploying publishes it the same way a repo build would, with the same events, rollback and
file views.
A zip made by compressing a directory wraps everything in one top-level folder. slipway
strips a single wrapper automatically, so both of these serve the same site:
__MACOSX/ and .DS_Store are skipped, and an archive containing .. in a path is
rejected rather than relocated.
An uploaded site has no build command, no build-time environment variables and no branch to
watch, so nothing auto-redeploys. Everything else on this page works identically.
Environment variables
A static site has no runtime, soenv applies to the build only.
slipway.yaml
Single-page apps
SetnotFound to your entry document so client-side routes resolve.
slipway.yaml
index.html. Requests that look like assets, a
dotted filename that is not .html, still return a real 404, so a missing /app.js does
not come back as HTML and surface as a JavaScript syntax error.
For a multi-page site, point notFound at a real error page instead:
slipway.yaml
404.html in the publish directory is used automatically even without notFound, and
the nearest one wins, so docs/404.html answers misses under /docs/.
Redirects and headers
slipway.yaml
200 rewrite; set force: true to override that. A 3xx rule beats a
real file, so you can retire a live URL without deleting the page behind it.
An empty header value removes the header.
slipway also reads _redirects and _headers files from the publish directory, in the
Netlify and Cloudflare Pages format, so a site moving from either platform works unchanged.
A syntax error there does not fail the deploy: the bad line is skipped and named in the
build log. The files themselves are never served.
The same rules can be edited in the console without a rebuild. See
Redirects and headers for how the three sources combine and
which wins.
Caching
slipway sets caching for you:- Hashed assets, meaning anything under
/assets/,/_app/immutable/,/_next/static/, or with a content hash in the filename, getCache-Control: public, max-age=31536000, immutable. - Everything else revalidates, so a deploy is visible immediately.
headers rule.
You never need to purge a cache. Each deployment’s files are served from their own address
at the edge, so a deploy or rollback moves to fresh cache entries rather than invalidating
old ones.
Deploys and rollbacks
A deploy is atomic. The previous build serves until the new one is completely uploaded, then the switch happens between requests. Rolling back rebuilds nothing, because the previous build’s files are still there, so it is a single pointer change. Older builds are kept for 30 days and at least the last 10, which is how far back you can roll. A switch takes a few seconds to reach every location and up to about a minute worldwide. Nobody ever sees a mixture of two builds.Custom domains
Add the domain on the project’s Settings → Domains, then point one DNS record at slipway:www.
See Custom domains.
Traffic
A static site is served from the CDN and the cluster is never in the request path, so there are no pod counters and nothing for the Metrics tab to sample. Its traffic is measured at the edge instead, and shows up in two places. The site’s own page carries Egress and Requests for the last 24 hours, hour by hour, along with how those requests were answered. An hour that is tall on requests and flat on egress is a site answering304 Not Modified, which means caching is working.
The project overview adds a CDN panel whenever the project runs any static services,
with one bar per hour and a colour per site. It sits beside CPU, Memory and Requests
rather than joining them: those cover the project’s containers at five-minute resolution,
and edge traffic is only reported by the hour. Drawing the two on one axis would make a
site serving the same rate as a container look twelve times busier.
Edge measurements arrive a couple of minutes behind, so the most recent bar keeps filling
in for a short while after a burst.
What a static site does not have
No shell, no scaling, no disks, no compute allocation and no sleep, because there is no container for any of those to act on. The console hides those tabs rather than locking them. Siblings cannot reach a static site over the private network. There is nohttp://site
inside the project because no process is listening, and ${service.site.host} fails with a
message pointing at ${service.site.public_url}.