docs/book/src/gateway/web-dashboard.md
gateway.web_dist_dir)The gateway daemon ships its HTTP API in the binary, but the web dashboard
HTML/JS/CSS lives on disk in a web/dist/ directory produced by Vite. The
gateway.web_dist_dir setting (and its {{#env-var-name gateway.web_dist_dir}}
schema-mirror env-var override) tells the daemon where that directory is.
When neither the setting nor a known fallback location contains a built
index.html, the gateway boots in API-only mode and the dashboard URL
returns a "not available" message.
{{#env-var web_dist}}
Then build the bundle once:
<div class="os-tabs-src">cargo web build
…and restart the daemon. The startup log changes from
Web dashboard: not available — no web/dist found. Build with `cargo web build` …
to
Web dashboard: serving from /absolute/path/to/zeroclaw/web/dist
gateway.web_dist_dir is an Option<String> pointing at the directory that
contains a built index.html. At gateway start, the daemon:
index.html on this machine.index.html on this machine;
falling back to auto-detect") and tries the auto-detect candidates below.GET / returns a "not available" message that points back here.The value is treated as a hint, not a hard requirement. A stale path (typo, host-specific path copied from another machine, missing build) demotes to auto-detect rather than crashing every dashboard request.
When gateway.web_dist_dir is unset (or set to a path with no index.html),
the daemon probes these locations in order and serves from the first one that
contains index.html:
| # | Candidate | When it matches |
|---|---|---|
| 1 | ./web/dist (relative to CWD) | Running cargo run from the repo root in dev |
| 2 | <dir-of-binary>/web/dist | The packaged binary ships web/dist next to itself |
| 3 | /zeroclaw-data/web/dist | Standard Docker / packaged-volume layout |
| 4 | /usr/share/zeroclawlabs/web/dist | AUR / system package install |
| 5 | ${XDG_DATA_HOME:-~/.local/share}/zeroclaw/web/dist | Prebuilt-binary installer (per-user) |
If you're on one of those distributions and the dashboard "just works", you
don't need to set gateway.web_dist_dir at all, the auto-detect found it.
web/distYou have three options. Pick whichever matches how you installed ZeroClaw.
git clone https://github.com/zeroclaw-labs/zeroclaw.git
cd zeroclaw
cargo web build # alias for `cargo run -p xtask --bin web -- build`
# auto-runs `npm install` on first run
The bundle lands in web/dist/. Point web_dist_dir at the absolute path of
that directory, or run the daemon from the repo root and let auto-detect
candidate 1 pick it up.
The full set of cargo web subcommands (dev, check, gen-api, etc.) is
documented in Building the web dashboard.
Release archives on the Releases page
ship the daemon with web/dist/ already populated alongside the binary.
Auto-detect candidate 2 finds it; no gateway.web_dist_dir configuration
needed.
The official Docker image places the bundle at /zeroclaw-data/web/dist
(auto-detect candidate 3). It works out of the box; you only need to set
web_dist_dir if you mount your own volume over that path.
The value is resolved with the standard config-layer order:
gateway.web_dist_dirEnv-var overrides apply to the in-memory Config only; they are never
persisted.
ZEROCLAW_gateway__web_dist_dirThe general operator override grammar (see Environment variables) maps the dotted TOML path to an env-var name mechanically:
TOML path: gateway.web_dist_dir
─────── ─────────────
section field-name (snake_case, kept as-is)
Env var: ZEROCLAW_gateway__web_dist_dir
───────── ── ────────────
prefix path-separator field-name
(`.` → `__`) (unchanged)
The same three steps produce env-var names for every other gateway knob,
e.g. gateway.request_timeout_secs becomes
{{#env-var-name gateway.request_timeout_secs}}.
~ or $HOMEA literal tilde is not expanded by the gateway; use an absolute path for gateway.web_dist_dir. Shell variables ($HOME, %USERPROFILE%) are likewise not expanded; pre-expand them in the env var if you set the value that way:
{{#env-var web_dist_home}}
Companion PR #6961 adds
the targeted "looks like an unexpanded ~ / $VAR,
shellexpand it before writing this
value" check tracked in
issue #6079 to both
zeroclaw doctor and zeroclaw self-test as a Warn-severity diagnostic.
Neither command surfaces it on current master, until #6961 lands, expand
~ / $VAR yourself before writing gateway.web_dist_dir (for example
write /home/alice/zeroclaw/web/dist instead of ~/zeroclaw/web/dist).
web_dist_dir = "web/dist" is interpreted relative to the daemon's working
directory at start time, not relative to the config location. If
you ship a config to another host or invoke the daemon from a different
directory (e.g. via systemd), the relative form will look in the wrong place.
Use absolute paths for web_dist_dir.
WARN gateway.web_dist_dir points at a path that doesn't contain index.html
on this machine; falling back to auto-detect. Update or remove the setting
to silence this warning.
This means the path is syntactically valid but the file isn't there yet.
Either run cargo web build, fix the path, or remove the setting entirely
and let auto-detect handle it.
INFO Web dashboard: not available — no web/dist found. Build with
`cargo web build` and point gateway.web_dist_dir at the resulting
web/dist directory.
API endpoints still work, only the HTML/JS bundle is missing. Build it (option A/B/C above) or set the path.
cargo web subcommands and what gets generated