Specifying HTTP Headers
The headers section allows you to specify custom HTTP response headers for specific resources. The keys in the headers object are the exact paths of the resources (no wildcards), and the values are lists of key-value pairs corresponding to the headers that the portal attaches to the response.
This mechanism allows you to control various aspects of the resource delivery, such as caching, encoding, and content types.
{
"headers": {
"/index.html": {
"Content-Type": "text/html; charset=utf-8",
"Cache-Control": "max-age=3500"
},
"/assets/index.a1b2c3d4.js": {
"Content-Type": "application/javascript; charset=utf-8",
"Cache-Control": "max-age=31536000, immutable"
},
"/assets/index.e5f6a7b8.css": {
"Content-Type": "text/css; charset=utf-8",
"Cache-Control": "max-age=31536000, immutable"
},
"/downloads/report.pdf": {
"Content-Type": "application/pdf",
"Content-Disposition": "attachment; filename=\"report.pdf\""
}
}
}
In the example ws-resources.json, the file index.html is served with the Content-Type header set to text/html; charset=utf-8 and the Cache-Control header set to max-age=3500. The resource path is always represented as starting from the root /.
Defaults
By default, you do not need to specify any headers. The site-builder automatically tries to infer the Content-Type header based on the file extension, and sets the Content-Encoding to identity (no transformation).
If the content type cannot be inferred, the Content-Type is set to application/octet-stream. Any headers specified in the ws-resources.json file will override these defaults.
Content-Type
Set the Content-Type explicitly when the inferred type is incorrect, when you need to specify a charset, or when serving a file type the portal does not recognise.
"/feed.xml": { "Content-Type": "application/rss+xml; charset=utf-8" }
"/app.wasm": { "Content-Type": "application/wasm" }
"/fonts/x.woff2": { "Content-Type": "font/woff2" }
"/data.csv": { "Content-Type": "text/csv; charset=utf-8" }
For raw markdown files served for LLM ingestion, use lowercase content-type.
Cache-Control
Walrus blobs are immutable, so assets with build-hashed filenames can be cached forever. Entry points should never be cached.
"/index.html": { "Cache-Control": "no-cache" }
"/assets/app.a1b2c3d4.js": { "Cache-Control": "max-age=31536000, immutable" }
"/assets/style.e5f6a7b8.css": { "Cache-Control": "max-age=31536000, immutable" }
"/data/prices.json": { "Cache-Control": "max-age=300" }
| Value | Meaning |
|---|---|
no-cache | Revalidate before each use |
no-store | Never cache |
max-age=31536000, immutable | Cache for 1 year (content never changes) |
max-age=3600 | Cache for 1 hour |
Content-Disposition
Controls whether the browser renders a resource inline or downloads it.
"/docs/guide.md": { "Content-Disposition": "inline" }
"/whitepaper.pdf": { "Content-Disposition": "inline" }
"/exports/data.csv": { "Content-Disposition": "attachment; filename=\"data-export.csv\"" }
Content-Encoding
Use when serving pre-compressed assets from your build pipeline.
"/assets/app.js.gz": {
"Content-Type": "application/javascript; charset=utf-8",
"Content-Encoding": "gzip"
},
"/assets/styles.css.br": {
"Content-Type": "text/css; charset=utf-8",
"Content-Encoding": "br"
}