Skill v1.0.0
currentAutomated scan100/100version: "1.0.0" name: hlivekit description: >- Use the hlivekit toolkit (github.com/SamHennessy/hlive/hlivekit) for common HLive needs — dynamic lists of components (ComponentList / hlivekit.List), giving an input focus, running server logic after a browser diff applies (OnDiffApply), real-time fan-out updates (PubSub), element-visibility events, scroll/redirect helpers, and preempt-disable-on-click. Use when an HLive task involves any of these patterns or imports the hlivekit package.
HLiveKit
hlivekit is HLive's companion toolkit of reusable patterns. Import alongside the core package:
import (l "github.com/SamHennessy/hlive""github.com/SamHennessy/hlive/hlivekit")
Pick the helper that matches the need:
Dynamic lists — ComponentList
For lists whose items are added/removed at runtime (search results, todo items, table rows). It tracks items and runs their teardown when removed, avoiding leaks.
list := hlivekit.List("tbody") // shortcut for NewComponentList// ...add it to the tree like any node...list.AddItem(l.CM("tr", // items are Teardowner (CM components)l.T("td", key),l.T("td", value),))list.RemoveItems(item) // remove specific itemslist.RemoveAllItems() // clear
Constructors: hlivekit.List(name, ...) / hlivekit.NewComponentList(name, ...). Methods: Add, AddItem(items ...l.Teardowner), RemoveItems, RemoveAllItems.
hlivekit.NewComponentListSimple(...) is a lighter variant without the memory cleanup logic — only use it when you manage item lifetimes yourself.
It's idiomatic to populate the list inside a CM component's SetMount (see the hlive-core skill) so it fills when the component appears:
cm := l.CM("table", list)cm.SetMount(func(ctx context.Context) {for _, row := range fetchRows(ctx) {list.AddItem(l.CM("tr", l.T("td", row.Name)))}})
Focus — Focus
Give an input focus from the server (no JS). Add it as an attribute; pair with a one-shot focus binding + FocusRemove so it only fires once:
input := l.C("input")input.Add(hlivekit.Focus(), l.OnOnce("focus", func(ctx context.Context, _ l.Event) {hlivekit.FocusRemove(input)}))
Run server logic after a diff applies — OnDiffApply
Fires a handler once HLive's diff has been applied in the browser. Useful for chaining updates (animation frames) or reacting to a render completing.
comp.Add(hlivekit.OnDiffApply(func(ctx context.Context, e l.Event) { /* ... */ }))
Also hlivekit.OnDiffApplyOnce(...). See _example/callback and _example/animation.
Real-time updates — PubSub
Server-side publish/subscribe to fan out changes to many connected sessions (or between components in one session). One PubSub is shared across the app.
pubSub := hlivekit.NewPubSub()page.DOM().HTML().Add(hlivekit.InstallPubSub(pubSub)) // install once per page// subscribe a handler to topicspubSub.Subscribe(hlivekit.NewSub(func(m hlivekit.QueueMessage) {// react; call l.Render(ctx)/RenderComponent to push updates}), "my-topic")// publish from anywherepubSub.Publish("my-topic", payload)
Key API: NewPubSub(), InstallPubSub(ps), ps.Subscribe(sub, topics...), ps.Unsubscribe(...), ps.Publish(topic, value), NewSub(onMessageFn). For components that subscribe on mount there's ComponentPubSub (hlivekit.CPS / NewComponentPubSub / WrapComponentPubSub) with SetMountPubSub. See _example/pubsub/pubsub.go.
Other helpers
- `OnElementVisible(handler)` /
OnElementVisibleOnce— fire when an element
scrolls into view (lazy-load, infinite scroll).
- `ScrollIntoView(alignToTop)` /
ScrollIntoViewRemove,
`ScrollTop(val)` / ScrollTopRemove — control scrolling from the server.
- `Redirect(url)` — issue a client-side redirect as an attribute.
- `PreemptDisableOn(eventBinding)` — disable a control in the browser
immediately on click (before the round-trip) to prevent double-submits.
Reference
hlivekit/README.md and the source: hlivekit/componentList.go, hlivekit/focus.go, hlivekit/diffapply.go, hlivekit/pubsub.go, hlivekit/elementVisible.go, hlivekit/scrollIntoView.go, hlivekit/scrollTop.go, hlivekit/redirect.go, hlivekit/preemptDisableOnClick.go. Examples: _example/todo, _example/pubsub, _example/callback, _example/url_params.