Deployment

Braised builds a self-contained dist/ directory of static HTML, CSS, and JS. Serve it with any static host, CDN, or reverse proxy. This page covers the options that affect how assets and links are generated at build time.

Root-hosted sites

No configuration needed. Build once, copy dist/ to your host:

braised build
rsync -av dist/ user@host:/var/www/html/

Sub-path deployment

When a site is served from a path prefix (e.g. /docs or /staging/my-branch) rather than a domain root, the default root-relative asset links (/assets/braised.css) will 404. Set base_url in braised.yaml to prefix all generated links:

site:
  base_url: /docs

base_url is applied to every root-relative URL Braised outputs: asset tags, the home link, navigation, content links, braised:ref/ cross-references, and images. Relative links, fragment links, and external URLs are never changed. Write content paths relative to the site root — never include the prefix yourself.

Canonical URLs, og:url, and sitemap.xml use site.url instead, which is independent of base_url. For a sub-path site, set url to the full public address including the path. See url and base_url are independent.

Nginx example

location /docs/ {
    alias /var/www/html/docs/;
    try_files $uri $uri/ /docs/index.html;
}
# braised.yaml
site:
  base_url: /docs

Multiple environments

For sites where the base path changes between environments (e.g. root in production, /staging/<branch> in PR previews), keep the production value in braised.yaml and override it per environment. Usually only base_url changes: keep url pointing at production so staging pages declare the production page as canonical.

Environment variable substitution

Any value in braised.yaml can reference environment variables using ${VAR} syntax. Unset variables resolve to an empty string and produce a build warning:

site:
  title: My Docs
  base_url: ${BRAISED_BASE_URL}
# production — BRAISED_BASE_URL unset → empty → root-hosted
braised build

# staging
BRAISED_BASE_URL=/staging/my-branch braised build

Alternate config file

For larger differences between environments (different output dirs, pipeline endpoints, etc.), maintain a separate config file and pass it with --config:

# braised-prod.yaml
site:
  title: My Docs
  url: https://docs.example.com
  base_url: /docs
pipeline:
  command: python3 scripts/ingest-prod.py
braised build --config braised-prod.yaml

When --config is given without an explicit site directory, braised uses the directory containing the config file as the site root (so docs/, nav.yaml, and dist/ are resolved relative to it).

GitHub Actions

jobs:
  deploy-staging:
    steps:
      - uses: actions/checkout@v4
      - run: braised build
        env:
          BRAISED_BASE_URL: /staging/${{ github.ref_name }}
      - run: rsync -av dist/ user@staging:/var/www/html/staging/${{ github.ref_name }}/

  deploy-production:
    steps:
      - uses: actions/checkout@v4
      - run: braised build --config braised-prod.yaml
      - run: rsync -av dist/ user@prod:/var/www/html/docs/