Guide / 16 — Hot Morphing
Hot Morphing
Hot Morphing is Stew's built-in live reloading system. It updates the browser instantly when code changes, without reloading the page and without losing UI state.
How It Works
- CLI Watcher:
stew run devmonitors project files. When a file changes, it sends a reload signal via a shared channel. - SSE Middleware:
sdk/liveinjects aGET /_stew/liveendpoint into the Go server. The browser maintains an open Server-Sent Events connection to this endpoint. - Client Script:
live.InjectScript()injects a<script>into the HTML that listens for SSE and triggers a morph-reload. - Idiomorph Morphing: Instead of a full reload, idiomorph performs a smart diff between the current DOM and the new HTML, preserving scroll position, focus, and input states.
Configuring a Layout for Hot Morphing
In your root layout pages/@layout.stew:
<goscript>
import "os"
import "github.com/ZiplEix/stew/sdk/live"
</goscript>
<!DOCTYPE html>
<html lang="en">
<head>
<!-- idiomorph is required for morphing -->
<script src="https://unpkg.com/idiomorph/dist/idiomorph-ext.min.js"></script>
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
</head>
<body hx-ext="morph">
<slot />
<!-- Live script injected only in dev mode -->
{{ if os.Getenv("STEW_DEV") == "true" }}
{{ raw(live.InjectScript()) }}
{{ end }}
</body>
</html>
⚠️ Critical: The Body Tag Limitation
By design, Hot Morphing only updates elements located inside the <body> tag.
While you must place the hx-ext="morph" attribute on the <body> itself, the <body> tag and its siblings (like <head>) are not morphed. This ensures that the Live Reload script connection remains active throughout the development session.
Configuring the Server
In main.go, wrap your router with the live middleware:
package main
import (
"net/http"
"os"
"github.com/ZiplEix/stew/sdk/live"
)
func main() {
mux := http.NewServeMux()
RegisterStewRoutes(mux)
var handler http.Handler = mux
if os.Getenv("STEW_DEV") == "true" {
handler = live.Middleware(mux)
}
http.ListenAndServe(":8080", handler)
}
The live.Middleware adds the /_stew/live SSE route and manages the reload signal broadcast.
Automatic Environment Variables
| Variable | Dev Value | Role |
|---|---|---|
| STEW_DEV | true | Enables Hot Morphing and development logging |