Ring middleware for hot reload of server-rendered applications.
Ring middleware for hot reload of server-rendered applications.
(deregister-notify-fn! f)Removes a previously registered notification function.
Removes a previously registered notification function.
(hot-reloader &
[{:keys [watch-paths watch-extensions uri-prefix inject?
debounce-ms bust-css-cache?]
:or {watch-paths ["src"]
watch-extensions #{".cljc" ".html" ".css" ".clj" ".edn"}
uri-prefix "/__hot-reload"
inject? (constantly true)
debounce-ms 100
bust-css-cache? false}}])Creates a hot reloader — an immutable map of composable pieces for hot
reload. Does not start watching; call start! to begin.
Returns a map with:
:ws-handler - Ring handler for the WebSocket endpoint. Mount
at a route (e.g. "/__hot-reload") or let
wrap-hot-reload handle routing automatically.
Handles both sync and async Ring.
:injection-middleware - Ring middleware (fn [handler] -> handler) that injects the client script into full HTML page responses. Partial responses (htmx fragments, etc.) are left untouched.
:script - JavaScript string containing the client code (idiomorph, WebSocket reconnection, error overlay).
:uri-prefix - The WebSocket endpoint path.
Lifecycle functions (call these yourself):
(start! reloader) — starts watching; returns a handle (stop! reloader handle) — stops watching, cleans up resources
Options: :watch-paths - directories to watch (default ["src"]) :watch-extensions - file extensions that trigger reload (default #{"clj" ".cljc" ".edn" ".html" ".css"}) :uri-prefix - WebSocket endpoint path (default "/__hot-reload") :inject? - predicate (fn [request response]) controlling script injection (default: always inject into HTML responses) :debounce-ms - debounce window in ms (default 100) :bust-css-cache? - append cache-busting param to stylesheet URLs on reload (default false)
Creates a hot reloader — an immutable map of composable pieces for hot
reload. Does not start watching; call `start!` to begin.
Returns a map with:
:ws-handler - Ring handler for the WebSocket endpoint. Mount
at a route (e.g. "/__hot-reload") or let
`wrap-hot-reload` handle routing automatically.
Handles both sync and async Ring.
:injection-middleware - Ring middleware (fn [handler] -> handler) that
injects the client script into full HTML page
responses. Partial responses (htmx fragments,
etc.) are left untouched.
:script - JavaScript string containing the client code
(idiomorph, WebSocket reconnection, error overlay).
:uri-prefix - The WebSocket endpoint path.
Lifecycle functions (call these yourself):
(start! reloader) — starts watching; returns a handle
(stop! reloader handle) — stops watching, cleans up resources
Options:
:watch-paths - directories to watch (default ["src"])
:watch-extensions - file extensions that trigger reload
(default #{"clj" ".cljc" ".edn" ".html" ".css"})
:uri-prefix - WebSocket endpoint path (default "/__hot-reload")
:inject? - predicate (fn [request response]) controlling script
injection (default: always inject into HTML responses)
:debounce-ms - debounce window in ms (default 100)
:bust-css-cache? - append cache-busting param to stylesheet URLs on
reload (default false)(notify!)Triggers a reload notification to all registered listeners. Used by the nREPL middleware.
Triggers a reload notification to all registered listeners. Used by the nREPL middleware.
(register-notify-fn! f)Registers a notification function. Called by the middleware on setup so that the nREPL middleware can trigger reloads.
Registers a notification function. Called by the middleware on setup so that the nREPL middleware can trigger reloads.
(start! reloader)Starts the file watcher for a hot reloader. Returns a handle to pass
to stop!.
Starts the file watcher for a hot reloader. Returns a handle to pass to `stop!`.
(stop! reloader handle)Stops the file watcher for a hot reloader. handle is the value
returned by start!.
Stops the file watcher for a hot reloader. `handle` is the value returned by `start!`.
(wrap-hot-reload handler reloader)Ring middleware that provides hot reload for server-rendered HTML responses.
Takes a Ring handler and a hot reloader (from hot-reloader), returns a
new Ring handler that:
This is a standard Ring middleware — it takes a handler and returns a handler.
Example: (let [hr (hot/hot-reloader {:watch-paths ["src"]}) app (hot/wrap-hot-reload my-handler hr) h (hot/start! hr)] ;; app is your Ring handler ;; later: (hot/stop! hr h))
For more control (e.g. mounting the WebSocket endpoint as a router route
and adding injection as separate middleware), use the reloader map keys
directly: :ws-handler, :injection-middleware, :script.
Ring middleware that provides hot reload for server-rendered HTML responses.
Takes a Ring handler and a hot reloader (from `hot-reloader`), returns a
new Ring handler that:
1. Intercepts requests to the WebSocket endpoint
2. Injects the client script into full HTML page responses
3. Passes all other requests through unchanged
This is a standard Ring middleware — it takes a handler and returns a handler.
Example:
(let [hr (hot/hot-reloader {:watch-paths ["src"]})
app (hot/wrap-hot-reload my-handler hr)
h (hot/start! hr)]
;; app is your Ring handler
;; later: (hot/stop! hr h))
For more control (e.g. mounting the WebSocket endpoint as a router route
and adding injection as separate middleware), use the reloader map keys
directly: `:ws-handler`, `:injection-middleware`, `:script`.cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |