Documentation
Downloads & redirects
Beyond rendered pages, a site's site.toml serves two things directly:
redirects and file downloads (composed assets). Both are matched before page
rendering and are read fresh on every request, so a git push applies changes with no
restart.
Redirects
A [[redirect]] maps an exact request path to a target with a 302:
[[redirect]] from = "/old-page" to = "/new-page"
| Field | Description |
|---|---|
from | The request path to match — exact, the whole path |
to | The redirect target (a local path or an absolute URL) |
- Matching is exact: one block maps one path. A path that does not match any
fromis handled normally (page, asset, or404). - Served
Cache-Control: no-cache, so a moving target (such as alatestalias) is never cached by clients. tocan point anywhere, including another origin.
Example: send downloads to object storage
The download page links to in-domain paths like
/dl/latest/qwen3/everlock-linux-amd64v3, and the self-updater polls
the same shape. One redirect per file hands those requests off to the release bucket:
[[redirect]] from = "/dl/latest/qwen3/everlock-linux-amd64v3" to = "https://everlock.s3.eu-central-1.amazonaws.com/dl/0.5.0/everlock-linux-qwen3-amd64v3" [[redirect]] from = "/dl/latest/qwen3/everlock-darwin-arm64" to = "https://everlock.s3.eu-central-1.amazonaws.com/dl/0.5.0/everlock-darwin-qwen3-arm64" # …one block per published (variant, platform)
A browser and reqwest both follow a 302 transparently — on HEAD as well as GET — so
the self-updater still reads the bucket's x-amz-meta-sha256 and Content-Disposition from
the redirected response and works without a change. The blocks are mechanical, so they are
generated at release time with the current version in each to.
Downloads (composed assets)
An [[asset]] serves a file at a URL with custom response headers. The body is the
concatenation of one or more parts — file paths in the store — so a large download is
assembled from stored pieces without holding the whole thing in memory.
[[asset]] url = "/downloads/tool.bin" parts = ["files/tool-v1.bin"] # one or more store paths, concatenated in order sha256 = "9aa4c9…" # optional hex digest of the assembled body [asset.headers] content-type = "application/octet-stream" content-disposition = 'attachment; filename="tool.bin"' cache-control = "public, max-age=31536000, immutable"
| Field | Description |
|---|---|
url | The request path this asset answers |
parts | Store file paths, streamed and concatenated in order to form the body |
sha256 | Optional hex digest of the assembled body (see below) |
[asset.headers] | Response headers applied verbatim (minus the reserved set) |
How it is served
GETstreams each part in order with bounded memory — roughly one part in flight — so a multi-gigabyte download costs tens of MB of RAM rather than its full size.HEADreturns the same headers with no body and reads no part bytes;Content-Lengthis the sum of the parts' sizes (a cheap store lookup). A client learns the size and digest without downloading.- When
sha256is set it is emitted as both anETag(soIf-None-Matchyields304) and anX-Everlock-SHA256header, letting a client compare a stored copy against the current bytes with a singleHEAD.
Reserved headers
[asset.headers] are applied verbatim except for the headers the server computes itself:
content-length, transfer-encoding, connection, keep-alive, and upgrade. Any other
header — content-type, content-disposition, cache-control, … — is yours to set.
Directory listings
Every non-leaf path above the declared assets renders an auto-generated index of its
immediate children. Assets at /downloads/a and /downloads/b make /downloads/ list a
and b. Drop an _index.md at that directory to render prose above the listing.
Why compose from parts?
For a single file, parts is just its one store path. Multiple parts matter when a large
blob is shared across downloads: each part is stored once in Git and reused, so many
released binaries that share the same model chunks cost the store only the bytes that
actually differ.
Choosing between them
Both can serve a download, so:
- Redirect when the bytes live elsewhere (object storage, a CDN). The client fetches the target directly and that host owns bandwidth, range requests, and caching.
- Composed asset when the bytes live in the site's own store and you want Everlock to
serve them with a fixed filename, a
HEAD-readable checksum, and on-the-fly assembly.