Skip to content

THE FIELD GUIDE

A small idea, brought to life.

Create, inspect, test and build your first Web UI application.

View source · ui/next/guides/first-steps.md
On this page

Build a Web interface with ordinary typed Volang code. Components describe the page, state records what can change, and the browser keeps native HTML behavior. The Web application runs with the Wasm VM.

This guide uses the new Web UI preview in github.com/vo-lang/ui/next. Use a matching toolchain that includes the Web UI tools. A toolchain with the native desktop SDK can also run and package this application with vo ui run and vo ui package; see the desktop preview guide in the toolkit for platform requirements.

Create your first application#

Check the installation and create a small project:

vo ui verify
vo ui create my-app
vo ui dev --project my-app

Open the local address printed by the development server. Change a name, press the button, then edit the source and see the result. Node.js 24 or newer runs the packaged tools; the application needs no npm manifest or JavaScript application code. The toolkit contains its matching compiler, framework and build libraries.

The project has a small set of files with clear jobs:

FilePurpose
app/app.voShared component code used by development, production and server rendering
web/app.cssYour application's appearance
main.voProduction entry
development/main.voDevelopment entry with the inspector and reload support
prerender/main.voServer HTML entry using the same application
ui-next.jsonBuild, entry and optional feature settings
vo.mod, vo.lock, vendor/uiThe exact framework source selected for this project
tests/browserBrowser tests using labels, roles and visible results

Start with a component#

Replace app/app.vo with this complete shared application:

package app

import (
	"fmt"
	ui "github.com/vo-lang/ui/next"
	"github.com/vo-lang/ui/next/kit"
)

var counterType = ui.Define("guide.Counter")

func View(initial string) ui.View {
	return ui.Component(counterType, func(scope *ui.Scope) ui.View {
		ui.InspectProp(scope, "initial", initial)
		count := ui.Int(scope, "count", 0)
		return ui.Element("main", ui.Element("h1", ui.Text("A little progress.")), kit.Button(kit.ButtonProps{
			OnPress: func() {
				count.Set(count.Get() + 1)
			},
		}, ui.Text("Take a step")), ui.Element("output", ui.Text("Steps taken: " + fmt.Sprint(count.Get()))).Attr("aria-label", "Progress").Attr("aria-live", "polite")).Class("vui", "starter").StyleScope("starter-app")
	})
}

Define the component type once at package scope. Each mounted instance gets its own scope, so two instances can keep independent counts. Int finds the same state by its local name on each render. Get reads it; Set notifies the components that depend on it. The button runs its action after a browser click.

Element and Text compose semantic HTML. kit.Button adds shared presentation and button behavior. Pass typed values, callbacks and child views through ordinary Vo functions when extracting your own components. InspectProp optionally shows the initial input in the development panel without changing how it is passed.

Keep the shared View(initial string) entry when changing the application. That lets server rendering and browser activation agree about their first view. Update the starter's browser test when you change its labels or behavior.

Check, test and build#

vo ui check --project my-app
vo ui browsers install
vo ui test --project my-app
vo ui build --project my-app
vo ui preview --project my-app

Checking reports source and formatting errors. Testing builds the actual application and runs its browser tests against Wasm VM in Chromium, Firefox and WebKit. The browser installation is needed once for the matching toolkit. Use UI_NEXT_BROWSER=chromium for a focused local run.

The default build includes static server HTML, application bytecode and the shared Wasm VM runtime. The output is under my-app/target/ui-next/dist; preview serves that output. Omit defaultBackend or set it to vm in ui-next.json. Development uses the same VM with rebuilds and diagnostics.

Inspect an update#

Open Inspect components in the development page. Expand a component to see its declared props, scalar state, dependencies and latest update cause. Press the button, wait for the new count, then capture again. Requests and subscriptions show their owner, status, replies, timeout and observed duration.

The panel samples only when requested. Its timing includes queueing and rendering work; use a production benchmark for performance comparisons. Production entries omit the optional collector and panel. Objects and undeclared closure captures remain opaque, and request bodies are not recorded.

Source errors keep the last working application visible. Fix the source to resume development. Compatible reloads restore supported state and native input; when a change cannot preserve state, the development message explains the reset.

Continue with state and identity and lifecycle and requests.

Built with Volang UI · A work in progress, made to be explored.
Opening Studio…