FWIW, when I wrote a browser-based projectional editor for a blocks language, I found it easiest to write it just like I would any other form on the web.
I had one UI component per type of AST node. The components rendered text fields and drop targets and other standard web UI affordances to support editability.
Variable bindings, types, etc, are derivative information that I could cache when necessary, or just recompute from the AST as-needed. I mostly did the latter.
Because I designed the AST for projectional editing, there were comment slots on any node that would benefit from special rendering of comments, and I had a comment block node that you could wrap any other block of code in to describe what that block did. If you’re using someone else’s AST, you may not have that luxury, but you may be able to write your own AST for editing and a translation layer between yours and the executable AST. I have parsed JavaScript ASTs to guess which comments document which other nodes and with some heuristics you can guess pretty well.
Hope this helps!