İçindekiler
GoUI, sunucu güdümlü bir Go UI çatısıdır: bileşenleri Go ile yazarsınız, tüm durumun (state) sahibi sunucudur ve HTML'i sunucu render eder; tarayıcıdaki küçük, vanilla-JS bir çalışma zamanı (runtime) ise bir WebSocket bağlantısı üzerinden minimum DOM yamalarını uygular. İstemci tarafında bir bileşen ağacı yoktur, bir build (derleme) hattı yoktur ve domain modelinizin JavaScript'te ikinci bir kopyası yoktur.
Bu kılavuz, sıfırdan çalışan bir GoUI uygulamasına giden yolu gösterir, proje iskeletini açıklar, ilk bileşeninizi adım adım gösterir ve repoyla birlikte gelen tüm örnekleri nasıl çalıştıracağınızı anlatır.
1. Gereksinimler
- Go 1.25 veya daha yeni (modülün kendisi
go 1.25.0'ı hedefler;go versionile kontrol edin) - WebSocket desteği olan bir tarayıcı (tüm modern tarayıcılar)
- Node.js yok, npm yok, bundler yok — istemci çalışma zamanı, statik dosya olarak sunulan düz ES modülleridir
2. Kurulum
GoUI normal bir Go modülüdür. Projenize şu şekilde ekleyin:
go get github.com/zatrano/goui@latest
Modül yolu her zaman github.com/zatrano/goui'dir. Her alt paket bunun
altından import edilir, örneğin:
import (
"github.com/zatrano/goui/core"
"github.com/zatrano/goui/forms"
"github.com/zatrano/goui/i18n"
"github.com/zatrano/goui/upload"
"github.com/zatrano/goui/validation"
"github.com/zatrano/goui/ws"
)
GoUI framework-agnostic'tir: çekirdek modülün HTTP yönlendirici bağımlılığı yoktur. WebSocket ve yükleme route'ları küçük adapter modülleriyle bağlanır. Çekirdek modülü ve yığınınıza uyan adapter'ı ekleyin:
go get github.com/zatrano/goui@latest
go get github.com/zatrano/goui/adapters/fiber@latest # veya gin, echo, stdlib
Tam adapter karşılaştırması için
13-project-integration.md'ye bakın. Repodaki
demolar Fiber adapter'ını kullanır; kanıt örnekleri
examples/adapters/{nethttp,chi,gin,echo} altındadır.
3. Proje iskeleti
Minimal bir GoUI uygulaması şu şekle sahiptir:
myapp/
├── go.mod
├── main.go # HTTP uygulaması, registry, hub, adapter route'ları
├── index.html # /client/goui.js'i yükler ve bağlanır
└── (isteğe bağlı) i18n/
└── locales/
├── tr.json
└── en.json
main.go dört şeyden sorumludur:
- Bir
core.Registryinşa etmek ve bileşen(ler)inizi isimle kaydetmek. - Bir
i18n.Translatorinşa etmek (isteğe bağlı olarak locale dosyalarını yükleyerek). - Bir
ws.Hubinşa etmek,ws.NewServer(hub, registry, translator)ile sarmalamak ve seçtiğiniz adapter üzerindenGET /goui/ws'i kaydetmek (bkz. §2). - GoUI istemci çalışma zamanını (
client/) ve sayfanızınindex.html'ini statik dosyalar olarak sunmak.
client/ dizinini HTTP yığınınızın statik dosya sunma yöntemiyle servis edin —
Fiber için örnek:
app.Use("/client", static.New("./client"))
4. İlk bileşeniniz
Her GoUI bileşeni core.Component arayüzünü uygular:
type Component interface {
Mount(ctx context.Context) error
Render() (string, error)
HandleEvent(ctx context.Context, event string, payload map[string]any) error
Unmount(ctx context.Context) error
}
core.BaseComponent'i gömerek (embed) dirty-tracking, i18n ve toast
yardımcılarını bedava elde edersiniz (tam sözleşme için
02-components.md'ye bakın).
İşte kanonik "Counter" (Sayaç) bileşeni:
package main
import (
"context"
"log"
"path/filepath"
"github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v3/middleware/static"
gouifiber "github.com/zatrano/goui/adapters/fiber"
"github.com/zatrano/goui/core"
"github.com/zatrano/goui/i18n"
"github.com/zatrano/goui/ws"
)
type Counter struct {
core.BaseComponent
Count int
}
func (c *Counter) Mount(_ context.Context) error { return nil }
func (c *Counter) Render() (string, error) {
html, err := core.RenderTemplate(`<div class="counter">
<span class="count">{{.Count}}</span>
<button type="button" g-click="increment">+</button>
<button type="button" g-click="decrement">-</button>
</div>`, c)
if err != nil {
return "", err
}
c.ResetDirty()
return html, nil
}
func (c *Counter) HandleEvent(_ context.Context, event string, _ map[string]any) error {
switch event {
case "increment":
c.Count++
c.MarkDirty()
case "decrement":
c.Count--
c.MarkDirty()
}
return nil
}
func (c *Counter) Unmount(_ context.Context) error { return nil }
func main() {
registry := core.NewRegistry()
if err := registry.Register("counter", func() core.Component { return &Counter{} }); err != nil {
log.Fatal(err)
}
translator := i18n.NewTranslator()
hub := ws.NewHub()
app := fiber.New()
app.Use("/client", static.New(filepath.Join(".", "client")))
app.Get("/", func(c fiber.Ctx) error {
return c.SendFile("index.html")
})
gouifiber.Register(app, gouifiber.Options{
Server: ws.NewServer(hub, registry, translator),
})
log.Println("listening on http://localhost:3000")
log.Fatal(app.Listen(":3000"))
}
Ve buna eşlik eden index.html:
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<title>GoUI Counter</title>
</head>
<body>
<div id="app"></div>
<script type="module">
import { GoUIClient } from '/client/goui.js';
const client = new GoUIClient('/goui/ws', 'counter', { mount: '#app', locale: 'tr' });
client.connect();
</script>
</body>
</html>
Bu sayfa yüklendiğinde neler olur:
GoUIClient,/goui/ws?component=counter&locale=tr'ye bir WebSocket açar.- Sunucu bir
ws.Sessionoluşturur,Registry'den birCounterinşa etmesini ister,Mount'u çağırır, ardından birsessionframe'i ve onu takiben ilkrenderframe'ini gönderir. +'a tıklamak bireventframe'i gönderir ({"type":"event","event":"increment", ...}); sunucuHandleEvent'i çağırır, yeniden render eder, eski/yeni HTML ağacını diff'ler ve minimal birrenderyaması geri gönderir.- Sekme bağlantısı kesilirse (yeniden yükleme, ağ kesintisi), oturum bir
grace period (varsayılan 60 sn, bkz.
04-sessions-and-websocket.md) boyunca canlı tutulur; böylece yeniden bağlanma, baştan başlamak yerine durumu geri yükler.
5. Repoyla gelen örnekleri çalıştırma
Repo, examples/ altında çalıştırılabilir on demo sunar; her biri repo
kökünden doğrudan go run edebileceğiniz bağımsız bir main.go'dur. Her
örnek kendi statik HTML sayfasını sunar, GoUI WebSocket route'unu bağlar ve
kendine özel bir portu dinler; böylece birkaçını yan yana çalıştırabilirsiniz:
| Port | Komut | Demo | Ne gösteriyor |
|---|---|---|---|
| 3000 | go run ./examples/counter |
counter | Minimal Component yaşam döngüsü, g-click, dirty tracking |
| 3001 | go run ./examples/contact-form |
contact-form | Native form alanları, doğrulama, Toast/ToastT, prefetch → activate |
| 3002 | go run ./examples/searchable-select |
searchable-select | Select ailesi: Searchable Select, Multi Select, Combobox, Autocomplete, Tag Input, Tree Select, Cascader, Dual Listbox |
| 3003 | go run ./examples/numeric-controls |
numeric-controls | Currency Input, Percentage Input, Rating |
| 3004 | go run ./examples/field-meta |
field-meta | Karakter sayacı (ShowCharCount) ve parola gücü (ShowStrength) |
| 3005 | go run ./examples/date-controls |
date-controls | Date Range Picker, Time Range Picker, Calendar Date Picker |
| 3006 | go run ./examples/identity-inputs |
identity-inputs | OTP/PIN, Country/Language/Timezone/Currency Picker, Phone Input |
| 3007 | go run ./examples/editors |
editors | Markdown Editor (goldmark), Rich Text (Quill), Code Editor (CodeMirror) |
| 3008 | go run ./examples/media-upload |
media-upload | Drag & Drop Upload, Image Upload, Avatar Upload + kırpma |
| 3009 | go run ./examples/misc-controls |
misc-controls | Emoji/Icon/Font Picker, Swatch Color Picker, Gradient Picker, Mention, Signature Pad |
| 3010 | go run ./examples/adapters/nethttp |
net/http adapter | Counter, düz net/http + adapters/stdlib |
| 3011 | go run ./examples/adapters/chi |
Chi adapter | Counter, Chi üzerinde adapters/stdlib Mount |
| 3012 | go run ./examples/adapters/gin |
Gin adapter | Counter, Gin üzerinde |
| 3013 | go run ./examples/adapters/echo |
Echo adapter | Counter, Echo üzerinde |
Herhangi birini repo kökünden çalıştırın, ardından yazdırılan URL'yi açın:
go run ./examples/counter
go run ./examples/contact-form
go run ./examples/searchable-select
Her örnek kendi portunu dinlediğinden, birkaçını aynı anda ayrı terminallerde
başlatabilirsiniz — farklı form kontrollerini yan yana karşılaştırırken
faydalıdır. Her örnek, repo kökünü runtime.Caller(0) ile çözer; böylece
mevcut çalışma dizininiz ne olursa olsun çalışır ve şunları bağlar:
/client→ çatının JS çalışma zamanı (client/)/forms→forms/style.cssve ilgili statik varlıklar (kullanıldığı yerlerde)/goui/ws→ WebSocket uç noktası (ws.Path, adapter tarafından bağlanır)/goui/upload,/goui/files/:id→ dosya yükleme uç noktaları (media-upload, misc-controls; adapterStoreseçeneği veyaupload.Mountile)
6. Sırada ne var
02-components.md— tamComponent/BaseComponent/Registry/ şablon sözleşmesi03-i18n.md— çevirmen (translator) kurulumu ve locale dosyaları04-sessions-and-websocket.md— Session/Hub yaşam döngüsü ve tel protokolü05-forms-tier1.md— her native form kontrolü06-validation.md— sunucu tarafı doğrulama kuralları07-forms-tier2.md— her zengin form kontrolü