diff --git a/packages/dev-server/src/assets.ts b/packages/dev-server/src/assets.ts
index f0d94f85..d364b9a3 100644
--- a/packages/dev-server/src/assets.ts
+++ b/packages/dev-server/src/assets.ts
@@ -34,6 +34,7 @@ import type { AssetServer } from "./runtime.ts";
import { servePublicAsset } from "./public.ts";
import { servePluginAsset, type ServedPluginAsset } from "./plugin-assets.ts";
import { serveIslandArtifact, serveWrnBrowserArtifact } from "./pipeline.ts";
+import { HMR_CLIENT_HREF, HMR_CLIENT_JS } from "./runtime.ts";
/** Style inputs the dev asset server needs to build `/__wrnexus/styles.css`. */
export interface DevStyles {
@@ -99,6 +100,7 @@ export function createDevAssetServer(
if (pathname.startsWith("/__wrnexus/island/")) {
return serveIslandArtifact(pathname) ?? new Response("Not Found", { status: 404 });
}
+ if (pathname === HMR_CLIENT_HREF) return jsResponse(HMR_CLIENT_JS);
if (pathname === "/__wrnexus/islands.js") return jsResponse(getIslandRuntime(true));
if (pathname === "/__wrnexus/reactive.js") return jsResponse(getReactiveRuntime(true));
if (pathname === "/__wrnexus/controllers.js")
diff --git a/packages/dev-server/src/runtime.ts b/packages/dev-server/src/runtime.ts
index 22bfcf18..740d5823 100644
--- a/packages/dev-server/src/runtime.ts
+++ b/packages/dev-server/src/runtime.ts
@@ -878,8 +878,19 @@ function randomNonce(): string {
}
/** The dev HMR client as a nonce-tagged inline script (strict-CSP friendly). */
-function hmrClientTag(nonce: string): string {
- return ``;
+/** Path the dev asset server publishes the HMR client on. */
+export const HMR_CLIENT_HREF = "/__wrnexus/hmr-client.js";
+
+/**
+ * The HMR client is served as an external module rather than inlined.
+ *
+ * A document's CSP nonce is fixed at load, so an inline script arriving from a
+ * later response — which is exactly what an HMR reload produces — can never
+ * carry a nonce this document accepts. An external file is covered by
+ * script-src 'self' and needs no nonce at all.
+ */
+function hmrClientTag(_nonce: string): string {
+ return ``;
}
/** 403 for a rejected cross-site WebSocket handshake. */