DEV Community

Alex Spinov
Alex Spinov

Posted on

Wails Has a Free API — Build Desktop Apps with Go and Any Web Framework

Wails lets you build desktop applications using Go for the backend and any web framework for the frontend. Native feel, Go performance, modern web UI — without Electron's bloat.

Why Wails?

  • Go backend — goroutines, channels, the entire Go ecosystem
  • Any frontend — React, Vue, Svelte, Solid, plain HTML
  • Native webview — not Chromium (unlike Electron), ~5MB binary
  • Bidirectional binding — call Go from JS, call JS from Go

Quick Start

go install github.com/wailsapp/wails/v2/cmd/wails@latest
wails init -n myapp -t react-ts
cd myapp
wails dev
Enter fullscreen mode Exit fullscreen mode

Go Backend

// app.go
package main

import "context"

type App struct {
    ctx context.Context
}

func NewApp() *App {
    return &App{}
}

func (a *App) startup(ctx context.Context) {
    a.ctx = ctx
}

// Exposed to frontend automatically
func (a *App) Greet(name string) string {
    return fmt.Sprintf("Hello %s, from Go!", name)
}

func (a *App) GetUsers() ([]User, error) {
    return db.GetAllUsers()
}

func (a *App) SaveFile(content string) error {
    return os.WriteFile("output.txt", []byte(content), 0644)
}
Enter fullscreen mode Exit fullscreen mode

Frontend (React)

import { Greet, GetUsers, SaveFile } from '../wailsjs/go/main/App';

function App() {
  const [greeting, setGreeting] = useState('');

  const handleGreet = async () => {
    const result = await Greet('Alice');
    setGreeting(result); // "Hello Alice, from Go!"
  };

  const handleUsers = async () => {
    const users = await GetUsers(); // Typed from Go struct!
    console.log(users);
  };

  return (
    <div>
      <button onClick={handleGreet}>Greet</button>
      <p>{greeting}</p>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Events System

// Go → Frontend
func (a *App) StartProcess() {
    for i := 0; i <= 100; i++ {
        runtime.EventsEmit(a.ctx, "progress", i)
        time.Sleep(50 * time.Millisecond)
    }
}
Enter fullscreen mode Exit fullscreen mode
// Frontend
import { EventsOn } from '../wailsjs/runtime';

EventsOn('progress', (value: number) => {
  setProgress(value);
});
Enter fullscreen mode Exit fullscreen mode

Dialogs

func (a *App) OpenFile() string {
    file, _ := runtime.OpenFileDialog(a.ctx, runtime.OpenDialogOptions{
        Title: "Select a file",
        Filters: []runtime.FileFilter{
            {DisplayName: "Text Files", Pattern: "*.txt;*.md"},
        },
    })
    return file
}

func (a *App) SaveDialog() string {
    file, _ := runtime.SaveFileDialog(a.ctx, runtime.SaveDialogOptions{
        Title: "Save as",
    })
    return file
}
Enter fullscreen mode Exit fullscreen mode

Build

# Development
wails dev

# Production build
wails build

# Cross-compile
wails build -platform windows/amd64
wails build -platform darwin/universal
wails build -platform linux/amd64
Enter fullscreen mode Exit fullscreen mode

Building Go desktop tools? Check out my Apify actors for data extraction APIs, or email spinov001@gmail.com for custom Go desktop apps.

Wails, Tauri, or Electron — what do you build desktop apps with? Share below!

Top comments (0)