From fe84b57bed48084af7b062e3f6dd6876c4142504 Mon Sep 17 00:00:00 2001 From: giles Date: Mon, 23 Mar 2026 18:14:43 +0000 Subject: [PATCH] Move CSSX rules to , skip client-affinity components in SSR - Shell inlines CSSX flush logic in (collected/clear-collected!) so island CSS rules survive #main-panel morphs during SPA navigation - OCaml render_to_html skips :affinity :client components during Phase 1b SSR (prevents ~cssx/flush rendering inside body-html) Co-Authored-By: Claude Opus 4.6 (1M context) --- hosts/ocaml/lib/sx_render.ml | 1 + shared/sx/templates/shell.sx | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) 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