Getting started

go-app is a package to build progressive web apps (PWA) with Go programming language and WebAssembly.

This document is about how to get started by showing how to write and build a simple hello world! PWA.


Using this package requires a fully functional Go environment installed with a Go version equal to or greater than 1.14. Instructions about how to install and set up Go can be found on

Go installation can be checked with the following command in a terminal:

go version


Create a Go package for your PWA and change directory to the newly created location:

mkdir -p $GOPATH/src/
cd $GOPATH/src/

Then Initialize the go module and download the go-app package.

go mod init
go get -u


Here is the code used to create a progressive web app that displays a simple Hello World.

package main

import (


// hello is a component that displays a simple "Hello World!". A component is a
// customizable, independent, and reusable UI element. It is created by
// embedding app.Compo into a struct.
type hello struct {

// The Render method is where the component appearance is defined. Here, a
// "Hello World!" is displayed as a heading.
func (h *hello) Render() app.UI {
	return app.H1().Text("Hello World!")

// The main function is the entry point where the app is configured and started.
// It is executed in 2 different environments: A client (the web browser) and a
// server.
func main() {
	// The first thing to do is to associate the hello component with a path.
	// This is done by calling the Route() function,  which tells go-app what
	// component to display for a given path, on both client and server-side.
	app.Route("/", &hello{})

	// Once the routes set up, the next thing to do is to either launch the app
	// or the server that serves the app.
	// When executed on the client-side, the RunWhenOnBrowser() function
	// launches the app,  starting a loop that listens for app events and
	// executes client instructions. Since it is a blocking call, the code below
	// it will never be executed.
	// On the server-side, RunWhenOnBrowser() does nothing, which allows the
	// writing of server logic without needing precompiling instructions.

	// Finally, launching the server that serves the app is done by using the Go
	// standard HTTP package.
	// The Handler is an HTTP handler that serves the client and all its
	// required resources to make it work into a web browser. Here it is
	// configured to handle requests with a path that starts with "/".
	http.Handle("/", &app.Handler{
		Name:        "Hello",
		Description: "An Hello World! example",

	if err := http.ListenAndServe(":8000", nil); err != nil {

Build and run

Running a progressive app with go-app requires 2 Go programs:

  • A client that runs in a web browser
  • A server that serves the client and its resources

At this point, the package has the following content:

├── go.mod
├── go.sum
└── main.go

0 directories, 4 files

Building the client

GOARCH=wasm GOOS=js go build -o web/app.wasm

Note that the build output is explicitly set to web/app.wasm. The reason why is that the Handler expects the client to be a static resource located at the /web/app.wasm path.

Building the server

go build

Launching the app

Now the client and server built, the package has the following content:

├── go.mod
├── go.sum
├── hello
├── main.go
└── web
    └── app.wasm

1 directory, 6 files

The server is launched with the following command:


The app is now accessible from a web browser at http://localhost:8000.


The build process can be simplified by writing a makefile:

	GOARCH=wasm GOOS=js go build -o web/app.wasm
	go build

run: build

It can now be built and ran with this single command:

make run


Report issue

Found something incorrect, a typo or have suggestions to improve this article? Let me know :)

Loading go-app documentation...