Getting Started
gsxui components are copy-in: the CLI vendors real .gsx source into your own module, so what you build against is code you own and can edit — not a package you import and can't touch.
1. Install the CLI
go install github.com/gsxhq/gsxui/cmd/gsxui@latest2. Initialize your project
In your project (a Go module):
gsxui initgsxui initialized.
css: web/gsxui.css (import it from your entry point)
js: web/gsxui/index.js (import it from your entry point)
next: gsxui add buttonThis vendors the theme tokens (web/gsxui.css), the JS runtime and behavior barrel (web/gsxui/), and the class merger (ui/merge/merge.go), then points gsx.toml'sclass_merger at it — the seam that makes caller-class-merge work (see Theming). It alsogo gets gsx and tailwind-merge-go, and installs the gsx tool via go get -tool.
web/gsxui.css begins with@import "tailwindcss" and@import "tw-animate-css" — your Tailwind build resolves both from npm, so make sure they're installed:npm install tailwindcss @tailwindcss/vite tw-animate-css. Without tw-animate-css everyanimate-in/animate-out class the components carry (dialog, dropdown, tooltip) is silently inert.
3. Add components
gsxui add button cardadding: button card
done — build with: go build ./...card has no dependencies of its own, but a component that does (e.g. select, which needs icon) pulls its dependency in automatically — gsxui add select vendorsicon too. You own every file this writes:gsxui add never touches one you've already modified unless you pass --overwrite. After upgrading the gsxui binary, re-run gsxui add <name> --overwrite to refresh vendored components — that discards local edits to those files.
4. Your first page
A tiny two-file app: home.gsx renders a Card around aButton, and main.go serves it.
package main
import "example.com/myapp/ui"
component Home() {
<html lang="en">
<head>
<meta charset="UTF-8"/>
<link rel="stylesheet" href="/web/gsxui.css"/>
</head>
<body class="flex min-h-svh items-center justify-center bg-background p-8 text-foreground">
<ui.Card class="w-full max-w-sm">
<ui.CardHeader>
<ui.CardTitle>Hello, gsxui</ui.CardTitle>
<ui.CardDescription>Your first page.</ui.CardDescription>
</ui.CardHeader>
<ui.CardContent>
<ui.Button>Click me</ui.Button>
</ui.CardContent>
</ui.Card>
</body>
</html>
}package main
import (
"log"
"net/http"
)
func main() {
http.Handle("/web/", http.StripPrefix("/web/", http.FileServer(http.Dir("web"))))
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
Home().Render(r.Context(), w)
})
log.Println("listening on http://localhost:8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}Compile the .gsx file to plain Go, then run it:
go tool gsx generate(silent on success — it writes home.x.go next tohome.gsx and exits 0)
go run .2026/07/23 09:00:00 listening on http://localhost:8080Open http://localhost:8080 — a styled Card with a Button inside, rendered with gsxui's default light theme. Next:restyle it.