Module

server.live_reload

Live reload functionality for the dev server.

Provides Server-Sent Events (SSE) endpoint and HTML injection for hot reload.

Architecture:

  • SSE Endpoint (/bengal_reload): Maintains persistent connections to clients
  • Live Reload Script: Injected into HTML pages to connect to SSE endpoint
  • Reload Notifications: Broadcast to all clients when build completes using a global generation counter and condition variable (no per-client queues)

SSE Protocol:

Client: EventSource('/__bengal_reload__')
Server (init): retry: 2000

(client waits 2s before reconnect after disconnect) Server (events): data: {json payload}|reload

(triggers reload/css update) Server (idle): : keepalive

(sent on interval; ignored by client)

Dev behavior:

  • Keepalive interval is configurable via env BENGAL_SSE_KEEPALIVE_SECS (default 15s).
  • On new connections/reconnects, last_seen_generation is initialized to the current generation so we do not replay the last reload event to the client.

Classes

LiveReloadMixin
Mixin class providing live reload functionality via SSE. This class is designed to be mixed into a…
3

Mixin class providing live reload functionality via SSE.

This class is designed to be mixed into an HTTP request handler.

It provides two key methods:

  • handle_sse(): Handles the SSE endpoint (/bengal_reload)
  • serve_html_with_live_reload(): Injects the live reload script into HTML

The SSE connection remains open, sending keepalive comments roughly every 9 seconds and "reload" messages (or JSON payloads) when the site is rebuilt.

Attributes

Name Type Description
path str
client_address tuple[str, int]
wfile BufferedIOBase

Methods 2

handle_sse
Handle Server-Sent Events endpoint for live reload. Maintains a persistent HTT…
0 None
def handle_sse(self) -> None

Handle Server-Sent Events endpoint for live reload.

Maintains a persistent HTTP connection and sends SSE messages:

  • Keepalive comments (: keepalive) every 30 seconds
  • Reload events (data: reload) when site is rebuilt

The connection remains open until the client disconnects or an error occurs.

serve_html_with_live_reload
Serve HTML file with live reload script injected (with caching). Uses file mod…
0 bool
def serve_html_with_live_reload(self) -> bool

Serve HTML file with live reload script injected (with caching).

Uses file modification time caching to avoid re-reading/re-injecting unchanged files during rapid navigation.

Returns

bool

True if HTML was served (with or without injection), False if not HTML

Internal Methods 1
_inject_live_reload
Inject live reload script into an HTTP response. This method is provided for t…
1 bytes
def _inject_live_reload(self, response: bytes) -> bytes

Inject live reload script into an HTTP response.

This method is provided for test compatibility and wraps the module-level inject_live_reload_into_response function.

Parameters 1
response bytes

Complete HTTP response (headers + body)

Returns

bytes

Modified response with live reload script injected

Functions

notify_clients_reload
Notify all connected SSE clients to reload. Sends a "reload" message to all connected clients via …
0 None
def notify_clients_reload() -> None

Notify all connected SSE clients to reload.

Sends a "reload" message to all connected clients via their queues. Clients with full queues are skipped to avoid blocking.

This is called after a successful build to trigger browser refresh.

send_reload_payload
Send a structured JSON payload to connected SSE clients.
3 None
def send_reload_payload(action: str, reason: str, changed_paths: list[str]) -> None

Send a structured JSON payload to connected SSE clients.

Parameters 3

Name Type Default Description
action str

'reload' | 'reload-css' | 'reload-page'

reason str

short machine-readable reason string

changed_paths list[str]

list of changed output paths (relative to output dir)

set_reload_action
Set the next reload action for SSE clients. Actions: - 'reload' : full page reload - …
1 None
def set_reload_action(action: str) -> None

Set the next reload action for SSE clients.

Actions:

  • **'reload' **: full page reload
  • **'reload-css' **: CSS hot-reload (no page refresh)
  • **'reload-page' **: explicit page reload (alias of 'reload')

Parameters 1

Name Type Default Description
action str
inject_live_reload_into_response
Inject live reload script into an HTTP response.
1 bytes
def inject_live_reload_into_response(response: bytes) -> bytes

Inject live reload script into an HTTP response.

Parameters 1

Name Type Default Description
response bytes

Complete HTTP response (headers + body)

Returns

bytes

Modified response with live reload script injected