HMR / hot reload

In dev, bext's client runtime does hot reload with state preservation: on each rebuild, <style> blocks are hot-swapped (instant CSS), <main> is replaced in place, and resumable islands' live state (signal values) is snapshotted and restored — your counter, form fields, and scroll survive the edit instead of resetting.

Tip
Try it here: open the console and run window.__bextHmr.snapshot(), bump the counter on the Resumability page, then reload — the value is kept (one-shot: a second reload starts fresh). That's the hard half of HMR (state preservation), entirely client-side, with zero bundler risk.

What works today

  • In-place module swap (window.__bextHmr.swapIsland): edit an island → new code goes live, state preserved, NO reload.
  • CSS hot-swap: <style> blocks are replaced with no reload.
  • Content swap: <main> is replaced in place; islands re-mount with the new code.
  • State preservation: island signals survive (snapshot → restore, one-shot).
  • bext:navigated event to re-init content scripts.

What's left (the deeper arc)

  • Server-side SSR module hot-swap (live-binding via __bextRebind thunks in the warm V8 context) — ~60% built, BEXT_DEV_MODE; the plan judges it marginal (bext already recompiles incrementally).

Enable it

layout.tsxTSX
import { clientRuntimeBody } from "@bext-stack/framework/client";

// Dev mode: live-reload with state preservation.
<script dangerouslySetInnerHTML={{ __html:
  clientRuntimeBody({ navigation: true, liveReload: true })
}} />

// On a rebuild event the runtime:
//   1. hot-swaps <style> blocks (CSS edits are instant, no flash)
//   2. swaps the <main> content in place
//   3. snapshots each resumable island's LIVE signal values, and on the
//      next mount restores them — so your counter / form / scroll survive
//      the edit instead of resetting.

// The snapshot channel is also exposed for manual use:
window.__bextHmr.snapshot();   // before a reload