UCloud logo UCloud logo UCloud
v2025.1.0
  1. UCloud/Core
  2. 1. Introduction
  3. 2. Projects
  4. 3. Accounting
  5. 4. Orchestration
  6. UCloud/IM for Slurm-based HPC
  7. 5. Installation
  8. 6. Architecture and Networking
  9. 7. User and Project Management
  10. 8. Filesystem Integration
    1. 8.1. Inter-provider file transfers
  11. 9. Slurm Integration
    1. 9.1. Application Management
    2. 9.2. Built-in Applications
  12. 10. Reference
    1. 10.1. Configuration
    2. 10.2. CLI
  13. 11. Appendix
    1. 11.1. Built-in Application Index
  14. UCloud/IM for Kubernetes
  15. 12. Installation
  16. 13. Architecture and Networking
  17. 14. Filesystem Integration
  18. 15. Compute Jobs
    1. 15.1. Public Links
    2. 15.2. Public IPs
    3. 15.3. License Servers
    4. 15.4. SSH Servers
  19. 16. Integrated applications
    1. 16.1. Syncthing
    2. 16.2. Integrated terminal
  20. 17. UCX applications
    1. 17.1. Hello world
    2. 17.2. Data binding
    3. 17.3. UI events
    4. 17.4. Component reference
    5. 17.5. API reference
  21. 18. Reference
    1. 18.1. Configuration
    2. 18.2. CLI
  22. H: Procedures
  23. 19. H: Procedures
  24. 20. H: Introduction
  25. 21. H: Auditing
  26. 22. H: Auditing scenario
  27. 23. H: GitHub actions
  28. 24. H: Deployment
  29. 25. H: 3rd party dependencies (risk assesment)
  1. Links
  2. Source Code
  3. Releases

Hello world

This is a minimal UCX application with one bound input and one button event.

package main

import (
    "fmt"
    "strings"
    "sync"

    "ucloud.dk/shared/pkg/ucx"
)

type helloApp struct {
    mu      sync.Mutex   `ucx:"-"`
    session *ucx.Session `ucx:"-"`

    Name    string
    Message string
}

func NewHelloApp() ucx.Application {
    return &helloApp{
        Name:    "UCloud",
        Message: "Click the button",
    }
}

func (app *helloApp) Mutex() *sync.Mutex      { return &app.mu }
func (app *helloApp) Session() **ucx.Session  { return &app.session }
func (app *helloApp) OnInit()                 {}

func (app *helloApp) UserInterface() ucx.UiNode {
    return ucx.Flex(ucx.FlexProps{Direction: "column", Gap: 8}).
        Sx(ucx.SxP(4)).
        Children(
            ucx.H2("UCX hello world"),
            ucx.InputText("name", "Name", "Type your name", "name"),
            ucx.Button("sayHello", "Say hello", ucx.ColorPrimaryMain).
                On(ucx.UiEventClick, func(ev ucx.UiEvent) {
                    app.Message = fmt.Sprintf("Hello %s!", strings.TrimSpace(app.Name))
                }),
            ucx.TextBound("message"),
        )
}

func (app *helloApp) OnMessage(frame ucx.Frame) {
    switch frame.Opcode {
    case ucx.OpModelInput:
        app.Name = strings.TrimSpace(app.Name)
        if app.Name == "" {
            app.Message = "Please enter a name"
        }
    }
}

func main() {
    ucx.AppServe(func() ucx.Application {
        return NewHelloApp()
    })
}

What is happening

  • Name and Message are exported fields, so they are serialized into the UCX model.
  • InputText(..., "name") binds to the Name field (Name -> name by default).
  • button clicks are handled with .On(ucx.UiEventClick, ...).
  • TextBound("message") renders the Message field.
  • ucx.AppServe(...) handles handshake, mount, model patching, and event dispatch.

First extensions

From here, most real apps add:

  • validation (errors.<field> paths),
  • collections ([]struct) displayed through ucx.List(...),
  • and backend calls via ucxsvc / ucxapi when submit is clicked.
Previous UCX applications
Next Data binding