squint

2026-02-11T14:30:30.728619Z

A small field report on Reagami. I am experimenting a bit with a combination of Reagami, Scittle and Replicant on the backend. Trying to get a setup like Datastar. I have something basic working, but I wanted to share one issue others might also run into with Reagami at some point. I was rendering on the html body like

(reagami/render js/document.body [my-component])
And this works mostly fine, except if there are other processes injecting html as well. In my case a password manager injecting some element, this triggers an incorrect children count (https://github.com/borkdude/reagami/blob/main/src/reagami/core.cljc#L242) and causes the full dom to reload. And therefore also emptying forms and such. After I figured this out, I fixed it by using the variant mentioned in the README. So a div#app as a first child of the body
(reagami/render (js/document.querySelector "#app") [my-component])
Now things work very nicely!

borkdude 2026-02-11T14:32:29.745219Z

Nice!

borkdude 2026-02-11T14:32:50.132049Z

Why are you using reagami when you already have replicant?

2026-02-11T14:33:41.697659Z

I'm using replicant on the backend. It generates the hiccup send via an SSE stream to the browser which is loaded with Reagami

2026-02-11T14:34:16.017079Z

I am using Replicant on the backend instead of hiccup or something else because I am using replicant-kanban as a test case

borkdude 2026-02-11T14:34:54.592919Z

that's great. but scittle also supports replicant on the front-end. of course I'm happy you are trying reagami, but in scittle it's interpreted right? if this is fast enough, than it's a really nice demo :)

2026-02-11T14:37:05.194259Z

Yeah it works like the normal replicant-kanban. I can see some benefits of a datastar way of working. So no need to compile clojurescript this way and the backend as a source of truth. I have a set of local actions such a dragging etc defined with Scittle, and the rest is posted to the backend. This triggers an event in the stream and re-rendering

2026-02-11T14:38:55.034459Z

in scittle it's interpreted right?Ah yeah, so I added Reagami to my custom Scittle build, but to debug why Reagami was fully re-rendering I loaded it from source with some debugging in it. Didn't notice a difference in speed

2026-02-11T14:39:46.034269Z

It was a small change to Scittle. If you are interested I can do a PR for sci.configs and a scittle plugin as well

borkdude 2026-02-11T14:40:55.163249Z

sure!

👍 1
2026-02-11T14:40:55.780209Z

Also cool to see live updates in multiple browsers with replicant-kanban btw

borkdude 2026-02-11T14:41:13.025999Z

do you think reagami has a bug in this respect or not?

borkdude 2026-02-11T14:41:51.709329Z

I think it just expects to not mess with the dom nodes it created itself. but you can create child nodes which it leaves intact with :on-mount

2026-02-11T14:42:02.959589Z

Not a bug, but maybe if someone mounts on the body a warning could be helpful. If this becomes a common problem i guess

2026-02-11T14:44:06.920279Z

Probably people would not notice until they are using forms etc. Until then they might experience some slowness in Re-rendering i guess

borkdude 2026-02-11T14:45:34.066419Z

I'm not exactly clear on the issue. Could you describe the issue from the start?

2026-02-11T14:45:51.023289Z

sure, here or on github?

borkdude 2026-02-11T14:46:09.917139Z

here

2026-02-11T14:53:54.191319Z

Ok, so when I mount my app on the body element:

(reagami/render js/document.body hiccup)
Reagami is in trouble because in my browser my password manager happens to inject an element in the body. This changes the children count in Reagami and this triggers a render a the root. I've added these debugging lnes in the Reagami code:
if (not (== old-children-count new-children-count))
          (do (println "Old count vs new count" old-children-count new-children-count)
              (js/console.log "Replacing Children" old-children)
              (.apply parent.replaceChildren parent (.map new-children #(create-node % root))))
....
Then I see the below in the console, regardless of what elements actually changed. So the patching is not efficient because of this and things with a state like forms (and I'm guessing components) also get reloaded Choosing a different element then the body might be a good way to avoid conflicts caused by html injection by third parties
(reagami/render  (js/document.querySelector "#app") hiccup)

2026-02-11T14:54:19.603899Z

Is that clear enough or still a bit vague?

borkdude 2026-02-11T14:57:00.731389Z

yes, this is an expected problem. reagami keeps track of all the nodes it created with a vdom like architecture. when you mess with the dom manually, it will get confused. if you want to inject dom nodes, you can do with :on-render or :on-mount etc. indeed it's better to mount on a child node in the body specially dedicated to your app. it's not a problem reagami can fix. Probably other libs like this like replicant will also have the same problem (I expect..)

2026-02-11T14:58:58.075979Z

Yeah in this case I wasn't aware of the injection and at first it didn't seem to be a problem. Only when I was wondering why the form was being reset

borkdude 2026-02-11T15:03:07.506729Z

so the scenario is likely: body has 0 children. reagami does it's job, inserts 1 (the app?) then password manager comes along, injects another dom element. on the re-render, reagami compares the amount of children in the vdom (1) with the new one (1 from the app). but the real dom node count is two... if the password injects before your app, reagami will replace your password stuff with the app

borkdude 2026-02-11T15:03:12.176719Z

could this be the scenario?

borkdude 2026-02-11T15:03:47.963869Z

if so, I think we could fix this with id reconciliation

borkdude 2026-02-11T15:04:19.845769Z

if the password manager inserts after the app node, then I think there won't be any problem

2026-02-11T20:57:52.836349Z

Sorry, I got interrupted. Yeah I think that's the scenario