Dev Server
Dev Server¶
Run a static server with auto-reload over SSE.
pip install .
wyb dev --dir . --host 127.0.0.1 --port 8000 --watch src examples --open \
--mount /=. --mount /examples=examples --mount /src=src
Behavior:
- Watches
--watchdirectories for file mtime changes - Notifies browser via
/__sseevents; demo subscribes and reloads the page - Binds to the requested port or the next available up to +20
- Serves additional static directories using
--mount /prefix=path(repeatable) - Optionally opens the browser with
--openand--open-path /examples/demo/ - Prints the resolved host/port, selected port (if your requested one was busy), active mounts, and watched paths at startup
Options:
--mount /prefix=path: mount filesystempathat the given URL prefix. The longest-prefix match wins.--open: open the default browser to the server URL after it starts.--open-path: append this path when opening the browser, e.g./examples/demo/.
Advanced usage¶
- Multiple mounts and base URLs
- The server maps URL prefixes to filesystem directories. The longest-prefix match wins.
-
Example: serve repo root at
/, demo at/examples, and source at/src:bash wyb dev --dir . \ --mount /=. \ --mount /examples=examples \ --mount /src=src \ --open --open-path /examples/demo/ -
Host/port selection and fallbacks
- Defaults:
--host 127.0.0.1,--port 8000. - If the requested port is busy, the server tries the next 20 ports and prints which one was selected.
-
To expose on your LAN or containers, use
--host 0.0.0.0and open via your machine IP. -
Auto-open behavior
--openlaunches your default browser to the server URL.-
If
--open-pathis omitted, the server heuristically opens/ifindex.htmlexists under--dir, otherwise/examples/demo/if present, otherwise/. -
Watching and reload delay
--watchaccepts a list of directories; defaults tosrc examples.- File change detection is based on mtimes and checks ~every 0.5s. Expect a ~0.5–1.5s full page reload.
-
To disable auto-reload entirely, pass
--watchwith no values:bash wyb dev --dir . --watch --mount /=. -
SSE endpoint for reloads
- The dev server exposes
GET /__ssewhich streamsreloadevents. The demo subscribes and callslocation.reload(). -
Integrate into your own app with a minimal client:
js const es = new EventSource("/__sse"); es.addEventListener("reload", () => location.reload()); -
Cache busting in development
- All responses include
Cache-Control: no-store, max-age=0. -
For ES modules, also append a timestamp query param to avoid module graph caching by the browser:
html <script type="module"> import(`./bootstrap.js?v=${Date.now()}`); </script> -
Path safety and traversal
- The server sanitizes paths (
.,..) before mapping to the filesystem; use mounts instead of relative escapes. -
For a base-path style setup, mount your app under a prefix (e.g.,
--mount /app=dist) and open--open-path /app/. -
Not for production
- This server is built on Python's
http.serverand is intended for development only.
Troubleshooting¶
- Auto-reload not firing
- Confirm the dev server is running and
GET /__sseshows an open EventSource connection in your browser's Network panel. - Ensure your changed files live under the
--watchdirectories; add or adjust entries accordingly. -
Behind proxies: make sure
/__sseis passed through unbuffered (e.g., Nginxproxy_buffering off;andX-Accel-Buffering: no). -
Stale assets
-
Verify
Cache-Control: no-storeon responses. For modules, include a?v=${Date.now()}cache-buster as shown above. -
Port is already in use
- The server will pick the next free port and print a notice. If you need the exact port, stop the conflicting process.
-
macOS example:
lsof -i :8000thenkill -9 <PID>. -
Browser did not open
--openrelies on the system default browser; some headless or remote setups may block it.-
Provide an explicit
--open-pathor copy the printed URL into your browser manually. -
Mounts not serving as expected
- Prefixes must start with
/(added automatically if omitted). Paths are resolved relative to--dirwhen not absolute. -
When multiple mounts could match, the longest URL prefix wins. Check the startup "Mounts:" list to verify mapping.
-
Exposing on the network
- Use
--host 0.0.0.0and ensure firewalls allow inbound traffic to the selected port.
See also: the general troubleshooting page under Meta → Troubleshooting.
Cache busting (development):
- The server sends
Cache-Control: no-storefor all static responses to avoid stale assets during development. - The demo HTML dynamically imports
bootstrap.jswith a timestamp query param to ensure the module itself is refreshed:
<script type="module">
const v = Date.now();
import(`./bootstrap.js?v=${v}`);
\/script>
Error overlay (development only):
- The demo
bootstrap.jsnow shows a lightweight in-browser overlay when a Python exception or JS error occurs during app startup. It also listens for unhandled promise rejections. - The overlay is dismissed via the "Dismiss" button and will be replaced on subsequent errors.