Back
Updating only one user (the
Realtime (DOM without JS)
Kyrux automatically injects a WebSocket into every rendered page. The developer doesn't write any JS — just HTML attributes and Go functions.
1. Mark the element in the template
<div kyrux-target="lista-posts">
{% include "partials/lista.html" %}
</div>
2. Update the DOM from the view
func CriarPostView(ctx *router.Context) {
// ... save to the database ...
// Render the updated fragment
html, _ := render.Partial("blog", "partials/lista.html", map[string]any{
"posts": models.ListarPublicados(fw.DB.Use()),
})
fw.Realtime.Replace("lista-posts", html) // replaces the innerHTML
fw.Realtime.Append("lista-posts", html) // appends to the end
fw.Realtime.Prepend("lista-posts", html) // prepends to the beginning
fw.Realtime.Remove("lista-posts") // removes the element from the DOM
ctx.Redirect("/posts/", http.StatusFound)
}
⚠️
Replace/Append/Prepend/Removeare global broadcasts — every connected client receives the update. Never use them with private data.
Updating only one user (the For variants)
For per-user content (balance, notifications, cart), use the session-scoped variants — only the connections (tabs) for that session receive it:
sess, _ := ctx.Get("session") // set by RequireLogin
s := sess.(*session.Session)
fw.Realtime.ReplaceFor(s.ID, "saldo", html) // only this user's tabs
fw.Realtime.AppendFor(s.ID, "notificacoes", html)
fw.Realtime.RemoveFor(s.ID, "alerta")
fw.Realtime.ReplaceTextFor(s.ID, "contador", "3") // textContent — safe for user content
3. Broadcast via EventBus
// Trigger an update to every connected client through an event:
fw.Realtime.Broadcast("novo.post", payload)
How it works
View saves to the database
→ render.Partial() renders the updated HTML
→ fw.Realtime.Replace() sends it over the WebSocket
→ the browser receives JSON {type:"kyrux:dom", target, html, action}
→ the injected JavaScript locates [kyrux-target="..."] and updates the DOM
Zero JavaScript written by the developer.