Core Concepts

Understand the fundamental building blocks of GoliveKit.

Component Interface

Every GoliveKit component implements the core.Component interface:

pkg/core/component.go
type Component interface { // Name returns the unique component identifier Name() string // Mount is called when the component is first loaded Mount(ctx context.Context, params Params, session Session) error // Render returns the HTML representation Render(ctx context.Context) Renderer // HandleEvent processes user interactions HandleEvent(ctx context.Context, event string, payload map[string]any) error // Terminate is called when the component is destroyed Terminate(ctx context.Context, reason TerminateReason) error }

Component Lifecycle

┌─────────────────────────────────────────────────────────────┐ │ HTTP REQUEST │ │ │ │ │ ▼ │ │ Mount() │ │ │ │ │ ▼ │ │ Render() │ │ │ │ │ ▼ │ │ HTML Response │ └─────────────────────────────────────────────────────────────┘ │ │ WebSocket Connect ▼ ┌─────────────────────────────────────────────────────────────┐ │ INTERACTIVE PHASE │ │ │ │ │ ┌──────────────┴──────────────┐ │ │ │ │ │ │ ▼ │ │ │ HandleEvent() │ │ │ │ │ │ │ ▼ │ │ │ Render() │ │ │ │ │ │ │ ▼ │ │ │ Compute Diff ──────────────────────►│ │ │ │ │ │ │ ▼ │ │ │ Send to Client │ │ │ │ │ │ │ └─────────────────────────────┘ │ │ │ │ │ │ Disconnect │ │ ▼ │ │ Terminate() │ └─────────────────────────────────────────────────────────────┘

BaseComponent

Use core.BaseComponent to get common functionality:

counter.go
type Counter struct { core.BaseComponent // Provides Assigns(), Socket(), etc. Count int } func (c *Counter) Mount(ctx context.Context, params core.Params, session core.Session) error { c.Count = 0 // Access assigns c.Assigns().Set("initialized", true) return nil }

Assigns (State)

Assigns is a thread-safe key-value store for component state:

assigns.go
// Set a value c.Assigns().Set("user", user) c.Assigns().Set("items", items) c.Assigns().Set("loading", false) // Get a value user := c.Assigns().Get("user") // Get with type assertion if user, ok := c.Assigns().Get("user").(*User); ok { fmt.Println(user.Name) } // Check if key exists if c.Assigns().Has("user") { // Key exists } // Delete a key c.Assigns().Delete("user") // Clone for safe iteration snapshot := c.Assigns().Clone()

Socket

The Socket provides access to the WebSocket connection:

socket.go
// Send a message to the client c.Socket().Send("event_name", map[string]any{ "message": "Hello!", }) // Push a redirect c.Socket().Redirect("/dashboard") // Get the socket ID id := c.Socket().ID()

Rendering

The Render method returns HTML using the Renderer interface:

render.go
func (c *Counter) Render(ctx context.Context) core.Renderer { return core.RendererFunc(func(ctx context.Context, w io.Writer) error { // Use data-live-view to identify the component // Use data-slot for efficient partial updates fmt.Fprintf(w, ` <div data-live-view="counter"> <h1>Count: <span data-slot="count">%d</span></h1> <button lv-click="increment">+</button> <button lv-click="decrement">-</button> </div> `, c.Count) return nil }) }

Important attributes:

  • data-live-view="name" - Identifies the LiveView component root
  • data-slot="id" - Marks regions for efficient partial updates