GOXis a compile-time JSX dialect for Go. It allows developers to write standard HTML markup and instantiate custom Go components directly insidereturn (...)statements without runtime reflection or template strings.
Basic Component
Any struct embeddingcomponent.ComponentBaseand implementingRender() *component.Nodeis a valid GoKS component:
package app
import (
"github.com/misbakhul29/goks/pkg/component"
"github.com/misbakhul29/goks/pkg/html"
)
type Greeter struct {
component.ComponentBase
Name string
IsAdmin bool
}
func (g *Greeter) Render() *component.Node {
return html.Div(html.H2("Hello, {g.Name}!").Class("text-2xl font-bold text-white"), "{component.If(g.IsAdmin, (", html.Span("Admin User").Class("text-xs px-2 py-1 bg-amber-500/20 text-amber-300 rounded font-mono"), "))}").Class("p-6 rounded-xl bg-slate-900 border border-slate-800")
}Expressions & Attributes
Curly braces evaluate any valid Go expression. Dynamic attribute values can also use braces:
<div class={"bg-" + color + " p-4"} id={elementID}>
<span>{user.Username}</span>
</div>Conditional Rendering
Usecomponent.If(condition, node)to conditionally render elements:
{component.If(isLoggedIn, (
<a href="/dashboard" class="text-cyan-400">Dashboard</a>
))}Rendering Lists
Standard Go slices of[]*component.Nodecan be embedded directly inside children slots:
func (p *Page) Render() *component.Node {
items := []string{"Go", "WebAssembly", "Tailwind v4", "TinyGo"}
var renderedItems []*component.Node
for _, item := range items {
renderedItems = append(renderedItems, (
<li class="px-3 py-1 bg-slate-800 rounded text-cyan-300 font-mono text-sm">{item}</li>
))
}
return html.Ul(component.Any(renderedItems)).Class("flex flex-wrap gap-2")
}Using Custom Components
Custom components are invoked using standard package qualification like<ui.Button Label="Save" />or<components.Navbar />. Props are mapped to struct fields with strict compile-time type safety.