docs

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:

  1. Host match. If the request's Host header matches a domain_redirects entry, the edge replies with the redirect before touching paths.
  2. Path redirects. redirects are evaluated next, in declaration order. The first from that matches wins.
  3. Routes. routes are checked in declaration order; the first path that matches selects the route (and applies its headers). When routes is omitted, an implicit /* → serve-bundle rule applies. (target/cache/ttl/edge parse but resolve to static file serving today — see the callout above.)
  4. File serving. If the request falls through to the file server and no file matches, error_pages produces the error response. spa: true short-circuits this by serving /index.html with status 200 for unknown paths.

Precedence between scopes:

  • error_pages: per-route entries override site-level entries; auto-detected files (e.g. a 404.html at the bundle root) fill in any codes not explicitly configured.
  • cache vs ttl: cache wins when both are set on the same route. ttl is a convenience alias.

Top-level fields

FieldTypeRequiredDescription
namestringyesSite name (lowercase letters, digits, hyphens; ≤ 63 chars). Becomes the <name>.yo.urspace.net subdomain.
buildobjectnoClient-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.
originstringnoDefault upstream for routes whose target is origin (planned — pairs with the origin-proxy workstream; see the routes.target note). Example: https://localhost:3000.
tlsobjectnoTLS certificate options. See tls.
routeslistnoRequest-path routing rules, evaluated in order. See routes.
custom_domainslist of stringnoExternal 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.
spaboolnoWhen true, unknown paths fall back to /index.html with status 200. Fixes client-side-routed PWA direct loads. Whole-site scope in v1.
error_pagesmap of int → stringnoSite-level HTTP status → bundle-relative file path. Served instead of the default error response. Per-route error_pages take precedence.
redirectslistnoPath-level redirects evaluated before file serving. See redirects.
domain_redirectslistnoHost-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.

FieldTypeDescription
diststringSubdirectory 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

FieldTypeDescription
autoboolEnable automatic certificate management (ACME). The typical production setting.
certstringPath to a user-provided TLS certificate (PEM). Ignored when auto: true.
keystringPath 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.

FieldTypeRequiredDescription
pathstringyesMatch pattern, e.g. /api/*. Single-segment * and recursive ** wildcards are supported.
targetstringnoWhere 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).
cachestringnoCache policy: none or a duration like 30m, 1h, 7d (planned — see target).
ttlstringnoAlias for cache duration. Ignored when cache is set explicitly.
headersmap of string → stringnoResponse headers merged into the response. Useful for CORS, cache-control, and security headers.
edgestringnoName 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_pagesmap of int → stringnoPer-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.

FieldTypeRequiredDescription
fromstringyesSource path. A trailing /* makes it a prefix wildcard.
tostringyesTarget path. The suffix behaviour depends on whether to ends in /* — see the three modes below.
statusint or aliasnoRedirect 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 → /new redirects 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 from uses /*: /blog/* → /closed lands 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.

AliasHTTP codeWhen to use it
permanent301Most static-site redirects (default). Browsers and crawlers cache the redirect indefinitely.
temporary302The move may reverse. Browsers may rewrite the method to GET when following.
see-other303Always GET the target, even when the original was POST (POST-redirect-GET pattern).
temporary-strict307Temporary, but preserves the HTTP method and body.
permanent-strict308Permanent, 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.

FieldTypeRequiredDescription
fromstringyesSource hostname (verified custom domain).
tostringyesTarget hostname. Must differ from from.
from_pathstringnoScope the redirect to a path prefix on the source host. Trailing /* required when paired with to_path.
to_pathstringnoOverride the destination path. See path modes below.
statusint or aliasnoSame values and default as redirects.status.

Three path modes select based on which of from_path / to_path are set:

  • Preserve — neither from_path nor to_path: original path and query string are kept. www.foobar.com/blogfoobar.com/blog.
  • Fixed targetto_path only: all traffic redirects to one literal path. old.foobar.com/<anything>foobar.com/notice.
  • Prefix swapfrom_path/* + to_path/*: prefix replaced, suffix preserved. docs.foobar.com/guides/startfoobar.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

  • from cannot equal to (would be an instant loop).
  • Duplicate from entries are rejected — the first match wins, so declaring two is ambiguous.
  • from cannot match your own <name>.yo.urspace.net subdomain — 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_path without to_path is 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.

LimitValue
routes entries50
redirects entries100
domain_redirects entries20
error_pages entries (per scope)20
name length63 characters
Path length (any field)256 characters
Hostname length253 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).