Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Routing config schema

The routing section of project.cfg is the deploy-scoped config tier. It is authored in RON, parsed at sync, and folded into the immutable deployment manifest — so it is atomic with the content and rolls back with it. Every field is optional; an empty routing: () is all defaults.

Validate it without publishing:

boatramp validate
project.cfg: routing OK (2 redirects, 1 handler)

Top-level fields

FieldTypeDefaultDescription
versionu321Schema version, pinned at 1.
indexlist<string>["index.html"]Directory-index candidates, tried in order.
clean_urlsboolfalseMap extensionless URLs to .html (/about/about.html).
case_insensitiveboolfalseMatch paths case-insensitively against redirects, rewrites, and files.
trailing_slashenumPreserveTrailing-slash policy — see below.
error_documentsmap<u16, string>{}Status code → error document (404: "/404.html").
redirectslist<Redirect>[]Redirect rules, first match wins.
rewriteslist<Rewrite>[]Internal-rewrite or reverse-proxy rules, first match wins.
headerslist<HeaderRule>[]Response-header rules; every matching rule applies, in order.
cacheCacheConfigDefault Cache-Control — see below.
mime_overridesmap<string, string>{}Extension → MIME override (".webmanifest": "...").
proxy_allowlist<string>[]Allowed upstream hosts for proxy rewrites — see below.
handlerslist<HandlerConfig>[]WebAssembly request handlers, matched after redirects, before static lookup.
consumerslist<ConsumerConfig>[]Message-consumer components, invoked per message on a topic.
cronslist<CronConfig>[]Scheduled handler invocations.
streamslist<StreamConfig>[]Host-level SSE / WebSocket endpoints fanning out topics.

Pattern fields (from, matches, handler route) use the path matcher syntax and are compiled at validate/sync, so a bad pattern fails at deploy time rather than at request time.

trailing_slash

ValueEffect
PreserveLeave the path as-is (default).
AlwaysRedirect to add a trailing slash.
NeverRedirect to strip a trailing slash.

redirects

Each rule redirects a matching path. First match wins.

FieldTypeDefaultDescription
frompatternSource path pattern.
tostringDestination, with :name / :splat substitution.
statusu16308HTTP status. 308 is permanent and method-preserving.
redirects: [ (from: "/old/:slug", to: "/new/:slug", status: 301) ],

rewrites

A rewrite serves a different resource without changing the URL. An internal to (a path) rewrites; an absolute-URL to reverse-proxies to that upstream. First match wins.

FieldTypeDefaultDescription
frompatternSource path pattern.
tostringInternal path or absolute proxy URL, with :name / :splat substitution.
statusu16200Status served for an internal rewrite (e.g. 200 for SPA fallback).

An SPA fallback is a rewrite of everything to the app shell:

rewrites: [ (from: "/*", to: "/index.html", status: 200) ],

Proxy rewrites are constrained by proxy_allow.

headers

Each rule sets or removes response headers on matching paths. All matching rules apply, in order.

FieldTypeDescription
matchespatternPath pattern (named matches because for is a keyword).
setmap<string, string>Headers to set.
unsetlist<string>Header names to remove.
headers: [ (matches: "/assets/*", set: { "Cache-Control": "public, max-age=31536000, immutable" }) ],

cache

FieldTypeDescription
defaultstring?Default Cache-Control for responses not covered by a header rule.

proxy_allow

Upstream hosts a proxy rewrite may target. An entry is an exact host or a .suffix for a subtree (.internal.example.com). When the list is empty, proxying to any public host is allowed; private, loopback, and link-local addresses are always blocked as an SSRF guard, regardless of this list. To proxy to a private address, declare a gateway upstream instead.

handlers

A WebAssembly handler bound to a route. Matched after redirects, before static lookup. See Deploy a handler.

FieldTypeDefaultDescription
routepatternRoute pattern.
methodslist<string>[] (all)HTTP methods answered (GET, POST, …).
componentstringPath to the component .wasm within the deployment.
importslist<string>[]Requested capabilities — see imports.
limitsHandlerLimitsOptional resource caps, intersected with the site caps at activation.
envmap<string, string>{}Static environment variables. Never secrets — a credential-shaped value is rejected at validate; use [handlers].secrets in boatramp.cfg for those.

imports

The capability vocabulary a handler may request. An unrecognized import is rejected at validate.

ImportGrants
wasi:httpOutbound HTTP.
wasi:keyvaluePer-site KV store.
wasi:blobstorePer-site blob store.
wasi:messagingPublish / subscribe on topics.
sqlPer-site SQL database.
wasi:io, wasi:clocks, wasi:random, wasi:loggingStandard host facilities.

The site’s allow_imports is the allowlist; a handler requesting an import the site does not permit is denied at activation.

limits (HandlerLimits)

FieldTypeDescription
memory_mbu32?Max linear memory, MiB.
timeout_msu32?Wall-clock timeout, ms.
fuelu64?CPU budget in wasmtime fuel units (deterministic instruction-count bound). Omitted = unmetered.

Each field may only lower the corresponding site cap, never raise it.

consumers

A component invoked once per message on a topic. See Run consumers, crons, and streams.

FieldTypeDescription
topicstringTopic to subscribe to (namespaced).
componentstringPath to the component .wasm.
importslist<string>Requested capabilities.

crons

A scheduled invocation of a declared handler route.

FieldTypeDefaultDescription
schedulestringStandard 5-field cron (minute hour dom month dow).
routestringHandler route to invoke; must be served by a declared handler.
overlapenumSkipSkip a tick if the previous run is still in flight, or Allow concurrent runs.

streams

A host-level endpoint that fans out messaging topics to connected clients.

FieldTypeDefaultDescription
routestringRoute the endpoint is served at.
topicslist<string>Topics broadcast to clients (server→client).
websocketboolfalseServe as a WebSocket instead of SSE (adds a client→server direction).
publish_topicstring?For a WebSocket, the topic client→server messages publish to. Omitted = receive-only.

Patterns

Route, redirect, rewrite, and header patterns share one matcher syntax:

TokenMatchesCapture
:nameOne path segment:name in to
* / /*The rest of the path:splat in to
literalItself

Path normalization (dot-segment collapsing, the trailing-slash policy) runs before matching, so patterns always see a canonical path and cannot be bypassed with .. or a double slash. See The request pipeline.