Gothic Framework G symbol

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 pkg/wasm (import . "github.com/felipegenef/gothicframework/v2/pkg/wasm") for use these helpers, otherwise you will get a tinygo compile error.

Note: the topic manager component must be mounted on the page before any component that subscribes to it. Mount it once at the top of your page template.

1. Declare the Topic

Create a file in src/topics/ and call CreateTopic. Gothic generates a subscriber function and a mount component named Add<Name>Topic() for you.

// src/topics/app_topic.go 
 package  gothicwasm

 import  .  "github.com/felipegenef/gothicframework/v2/pkg/wasm" 

 type  App  struct  {
	Count  int 
	Theme  string 
	Label  string 
}

 var  _ =  CreateTopic (App{}, TopicConfig{
	 Name :              "app" ,
	 Compression :      BROTLI,
	 SubscriberFnName :  "AppTopic" ,
	 ComponentFnName :   "AddAppTopic" ,
}) 

2. Mount the Manager and Publish

Mount AddAppTopic() once on the page. Then 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.

// page template, mount the manager once 
 templ   Home () {
	@ AddAppTopic ()
	@ Counter ()
	@ ThemeSwitcher ()
}

 // 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 root 
	 Observe ( func () {
		 if  topic.Theme.Get() ==  "dark"  {
			 AddClass ( "root" ,  "dark" )
		}  else  {
			 RemoveClass ( "root" ,  "dark" )
		}
	}, topic.Theme)
} 

Liked topics? Next up, pick the right WASM compiler for your route!