Topics
Topics let multiple WASM components on the same page share reactive state. Think of them as Gothic's version of React's useContext. One component publishes a value and every component subscribed to that field reacts automatically.
A topic is just a struct declared in src/topics/. Each field becomes an *ObservableField[T] with .Get(), .Set(), and .Peek() methods. Pass any field to Observe as a dependency and your callback re-runs only when that field changes.
Important: You must dot-import core/wasm (import . "github.com/gothicframework/core/wasm") for use these helpers, otherwise you will get a tinygo compile error.
Note: there is no mount step. Once a topic is declared in src/topics/, the always-loaded Gothic core registers it automatically. Any component can then grab it with its generated accessor and start reading or publishing.
1. Declare the Topic
Create a file in src/topics/ and call CreateTopic. Gothic generates an accessor function named after SubscriberFnName (here AppTopic()) that every component uses to reach the same shared instance.
// src/topics/app_topic.go
package gothicwasm
import . "github.com/gothicframework/core/wasm"
type App struct {
Count int
Theme string
Label string
}
var _ = CreateTopic(App{}, TopicConfig{
Name: "app",
Compression: BROTLI,
SubscriberFnName: "AppTopic",
})2. Publish from Any Component
Any component can grab the topic with AppTopic() and call .Set() on a field to publish an update. Use .Peek() when you need the current value without subscribing.
// writer component, publish a single field
ClientSideState: func() {
topic := AppTopic()
CreateWasmFunc("increment", func() {
topic.Count.Set(topic.Count.Peek() + 1)
})
CreateWasmFunc("toggleTheme", func() {
if topic.Theme.Peek() == "light" {
topic.Theme.Set("dark")
} else {
topic.Theme.Set("light")
}
})
}3. Subscribe to Reactive Fields
In another component, call AppTopic() to get the same shared instance. Pass a field to Observe as a dependency and the callback re-runs whenever that field changes.
Note: use .Get() inside an Observe callback to subscribe to the field. Use .Peek() to read the value without creating a subscription.
// reader component, reacts to remote changes
ClientSideState: func() {
topic := AppTopic()
// re-runs only when Count changes, not Theme or Label
Observe(func() {
SetText("count-display", strconv.Itoa(topic.Count.Get()))
}, topic.Count)
// react to Theme, toggle a class on the body
Observe(func() {
if topic.Theme.Get() == "dark" {
AddClass("root", "dark")
} else {
RemoveClass("root", "dark")
}
}, topic.Theme)
}Liked topics? Next, learn how to share code across WASM pages and render templ components client-side!
