Config Reference
The yourspace.yml file describes how your site is served — routing, redirects, TLS, custom domains, error pages. This page is both the authoritative reference (every field the current server recognizes, with types and limits) and a guide for common patterns. Fields not listed here are ignored.
What's live today
Path matching, response headers, redirects,
domain_redirects, error_pages, spa,
custom domains, and TLS are all active. A route's target,
cache, ttl, and edge values parse and
validate today but currently resolve to static file serving regardless of
value — the origin-proxy, cache-layer, and edge-function semantics land with
their respective workstreams. The fields are stable, so config written for
them now keeps working once the behaviour ships.
Minimal config
name: my-site routes: - path: /*
A single required field (name) and one implicit default (/* serves the bundle) is enough to deploy. Everything else is optional.
Fully populated example
name: my-site
origin: https://localhost:3000
tls:
auto: true
custom_domains:
- foobar.com
- www.foobar.com
spa: false
routes:
- path: /api/*
target: origin
cache: none
- path: /*
target: edge-nearest
cache: 1h
headers:
x-frame-options: DENY
error_pages:
404: /404.html
500: /500.html
redirects:
- from: /old
to: /new
status: permanent
- from: /legacy/*
to: /archive/*
domain_redirects:
- from: www.foobar.com
to: foobar.com
How the config is evaluated
Requests flow through the config in a fixed order:
- Host match. If the request's Host header matches a
domain_redirectsentry, the edge replies with the redirect before touching paths. - Path redirects.
redirectsare evaluated next, in declaration order. The firstfromthat matches wins. - Routes.
routesare checked in declaration order; the firstpaththat matches selects the route (and applies itsheaders). Whenroutesis omitted, an implicit/*→ serve-bundle rule applies. (target/cache/ttl/edgeparse but resolve to static file serving today — see the callout above.) - File serving. If the request falls through to the file server and no file matches,
error_pagesproduces the error response.spa: trueshort-circuits this by serving/index.htmlwith status 200 for unknown paths.
Precedence between scopes:
error_pages: per-route entries override site-level entries; auto-detected files (e.g. a404.htmlat the bundle root) fill in any codes not explicitly configured.cachevsttl:cachewins when both are set on the same route.ttlis a convenience alias.
Top-level fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Site name (lowercase letters, digits, hyphens; ≤ 63 chars). Becomes the <name>.yo.urspace.net subdomain. |
build | object | no | Client-only tooling hints consumed by the CLI. The server ignores this block entirely — fields under it never reach or round-trip through the API. See build. |
origin | string | no | Default upstream for routes whose target is origin (planned — pairs with the origin-proxy workstream; see the routes.target note). Example: https://localhost:3000. |
tls | object | no | TLS certificate options. See tls. |
routes | list | no | Request-path routing rules, evaluated in order. See routes. |
custom_domains | list of string | no | External hostnames this site expects to serve. Informational at MVP — binding and DNS verification run through the /v1/sites/{name}/domains API; this list is cross-checked on deploy for drift. |
spa | bool | no | When true, unknown paths fall back to /index.html with status 200. Fixes client-side-routed PWA direct loads. Whole-site scope in v1. |
error_pages | map of int → string | no | Site-level HTTP status → bundle-relative file path. Served instead of the default error response. Per-route error_pages take precedence. |
redirects | list | no | Path-level redirects evaluated before file serving. See redirects. |
domain_redirects | list | no | Host-level redirects from verified custom domains. See domain_redirects. |
build
Client-only namespace: the CLI reads fields under build: for local tooling decisions. The server never stores or echoes anything in this block, so it's a safe place for future tool-specific hints without touching the server schema.
| Field | Type | Description |
|---|---|---|
dist | string | Subdirectory containing the built site to deploy. Defaults to the project root when absent. Set to . to ship the project root explicitly. Overridable per-run with yourspace deploy --dist <path>. Paths are resolved relative to the yourspace.yml file's directory; absolute paths and .. escapes are rejected at pre-flight. |
Example:
name: my-site
build:
dist: ./dist
tls
| Field | Type | Description |
|---|---|---|
auto | bool | Enable automatic certificate management (ACME). The typical production setting. |
cert | string | Path to a user-provided TLS certificate (PEM). Ignored when auto: true. |
key | string | Path to a user-provided TLS key (PEM). Ignored when auto: true. |
Use auto: true for the default case. Use cert/key when you need to pin a specific certificate (e.g. an internal CA, or an existing wildcard cert).
routes
Each entry matches a request path and decides where it goes. Routes are checked in declaration order; the first match wins, so put narrow matches first and catch-alls last.
| Field | Type | Required | Description |
|---|---|---|---|
path | string | yes | Match pattern, e.g. /api/*. Single-segment * and recursive ** wildcards are supported. |
target | string | no | Where matched requests go: origin, cache, edge-nearest, or a URL (planned — parses today, resolves to static file serving until the origin-proxy/cache workstreams land). |
cache | string | no | Cache policy: none or a duration like 30m, 1h, 7d (planned — see target). |
ttl | string | no | Alias for cache duration. Ignored when cache is set explicitly. |
headers | map of string → string | no | Response headers merged into the response. Useful for CORS, cache-control, and security headers. |
edge | string | no | Name of an edge function to run for matching requests (planned — parses today, executes when the edge-function workstream lands). Functions will live in ./edge/<name>.js. |
error_pages | map of int → string | no | Per-route HTTP status → bundle-relative file path. Overrides the site-level error_pages for requests matching this route. |
Example: per-route caching and headers
routes:
- path: /api/*
target: origin
cache: none
headers:
access-control-allow-origin: "*"
- path: /assets/*
target: cache
ttl: 7d
headers:
cache-control: "public, max-age=604800"
- path: /*
target: edge-nearest
cache: 1h
error_pages:
404: /missing.html
The order matters: /api/* and /assets/* are specific prefixes and must appear before the /* catch-all, or they'd never match. Each route gets its own cache policy, header set, and optional error page.
redirects
Path redirects evaluated before the file-server layer. Exact paths and trailing /* wildcards are both supported.
| Field | Type | Required | Description |
|---|---|---|---|
from | string | yes | Source path. A trailing /* makes it a prefix wildcard. |
to | string | yes | Target path. The suffix behaviour depends on whether to ends in /* — see the three modes below. |
status | int or alias | no | Redirect status. Defaults to 301. Accepts an integer or one of the aliases below. |
Three modes, picked by whether from and to end in /*. The shape mirrors the from_path/to_path modes in domain_redirects:
- Exact — neither side uses
/*:/old → /newredirects only the literal path/old. - Prefix swap — both sides use
/*:/blog/* → /news/*rewrites the prefix and carries the captured suffix./blog/2024/post→/news/2024/post. - Fixed target — only
fromuses/*:/blog/* → /closedlands every matching path on one literal target./blog/anything→/closed.
from without /* paired with to ending in /* is rejected — the target would contain a literal *.
Redirect status aliases
Use the alias that matches your intent; the server sends the corresponding HTTP code.
| Alias | HTTP code | When to use it |
|---|---|---|
permanent | 301 | Most static-site redirects (default). Browsers and crawlers cache the redirect indefinitely. |
temporary | 302 | The move may reverse. Browsers may rewrite the method to GET when following. |
see-other | 303 | Always GET the target, even when the original was POST (POST-redirect-GET pattern). |
temporary-strict | 307 | Temporary, but preserves the HTTP method and body. |
permanent-strict | 308 | Permanent, but preserves the HTTP method and body. Note: some older HTTP clients don't follow 308. |
Example: legacy-path cleanup
redirects:
- from: /blog/*
to: /archive/blog/*
status: permanent
- from: /contact
to: /about#contact
- from: /old-api/*
to: https://api.example.com/*
status: see-other
domain_redirects
Host-level redirects: traffic arriving on one verified custom domain is sent to a different host. The source must already be bound to the site via the domains API; validation runs at deploy time, not parse time.
| Field | Type | Required | Description |
|---|---|---|---|
from | string | yes | Source hostname (verified custom domain). |
to | string | yes | Target hostname. Must differ from from. |
from_path | string | no | Scope the redirect to a path prefix on the source host. Trailing /* required when paired with to_path. |
to_path | string | no | Override the destination path. See path modes below. |
status | int or alias | no | Same values and default as redirects.status. |
Three path modes select based on which of from_path / to_path are set:
- Preserve — neither
from_pathnorto_path: original path and query string are kept.www.foobar.com/blog→foobar.com/blog. - Fixed target —
to_pathonly: all traffic redirects to one literal path.old.foobar.com/<anything>→foobar.com/notice. - Prefix swap —
from_path/*+to_path/*: prefix replaced, suffix preserved.docs.foobar.com/guides/start→foobar.com/docs/guides/start.
Example: www → apex canonical
custom_domains:
- foobar.com
- www.foobar.com
domain_redirects:
- from: www.foobar.com
to: foobar.com
status: permanent
Gotchas
fromcannot equalto(would be an instant loop).- Duplicate
fromentries are rejected — the first match wins, so declaring two is ambiguous. fromcannot match your own<name>.yo.urspace.netsubdomain — the redirect would intercept your primary traffic and make the site unreachable.- A → B and B → A inside the same site is detected and rejected as a redirect loop — this is provided as a convenience; preventing more complicated redirect loops (such as between three or more domains) is your responsibility 😉.
from_pathwithoutto_pathis ambiguous; omit both for path-preserve, or set both for prefix swap.
Common patterns
Single-page application (SPA) with a custom 404
A single-page application (SPA) routes client-side: every URL renders the same index.html and an in-page router selects which view to show. Direct loads of non-root paths — a refresh, a bookmark, a shared link — require the server to return that index.html rather than a 404; otherwise the in-page router never executes and the visitor sees the default 404.
name: my-app spa: true error_pages: 404: /404.html
spa: true serves /index.html for unknown paths (status 200) so the client-side router can handle them. error_pages[404] is still useful for genuinely missing resources like images or API endpoints that fall through to the file server.
Limits
Validation rejects any config that exceeds these limits. The intent is defence-in-depth against runaway configs, not a throttling policy — real quotas live at the API layer.
| Limit | Value |
|---|---|
routes entries | 50 |
redirects entries | 100 |
domain_redirects entries | 20 |
error_pages entries (per scope) | 20 |
name length | 63 characters |
| Path length (any field) | 256 characters |
| Hostname length | 253 characters |
Path and hostname validation
Every path and hostname is validated at parse time. Configs containing any of the following are rejected before they reach the proxy layer:
- Paths that don't start with
/. - Path traversal (
..) in any segment. - Control characters (CR, LF, tab, NUL) and curly braces (
{,}) in paths or hostnames. - Hostnames with a scheme, port, path, or spaces.
- Hostnames without a dot (must be fully qualified).