Getting started
Getting started
Install the tools, then create, develop and build an app, with native UI or a web frontend.
A MyGo app shows its windows with a web frontend, in the system's webview,
or with native UI that MyGo draws itself, written in Go. mygo init starts a project of either kind, and an app can add windows of the
other kind later.
Install
Install Go 1.27 or later. A project with a web frontend also needs Bun, which runs its tools, and apps with web pages need the system's webview:
- on Linux, GTK 3 and WebKitGTK 4.1, e.g.
sudo apt install libwebkit2gtk-4.1-0on Debian and Ubuntu; - on Windows 10, the WebView2 Runtime, which Windows 11 includes.
Native UI needs nothing more: Go builds the app, and it runs on what the system has (GTK 3 on Linux).
The mygo command line tool creates, runs and packages apps. It is a Go
program, which Go runs without installing it:
go run github.com/egoist/mygo/cmd/mygo@latest init my-appProjects with a web frontend also depend on it through npm, as the
mygo-cli package, so Bun or npm create one too:
bunx mygo-cli init my-app # or: npx mygo-cli init my-appYou can also install the CLI with Go, which puts mygo on your PATH:
go install github.com/egoist/mygo/cmd/mygo@latest
mygo init my-appmygo doctor checks that the machine has what MyGo needs.
Create a project
A web frontend
mygo init my-app creates a Go module and a TypeScript frontend built with
Vite, side by side, and installs their dependencies:
my-app/
├── main.go the app: its windows and the Go code the page calls
├── go.mod
├── mygo.config.ts the app's name, identifier and version, and how to build it
├── package.json the scripts, and the frontend's dependencies
├── index.html the page
├── src/
│ ├── main.ts the page's code
│ ├── style.css
│ └── mygo.ts the typed client of the Go code, generated
├── vite.config.ts
├── tsconfig.json
└── resources/
└── icon.png the app icon, a 1024×1024 PNGBuilds go to dist/ (the frontend) and build/ (the packaged apps), and
the development app to .mygo/; .gitignore leaves them out. See
configuration for the fields of mygo.config.ts.
Native UI
mygo init -template native my-app creates an app whose window shows
native UI: a Go module alone, with no frontend and no Bun.
my-app/
├── main.go the app: its state, its view and its window
├── main_test.go a test of the view, which runs without a window
├── go.mod with the CLI as a tool
├── mygo.json the app's name, identifier and version
└── resources/
└── icon.png the app icon, a 1024×1024 PNGThe module has the CLI as a
tool: go tool mygo runs it at the version go.mod pins, which
go get -tool github.com/egoist/mygo/cmd/mygo@latest updates with MyGo.
Develop
cd my-app
bun run dev # a web frontend: runs mygo dev
go tool mygo dev # native UImygo dev builds a development version of the app and starts it, then
rebuilds and restarts it when you edit a .go file, the configuration, the
icon or a resource. A build that fails to compile keeps the previous one
running. Quit the app, or press Ctrl+C, to stop.
With a web frontend, it also writes src/mygo.ts and starts the Vite dev
server, from which the development app loads its pages: edit src/main.ts
or src/style.css and Vite updates the page right away. Development builds
have the web inspector: right-click the page and choose Inspect Element
(Inspect on Windows), or call win.Page().OpenDevTools().
On macOS the development app is a real app bundle, My App Dev with the
identifier of the app plus .dev, so that it keeps its data, preferences
and permissions apart from the installed app.
Call Go
From the page
main.go binds a Go value, whose exported methods the page can call:
// Greeter is callable from the frontend: `mygo generate` turns its methods
// into typed TypeScript functions in src/mygo.ts.
type Greeter struct{}
// Greet returns a greeting for name.
func (Greeter) Greet(name string) string {
if name == "" {
name = "stranger"
}
return "Hello, " + name + "! This message comes from Go."
}
// Tick is sent to the page every second.
var Tick = mygo.NewEvent[time.Time]("tick")
func main() {
mygo.Bind(Greeter{})
// ...
}src/mygo.ts, which mygo dev keeps up to date, turns them into typed
functions and events:
import { Greeter, events } from "./mygo";
const greeting = await Greeter.greet("Ada"); // Promise<string>
events.tick.on((time) => console.log(time)); // time: stringAdd a method to Greeter, save, and it is there to call once the app has
restarted. Calling Go from the frontend covers what methods
can take and return, errors, events and security.
From native UI
Native UI is Go, so it calls your code directly, with no bindings. The view is a function of your app's state that MyGo calls to build each frame; it asks its elements what happened since the last one:
func (a *app) view(c *ui.Context) {
ui.Column(c).Fill().Center().Gap(16).Children(func() {
ui.TextInput(c, &a.name).Placeholder("Your name").Width(240)
if ui.PrimaryButton(c, "Greet").Clicked() {
a.greeting = greet(a.name) // your Go code
}
ui.Text(c, a.greeting)
})
}main_test.go clicks and types into the view without a window, as fast as
a unit test: run go test. Native UI covers layout, widgets,
text, input, drawing and changing the state from other goroutines.
Build
bun run build # a web frontend: runs mygo build
go tool mygo build # native UImygo build compiles the app, with the frontend built by Vite embedded in
it when there is one, and packages it for the machine's platform in
build/<os>-<arch>/:
| Platform | Output |
|---|---|
| macOS | My App.app, and a disk image my-app-0.1.0-arm64.dmg |
| Windows | My App.exe, and an installer my-app-setup-0.1.0-amd64.exe |
| Linux | the executable my-app with its desktop entry and icon, their archive with install.sh, which installs it for the user, and .deb and .rpm packages |
MyGo needs no cgo, so any machine builds for every platform:
bun run build -- -platform darwin/universal,windows/amd64,linux/amd64
go tool mygo build -platform darwin/universal,windows/amd64,linux/amd64The apps run where they are, but to ship them to users, sign them: see Building and distributing.
Next steps
- Windows and the application, to shape the app.
- Native UI, to build interfaces in Go, or the frontend, for web pages.
- Menus and the tray and the desktop APIs.
- The examples in the repository:
- with web pages:
examples/hello(the smallest app),examples/todo(typed services and events, persistence, dialogs, menus, several windows),examples/frameless(a custom title bar) andexamples/native(menus, a tray icon, dialogs, notifications, a global shortcut, the clipboard and dark mode); - with native UI:
examples/clipboard(copying and dragging text, HTML, lazy JSON, and file lists),examples/counter-native(a counter with a test of its view),examples/vibrancy(a translucent sidebar under an inset title bar, its material picked in it),examples/effort-slider(a web demo's animated slider redrawn: letters blurring in, a burst of pixels, a shaking card),examples/confetti(canvas-confetti's demos, every piece flying on poses that only paint),examples/wind(the glyph texture behind the Claude app's Code tab: characters lit by a passing wind, ripples from clicks, drawn by two shaders written in Go),examples/blackhole(a black hole whose light a shader traces through its gravity: the lensed accretion disk, Doppler beaming and an Einstein ring of stars, in three passes with bloom),examples/chat-glow(an assistant lit as Apple Intelligence: the window's edges glowing while it thinks, borders of conic gradients blurred, and a glowing field, shimmering text and an orb, shaders),examples/timeline(an intro on one playhead: a card sliding in, its title and rows following it, with play, pause, reverse and restart) andexamples/gallery(a tour of the toolkit: layout, widgets, text editing, a list of ten thousand rows, drawing and overlays).
- with web pages: