Desktop Apps

irgo's desktop mode creates native applications for macOS, Windows, and Linux using a real HTTP server and native webview window.

How Desktop Mode Works

Unlike mobile mode (which uses virtual HTTP), desktop mode:

  1. Starts a Go HTTP server on an auto-selected localhost port
  2. Opens a native window with an embedded browser engine (WebKit on macOS, Chromium on Windows/Linux)
  3. The webview navigates to the localhost URL
┌─────────────────────────────────────────┐│           Desktop App                    ││  ┌─────────────────────────────────┐    ││  │    Native Webview Window         │    ││  │  (Chromium/WebKit)               │    ││  │  Navigates to localhost:PORT     │    ││  └──────────────┬──────────────────┘    ││                 │ HTTP                   ││  ┌──────────────▼──────────────────┐    ││  │    Go HTTP Server                │    ││  │  • Page Routes → HTML            │    ││  │  • API Routes → JSON             │    ││  │  • Static Assets                 │    ││  └─────────────────────────────────┘    │└─────────────────────────────────────────┘

This architecture means your app works exactly like the web dev server, but packaged as a native desktop application.

Prerequisites

Desktop builds require CGO and a C compiler:

Warning

CGO must be enabled. If you see errors about CGO_ENABLED=0, ensure you have a C compiler installed and set CGO_ENABLED=1.

Desktop Entry Point

Desktop apps use a separate entry point with the desktop build tag:

main_desktop.go
//go:build desktoppackage mainimport (    "flag"    "fmt"    "net/http"    "myapp/app"    "github.com/stukennedy/irgo/desktop")func main() {    devMode := flag.Bool("dev", false, "Enable devtools")    flag.Parse()    // Create router    r := app.NewRouter()    // Set up HTTP handler with static files    mux := http.NewServeMux()    staticDir := desktop.FindStaticDir()    mux.Handle("/static/", http.StripPrefix("/static/",        http.FileServer(http.Dir(staticDir))))    mux.Handle("/", r.Handler())    // Configure desktop app    config := desktop.DefaultConfig()    config.Title = "My App"    config.Debug = *devMode    // Create and run    desktopApp := desktop.New(mux, config)    fmt.Println("Starting desktop app...")    if err := desktopApp.Run(); err != nil {        fmt.Printf("Error: %v\n", err)    }}

Configuration

config := desktop.Config{    Title:     "My App",     // Window title    Width:     1024,         // Initial window width    Height:    768,          // Initial window height    Resizable: true,         // Allow window resizing    Debug:     false,        // Enable browser devtools    Port:      0,            // 0 = auto-select available port}// Or start with defaultsconfig := desktop.DefaultConfig()config.Title = "My App"config.Debug = true

Configuration Options

OptionTypeDefaultDescription
Titlestring"Irgo App"Window title bar text
Widthint1024Initial window width in pixels
Heightint768Initial window height in pixels
ResizablebooltrueAllow window resizing
DebugboolfalseEnable browser devtools (right-click inspect)
Portint0Server port (0 = auto-select)

Running Desktop Apps

# Run directly (compiles and runs)irgo run desktop# With devtools enabled (for debugging)irgo run desktop --dev

Building Desktop Apps

# Build for current platformirgo build desktop# Build for specific platformirgo build desktop macos     # Creates build/desktop/macos/MyApp.appirgo build desktop windows   # Creates build/desktop/windows/MyApp.exeirgo build desktop linux     # Creates build/desktop/linux/myapp

Build Output

build/desktop/├── macos/│   └── MyApp.app/           # macOS application bundle│       └── Contents/│           ├── MacOS/│           │   └── myapp    # Executable│           ├── Resources/│           │   └── static/  # Static assets│           └── Info.plist   # App metadata├── windows/│   └── MyApp.exe            # Windows executable└── linux/    └── myapp                # Linux binary

Utility Functions

import "github.com/stukennedy/irgo/desktop"// Find static files directory// Works both in dev (./static) and bundled appstaticDir := desktop.FindStaticDir()// Find bundled resources// Looks in app bundle on macOS, same dir as exe on Windows/LinuxresourcePath := desktop.FindResourcePath("config.json")

Desktop vs Mobile Comparison

AspectDesktopMobile
HTTPReal localhost serverVirtual (no sockets)
BridgeNone (direct HTTP)gomobile + native code
Entry Pointmain_desktop.gomain.go
Build Tagdesktop!desktop
CGO RequiredYes (webview)No
DevToolsNative browser devtoolsSafari/Chrome remote debugging

Troubleshooting

CGO Errors

If you see "CGO_ENABLED=0" errors:

# Check CGO is enabledgo env CGO_ENABLED# Set it if neededexport CGO_ENABLED=1# Make sure you have a C compiler# macOSxcode-select --install# Linuxsudo apt install build-essential

Webview Not Showing (Linux)

# Install WebKit2GTKsudo apt install libwebkit2gtk-4.0-dev

Static Files Not Found

Use desktop.FindStaticDir() to locate static files. It handles both development and bundled app scenarios.

Next Steps