Documentation Index
Fetch the complete documentation index at: https://docs.go-mizu.dev/llms.txt
Use this file to discover all available pages before exploring further.
This guide walks you through creating a simple offline-first application using the sync package. You’ll learn how to set up a client, create collections, and use reactive primitives.
Prerequisites
- Go 1.22 or later
- Basic understanding of Go
Step 1: Create Your Project
mkdir sync-demo && cd sync-demo
go mod init sync-demo
go get github.com/go-mizu/mizu
Step 2: Define Your Data Type
Create main.go:
package main
import (
"context"
"fmt"
"time"
"github.com/go-mizu/mizu/view/sync"
)
// Todo is our synchronized data type
type Todo struct {
Title string `json:"title"`
Completed bool `json:"completed"`
}
func main() {
// Create the sync client
client := sync.New(sync.Options{
BaseURL: "http://localhost:8080/_sync", // Your sync server
Scope: "user:demo", // Data partition
// Optional callbacks
OnSync: func(cursor uint64) {
fmt.Printf("Synced to cursor %d\n", cursor)
},
OnOnline: func() {
fmt.Println("Connected to server")
},
OnOffline: func() {
fmt.Println("Working offline")
},
OnError: func(err error) {
fmt.Printf("Error: %v\n", err)
},
})
// ... continue below
}
Step 4: Start the Client
// Start sync in the background
ctx := context.Background()
if err := client.Start(ctx); err != nil {
fmt.Printf("Initial sync failed: %v\n", err)
// Client continues working offline
}
defer client.Stop()
Step 5: Create a Collection
// Create a typed collection
todos := sync.NewCollection[Todo](client, "todo")
Step 6: Use the Collection
// Create a todo (works even offline!)
todo := todos.Create("todo-1", Todo{
Title: "Learn sync",
Completed: false,
})
// Read the value
fmt.Printf("Created: %s\n", todo.Get().Title)
// Update it
todo.Set(Todo{
Title: "Learn sync",
Completed: true,
})
// List all todos
fmt.Printf("\nAll todos (%d):\n", todos.Count())
for _, entity := range todos.All() {
t := entity.Get()
status := "[ ]"
if t.Completed {
status = "[x]"
}
fmt.Printf(" %s %s\n", status, t.Title)
}
Step 7: Add Reactivity
// React to changes automatically
sync.NewEffect(func() {
count := todos.Count()
fmt.Printf("\n>>> Todo count changed: %d\n", count)
})
// Create more todos
todos.Create("todo-2", Todo{Title: "Build app"})
todos.Create("todo-3", Todo{Title: "Deploy"})
// Delete one
todos.Get("todo-2").Delete()
Complete Example
package main
import (
"context"
"fmt"
"time"
"github.com/go-mizu/mizu/view/sync"
)
type Todo struct {
Title string `json:"title"`
Completed bool `json:"completed"`
}
func main() {
// Create client
client := sync.New(sync.Options{
BaseURL: "http://localhost:8080/_sync",
Scope: "user:demo",
OnSync: func(cursor uint64) {
fmt.Printf("Synced to cursor %d\n", cursor)
},
OnOnline: func() {
fmt.Println("Connected!")
},
OnOffline: func() {
fmt.Println("Offline - changes will sync later")
},
})
// Start sync
ctx := context.Background()
client.Start(ctx)
defer client.Stop()
// Create collection
todos := sync.NewCollection[Todo](client, "todo")
// Log changes reactively
sync.NewEffect(func() {
fmt.Printf("Todo count: %d\n", todos.Count())
})
// Create some todos
todos.Create("1", Todo{Title: "Learn Go"})
todos.Create("2", Todo{Title: "Build sync app"})
todos.Create("3", Todo{Title: "Deploy"})
// Mark one complete
entity := todos.Get("1")
todo := entity.Get()
todo.Completed = true
entity.Set(todo)
// Find incomplete
incomplete := todos.Find(func(t Todo) bool {
return !t.Completed
})
fmt.Printf("\nIncomplete todos:\n")
for _, e := range incomplete {
fmt.Printf(" - %s\n", e.Get().Title)
}
// Keep running to see sync happen
time.Sleep(3 * time.Second)
}
Running the Example
If you have a sync server running:
Output:
Connected!
Synced to cursor 0
Todo count: 0
Todo count: 1
Todo count: 2
Todo count: 3
Incomplete todos:
- Build sync app
- Deploy
Synced to cursor 3
What Just Happened?
1. Client connects to server
│
â–¼
2. Initial sync (pulls any existing data)
│
â–¼
3. Collections created (bound to client)
│
â–¼
4. Effects set up (react to changes)
│
â–¼
5. Local changes made (immediate)
│
â–¼
6. Mutations queued (background)
│
â–¼
7. Push to server (when online)
│
â–¼
8. OnSync callback (confirms sync)
Key points:
- Changes are immediate locally
- Sync happens in the background
- Works offline - mutations queue until connected
- Reactive - effects run automatically when data changes
Understanding the Parts
The client manages:
- Connection to sync server
- Mutation queue (for offline support)
- Pulling changes from server
- Online/offline state
Collection
A collection is a reactive set of entities:
- Type-safe with generics
- Syncs with server automatically
- Supports CRUD operations
- Reactive (triggers effects)
An entity is a single record:
- Has a unique ID
- Reactive Get/Set
- Can be deleted
- Tracks existence
Reactive Primitives
- Signal: A value that notifies when changed
- Computed: A derived value that auto-updates
- Effect: A function that runs when dependencies change
Next Steps