Load freeze.sx + browser API stubs for complete island SSR

All islands now render server-side:
- freeze.sx loaded into kernel (freeze-scope for home/stepper)
- Browser-only APIs stubbed (local-storage-get/set, dom-listen,
  dom-dispatch, dom-set-data, dom-get-data, promise-then)
  → return nil on server, client hydrates with real behavior

Zero island failures. Both layouts/header and home/stepper render
with hydration markers, CSS classes, and initial signal values.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-23 14:44:51 +00:00
parent 2c8afd230d
commit 6e1d28d1d7
2 changed files with 16 additions and 2 deletions

View File

@@ -394,6 +394,16 @@ let make_server_env () =
bind "set-render-active!" (fun _args -> Nil);
bind "render-active?" (fun _args -> Bool true);
(* Browser APIs — no-op stubs for SSR *)
bind "local-storage-get" (fun _args -> Nil);
bind "local-storage-set" (fun _args -> Nil);
bind "dom-listen" (fun _args -> NativeFn ("noop", fun _ -> Nil));
bind "dom-dispatch" (fun _args -> Nil);
bind "dom-set-data" (fun _args -> Nil);
bind "dom-get-data" (fun _args -> Nil);
bind "event-detail" (fun _args -> Nil);
bind "promise-then" (fun _args -> Nil);
(* Raw HTML — platform primitives for adapter-html.sx *)
bind "make-raw-html" (fun args ->
match args with [String s] -> RawHTML s | [v] -> RawHTML (value_to_string v) | _ -> Nil);

View File

@@ -397,14 +397,18 @@ class OcamlBridge:
# All directories loaded into the Python env
all_dirs = list(set(_watched_dirs) | _dirs_from_cache)
# Web adapters + signals (aser lives in adapter-sx.sx,
# signals.sx provides reactive primitives for island SSR)
# Isomorphic libraries: signals, rendering, freeze scopes
web_dir = os.path.join(os.path.dirname(__file__), "../../web")
if os.path.isdir(web_dir):
for web_file in ["signals.sx", "adapter-html.sx", "adapter-sx.sx"]:
path = os.path.normpath(os.path.join(web_dir, web_file))
if os.path.isfile(path):
all_files.append(path)
# Spec library files (loaded after adapters)
for spec_lib in ["freeze.sx"]:
path = os.path.normpath(os.path.join(spec_dir, spec_lib))
if os.path.isfile(path):
all_files.append(path)
for directory in sorted(all_dirs):
files = sorted(