astwerk

wasmwrap & templ

wasmwrap without reactive

reactive is optional. Every other demo in this section uses it, but wasmwrap alone is enough for scripting that doesn't need signals — a nav toggle is three lines. See wasmwrap.

go
//go:build js && wasm

package main

import "github.com/LukasDerBaum42/astwerk/wasmwrap"

func main() {
	nav := wasmwrap.Query("#nav")
	wasmwrap.Query("#toggle").On("click", func(e wasmwrap.Event) {
		e.PreventDefault()
		nav.Class().Toggle("open")
	})
	select {}
}
Why select {} is there

When main returns, the WASM instance exits and every handler dies with it. select blocks forever, keeping the module alive for the click handler.

Re-rendering templ client-side

BindTempl runs a templ component in the browser and assigns the result as innerHTML — convenient for a display-only fragment, wrong for anything interactive, since everything inside is destroyed and rebuilt on every update. See reactive.

go
reactive.BindTempl(preview, func() templ.Component {
	return views.Markdown(source.Get())
})

// Convenient for a display-only panel that changes as a unit. Wrong for
// anything interactive: templ produces a string, so everything inside
// preview is destroyed and rebuilt — losing focus, scroll and selection.
Why BindTempl loses state

The component renders to a string, and the string is assigned as innerHTML — there is nothing to patch against, so the whole subtree is replaced and focus, scroll and selection go with the old nodes.

For layouts, an SEO head and an RSS feed ready to copy in, see Starter templates.