Build Status GoDoc Go Report Card


A very small library to build modern HTML5 desktop apps in Go. It uses Chrome browser as a UI layer. Unlike Electron it doesn't bundle Chrome into the app package, but rather reuses the one that is already installed. Lorca establishes a connection to the browser window and allows calling Go code from the UI and manipulating UI from Go in a seamless manner.


  • Pure Go library (no cgo) with a very simple API
  • Small application size (normally 5-10MB)
  • Best of both worlds - the whole power of HTML/CSS to make your UI look good, combined with Go performance and ease of development
  • Expose Go functions/methods and call them from JavaScript
  • Call arbitrary JavaScript code from Go
  • Asynchronous flow between UI and main app in both languages (async/await and Goroutines)
  • Supports loading web UI from the local web server or via data URL
  • Supports embedding all assets into a single binary
  • Supports testing your app with the UI in the headless mode
  • Supports multiple app windows
  • Supports packaging and branding (e.g. custom app icons). Packaging for all three OS can be done on a single machine using GOOS and GOARCH variables.

Also, limitations by design:

  • Requires Chrome/Chromium >= 70 to be installed.
  • No control over the Chrome window yet (e.g. you can't remove border, make it transparent, control position or size).
  • No window menu (tray menus and native OS dialogs are still possible via 3rd-party libraries)

If you want to have more control of the browser window - consider using webview library with a similar API, so migration would be smooth.


ui, _ := lorca.New("", "", 480, 320)
defer ui.Close()

// Bind Go function to be available in JS. Go function may be long-running and
// blocking - in JS it's represented with a Promise.
ui.Bind("add", func(a, b int) int { return a + b })

// Call JS function from Go. Functions may be asynchronous, i.e. return promises
n := ui.Eval(`Math.random()`).Float()

// Call JS that calls Go and so on and so on...
m := ui.Eval(`add(2, 3)`).Int()

// Wait for the browser window to be closed

Also, see examples for more details about binding functions, embedding assets and packaging binaries.

Hello World

Here are the steps to run the hello world example.

cd examples/counter
go get
go run main.go

How it works

Under the hood Lorca uses Chrome DevTools Protocol to instrument on a Chrome instance. First Lorca tries to locate your installed Chrome, starts a remote debugging instance binding to an ephemeral port and reads from stderr for the actual WebSocket endpoint. Then Lorca opens a new client connection to the WebSocket server, and instruments Chrome by sending JSON messages of Chrome DevTools Protocol methods via WebSocket. JavaScript functions are evaluated in Chrome, while Go functions actually run in Go runtime and returned values are sent to Chrome.

What's in a name?

There is kind of a legend, that before his execution Garcia Lorca have seen a sunrise over the heads of the soldiers and he said "And yet, the sun rises...". Probably it was the beginning of a poem. (J. Brodsky)

Lorca is an anagram of Carlo, a project with a similar goal for Node.js.


Code is distributed under MIT license, feel free to use it in your proprietary projects as well.




View Source
const (
	// PageA4Width is a width of an A4 page in pixels at 96dpi
	PageA4Width = 816
	// PageA4Height is a height of an A4 page in pixels at 96dpi
	PageA4Height = 1056


View Source
var ChromeExecutable = LocateChrome

    ChromeExecutable returns a string which points to the preferred Chrome executable file.


    func Embed

    func Embed(packageName, file string, dirs ...string) error

      Embed is a helper function that embeds assets from the given directories into a Go source file. It is designed to be called from some generator script, see example project to find out how it can be used.

      func LocateChrome

      func LocateChrome() string

        LocateChrome returns a path to the Chrome binary, or an empty string if Chrome installation is not found.

        func PDF

        func PDF(url, script string, width, height int) ([]byte, error)

          PDF converts a given URL (may be a local file) to a PDF file. Script is evaluated before the page is printed to PDF, you may modify the contents of the page there of wait until the page is fully rendered. Width and height are page bounds in pixels. PDF by default uses 96dpi density. For A4 page you may use PageA4Width and PageA4Height constants.

          func PNG

          func PNG(url, script string, x, y, width, height int, bg uint32, scale float32) ([]byte, error)

            PNG converts a given URL (may be a local file) to a PNG image. Script is evaluated before the "screenshot" is taken, so you can modify the contents of a URL there. Image bounds are provides in pixels. Background is in ARGB format, the default value of zero keeps the background transparent. Scale allows zooming the page in and out.

            This function is most convenient to convert SVG to PNG of different sizes, for example when preparing Lorca app icons.

            func PromptDownload

            func PromptDownload()

              PromptDownload asks user if he wants to download and install Chrome, and opens a download web page if the user agrees.


              type Bounds

              type Bounds struct {
              	Left        int         `json:"left"`
              	Top         int         `json:"top"`
              	Width       int         `json:"width"`
              	Height      int         `json:"height"`
              	WindowState WindowState `json:"windowState"`

                Bounds defines settable window properties.

                type UI

                type UI interface {
                	Load(url string) error
                	Bounds() (Bounds, error)
                	SetBounds(Bounds) error
                	Bind(name string, f interface{}) error
                	Eval(js string) Value
                	Done() <-chan struct{}
                	Close() error

                  UI interface allows talking to the HTML5 UI from Go.

                  func New

                  func New(url, dir string, width, height int, customArgs ...string) (UI, error)

                    New returns a new HTML5 UI for the given URL, user profile directory, window size and other options passed to the browser engine. If URL is an empty string - a blank page is displayed. If user profile directory is an empty string - a temporary directory is created and it will be removed on ui.Close(). You might want to use "--headless" custom CLI argument to test your UI code.

                    type Value

                    type Value interface {
                    	Err() error
                    	To(interface{}) error
                    	Float() float32
                    	Int() int
                    	String() string
                    	Bool() bool
                    	Object() map[string]Value
                    	Array() []Value

                      Value is a generic type of a JSON value (primitive, object, array) and optionally an error value.

                      type WindowState

                      type WindowState string

                        WindowState defines the state of the Chrome window, possible values are "normal", "maximized", "minimized" and "fullscreen".

                        const (
                        	// WindowStateNormal defines a normal state of the browser window
                        	WindowStateNormal WindowState = "normal"
                        	// WindowStateMaximized defines a maximized state of the browser window
                        	WindowStateMaximized WindowState = "maximized"
                        	// WindowStateMinimized defines a minimized state of the browser window
                        	WindowStateMinimized WindowState = "minimized"
                        	// WindowStateFullscreen defines a fullscreen state of the browser window
                        	WindowStateFullscreen WindowState = "fullscreen"


                        Path Synopsis
                        Code generated by Lorca.
                        Code generated by Lorca.