diff --git a/hosts/ocaml/lib/sx_render.ml b/hosts/ocaml/lib/sx_render.ml index 591dbd5..ed1cc8c 100644 --- a/hosts/ocaml/lib/sx_render.ml +++ b/hosts/ocaml/lib/sx_render.ml @@ -255,6 +255,7 @@ and render_list_to_html head args env = (try let v = env_get env name in (match v with + | Component c when c.c_affinity = "client" -> "" (* skip client-only *) | Component _ -> render_component v args env | Island _i -> (* Islands: SSR via the SX render-to-html from adapter-html.sx. diff --git a/shared/sx/templates/shell.sx b/shared/sx/templates/shell.sx index daf0f93..6667d5e 100644 --- a/shared/sx/templates/shell.sx +++ b/shared/sx/templates/shell.sx @@ -31,6 +31,14 @@ (when meta-html (raw! meta-html)) (meta :name "csrf-token" :content csrf) (style :id "sx-css" (raw! (or sx-css ""))) + ;; CSSX rules from island SSR — must be in so they survive + ;; #main-panel morphs during SPA navigation. Inline the flush logic + ;; rather than calling ~cssx/flush (which has :affinity :client and + ;; gets skipped during SSR rendering). + (let ((cssx-rules (collected "cssx"))) + (clear-collected! "cssx") + (when (not (empty? cssx-rules)) + (style :data-cssx true (raw! (join "" cssx-rules))))) (meta :name "sx-css-classes" :content (or sx-css-classes "")) ;; CDN / head scripts — configurable per app ;; Pass a list (even empty) to override defaults; nil = use defaults @@ -68,8 +76,6 @@ details.group{overflow:hidden}details.group>summary{list-style:none}details.grou (body :class "bg-stone-50 text-stone-900" ;; Server-rendered HTML — visible immediately before JS loads (div :id "sx-root" (raw! (or body-html ""))) - ;; Flush CSSX rules collected during island SSR - (~cssx/flush) (script :type "text/sx" :data-components true :data-hash component-hash (raw! (or component-defs ""))) (when init-sx