Skip to content

Dev server (CLI)

wybthon.dev

dev

Simple threaded dev server with live-reload via Server-Sent Events.

wyb dev serves a directory over HTTP, broadcasts a reload event on file change through /__sse, and exposes a small /__manifest endpoint that bootstrap scripts can use to discover application modules without maintaining a hardcoded file list.

Use the main function for CLI entry, or call serve directly to embed the server.

Classes:

Name Description
SSEHandler

HTTP handler that serves files and a /__sse endpoint for reload events.

Functions:

Name Description
translate_request_path

Translate a URL path to a filesystem path using mounts and a root fallback.

parse_mounts

Parse --mount CLI arguments of the form /prefix=path.

serve

Run a static dev server with auto-reload for directory.

main

CLI entry point for the wyb development server.

SSEHandler

Bases: SimpleHTTPRequestHandler

HTTP handler that serves files and a /__sse endpoint for reload events.

Class attributes

watchers: List of wfile objects for connected SSE clients; updated as clients connect and disconnect. root: Filesystem root used as the fallback when no mount matches the request path. mounts: List of (prefix, path) mounts consulted by translate_request_path.

Methods:

Name Description
end_headers

Append no-cache headers to every response to avoid stale assets.

do_GET

Dispatch requests to the SSE endpoint, manifest endpoint, or static handler.

translate_path

Translate a URL path to a filesystem path honoring configured mounts.

notify_reload

Send a reload SSE event to every connected client.

end_headers

end_headers() -> None

Append no-cache headers to every response to avoid stale assets.

do_GET

do_GET()

Dispatch requests to the SSE endpoint, manifest endpoint, or static handler.

translate_path

translate_path(path: str) -> str

Translate a URL path to a filesystem path honoring configured mounts.

notify_reload classmethod

notify_reload() -> None

Send a reload SSE event to every connected client.

translate_request_path

translate_request_path(path: str, root: Path, mounts: list[tuple[str, Path]]) -> Path

Translate a URL path to a filesystem path using mounts and a root fallback.

Parameters:

Name Type Description Default
path str

Incoming URL path.

required
root Path

Filesystem root used when no mount matches.

required
mounts list[tuple[str, Path]]

List of (prefix, base) pairs. Longest prefix wins.

required

Returns:

Type Description
Path

Concrete filesystem path. Directory traversal segments are

Path

stripped before the path is constructed.

parse_mounts

parse_mounts(mount_args: Iterable[str], base_dir: Path) -> list[tuple[str, Path]]

Parse --mount CLI arguments of the form /prefix=path.

  • Prefix must start with /; one is added when missing.
  • Paths are resolved relative to base_dir when not absolute.
  • Duplicate prefixes are allowed; resolution order is determined by translate_request_path.

Parameters:

Name Type Description Default
mount_args Iterable[str]

Raw CLI strings.

required
base_dir Path

Directory used to resolve relative paths.

required

Returns:

Type Description
list[tuple[str, Path]]

A list of (prefix, path) tuples ready to assign to

list[tuple[str, Path]]

serve

serve(directory: str, host: str = '127.0.0.1', port: int = 8000, watch: Iterable[str] = ('src', 'examples'), mounts: Iterable[str] | None = None, open_browser: bool = False, open_path: str | None = None) -> None

Run a static dev server with auto-reload for directory.

Parameters:

Name Type Description Default
directory str

Filesystem root to serve.

required
host str

Bind host.

'127.0.0.1'
port int

Preferred port. If busy, the server tries the next 20 ports before failing.

8000
watch Iterable[str]

Directories to recursively watch for change events.

('src', 'examples')
mounts Iterable[str] | None

Optional list of --mount strings like /static=path/to/static.

None
open_browser bool

When True, open a browser tab to the served URL after binding.

False
open_path str | None

Path to open when open_browser is True. When omitted, falls back to a sensible default based on content found in directory.

None

main

main(argv: list[str] | None = None) -> int

CLI entry point for the wyb development server.

Parameters:

Name Type Description Default
argv list[str] | None

Optional argument list (defaults to sys.argv[1:]).

None

Returns:

Type Description
int

Process exit code: 0 on success, non-zero on usage errors.

What's in this module

dev implements the simple threaded development server invoked by the wyb dev command. It serves static files from your project, mounts extra directories at custom URL prefixes, and exposes a Server-Sent Events (SSE) endpoint at /__sse for live reload.

You usually run it via the CLI:

wyb dev --dir . --port 8000 --watch src --watch examples
Flag Default Description
--dir . Root directory to serve.
--host 127.0.0.1 Host interface to bind.
--port 8000 Starting port (auto-increments on conflict).
--watch src, examples Directories to watch for live reload.
--mount (none) path=/url/prefix mount; can be repeated.

How live reload works

  1. The browser opens an EventSource to /__sse.
  2. The server walks --watch directories and notes file modification times.
  3. When something changes, the server pushes a reload event over SSE.
  4. The page reloads itself in response.

The demo's index.html includes a tiny snippet that listens for these events; you can copy it into your own apps.

See also