Wails — Desktop Apps with Go and Web Frontend

## Overview

25 stars

Best use case

Wails — Desktop Apps with Go and Web Frontend is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

## Overview

Teams using Wails — Desktop Apps with Go and Web Frontend should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/wails/SKILL.md --create-dirs "https://raw.githubusercontent.com/ComeOnOliver/skillshub/main/skills/TerminalSkills/skills/wails/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/wails/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How Wails — Desktop Apps with Go and Web Frontend Compares

Feature / AgentWails — Desktop Apps with Go and Web FrontendStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

## Overview

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Wails — Desktop Apps with Go and Web Frontend


## Overview


Wails, the Go framework for building desktop applications with web frontends. Helps developers build lightweight, fast desktop apps where the backend is Go and the frontend is any web framework (React, Vue, Svelte), communicating through auto-generated TypeScript bindings.


## Instructions

### Project Setup

```bash
# Install Wails CLI
go install github.com/wailsapp/wails/v2/cmd/wails@latest

# Check system dependencies
wails doctor

# Create a new project (React + TypeScript)
wails init -n my-app -t react-ts
cd my-app

# Development mode (hot reload for frontend + backend)
wails dev

# Build production binary
wails build                         # Outputs to build/bin/
wails build -platform darwin/amd64  # Cross-compile
wails build -nsis                   # Windows installer
```

### Go Backend

```go
// app.go — Application backend with methods exposed to frontend
// Methods on the App struct are automatically callable from JavaScript.

package main

import (
	"context"
	"database/sql"
	"fmt"
	"os"
	"path/filepath"

	_ "modernc.org/sqlite"
)

// App struct — any exported method becomes available in the frontend
type App struct {
	ctx context.Context
	db  *sql.DB
}

// startup is called when the app starts — initialize resources here
func (a *App) startup(ctx context.Context) {
	a.ctx = ctx

	// Open SQLite database in user's app data directory
	homeDir, _ := os.UserHomeDir()
	dbPath := filepath.Join(homeDir, ".my-app", "data.db")
	os.MkdirAll(filepath.Dir(dbPath), 0755)

	db, err := sql.Open("sqlite", dbPath)
	if err != nil {
		fmt.Printf("Failed to open database: %v\n", err)
		return
	}
	a.db = db

	// Create tables
	a.db.Exec(`CREATE TABLE IF NOT EXISTS notes (
		id INTEGER PRIMARY KEY AUTOINCREMENT,
		title TEXT NOT NULL,
		content TEXT NOT NULL DEFAULT '',
		created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
		updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
	)`)
}

// Note is a data model — returned to frontend as typed TypeScript interface
type Note struct {
	ID        int64  `json:"id"`
	Title     string `json:"title"`
	Content   string `json:"content"`
	CreatedAt string `json:"createdAt"`
	UpdatedAt string `json:"updatedAt"`
}

// GetNotes returns all notes — callable from frontend as GetNotes()
func (a *App) GetNotes() ([]Note, error) {
	rows, err := a.db.Query("SELECT id, title, content, created_at, updated_at FROM notes ORDER BY updated_at DESC")
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var notes []Note
	for rows.Next() {
		var n Note
		rows.Scan(&n.ID, &n.Title, &n.Content, &n.CreatedAt, &n.UpdatedAt)
		notes = append(notes, n)
	}
	return notes, nil
}

// CreateNote creates a new note — frontend calls CreateNote(title)
func (a *App) CreateNote(title string) (*Note, error) {
	result, err := a.db.Exec("INSERT INTO notes (title) VALUES (?)", title)
	if err != nil {
		return nil, err
	}
	id, _ := result.LastInsertId()
	return &Note{ID: id, Title: title, Content: ""}, nil
}

// UpdateNote saves note content — called on every edit
func (a *App) UpdateNote(id int64, title, content string) error {
	_, err := a.db.Exec(
		"UPDATE notes SET title = ?, content = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?",
		title, content, id,
	)
	return err
}

// DeleteNote removes a note
func (a *App) DeleteNote(id int64) error {
	_, err := a.db.Exec("DELETE FROM notes WHERE id = ?", id)
	return err
}

// OpenFile opens a native file dialog and returns the file content
func (a *App) OpenFile() (string, error) {
	selection, err := runtime.OpenFileDialog(a.ctx, runtime.OpenDialogOptions{
		Title: "Open File",
		Filters: []runtime.FileFilter{
			{DisplayName: "Text Files", Pattern: "*.txt;*.md"},
		},
	})
	if err != nil {
		return "", err
	}
	data, err := os.ReadFile(selection)
	return string(data), err
}
```

### Frontend (React + TypeScript)

```tsx
// frontend/src/App.tsx — React frontend with auto-generated bindings
// Wails generates TypeScript types from Go structs and functions.

import { useState, useEffect } from "react";
// These imports are auto-generated by Wails from Go code
import { GetNotes, CreateNote, UpdateNote, DeleteNote } from "../wailsjs/go/main/App";
import { main } from "../wailsjs/go/models";

function App() {
  const [notes, setNotes] = useState<main.Note[]>([]);
  const [selectedNote, setSelectedNote] = useState<main.Note | null>(null);

  useEffect(() => {
    loadNotes();
  }, []);

  async function loadNotes() {
    const result = await GetNotes();       // Calls Go method, returns typed Note[]
    setNotes(result || []);
  }

  async function handleCreate() {
    const note = await CreateNote("Untitled");  // Go returns *Note, TS gets main.Note
    if (note) {
      setNotes([note, ...notes]);
      setSelectedNote(note);
    }
  }

  async function handleSave(id: number, title: string, content: string) {
    await UpdateNote(id, title, content);  // Calls Go, saves to SQLite
    loadNotes();
  }

  async function handleDelete(id: number) {
    await DeleteNote(id);
    setSelectedNote(null);
    loadNotes();
  }

  return (
    <div className="app">
      <aside className="sidebar">
        <button onClick={handleCreate}>+ New Note</button>
        <ul>
          {notes.map((note) => (
            <li
              key={note.id}
              className={selectedNote?.id === note.id ? "active" : ""}
              onClick={() => setSelectedNote(note)}
            >
              <strong>{note.title}</strong>
              <small>{note.updatedAt}</small>
            </li>
          ))}
        </ul>
      </aside>

      <main className="editor">
        {selectedNote ? (
          <NoteEditor
            note={selectedNote}
            onSave={handleSave}
            onDelete={handleDelete}
          />
        ) : (
          <p>Select or create a note</p>
        )}
      </main>
    </div>
  );
}
```

### System Tray and Menus

```go
// main.go — Native menus and system tray
package main

import (
	"embed"
	"github.com/wailsapp/wails/v2"
	"github.com/wailsapp/wails/v2/pkg/menu"
	"github.com/wailsapp/wails/v2/pkg/options"
	"github.com/wailsapp/wails/v2/pkg/options/assetserver"
)

//go:embed all:frontend/dist
var assets embed.FS

func main() {
	app := &App{}

	appMenu := menu.NewMenu()
	fileMenu := appMenu.AddSubmenu("File")
	fileMenu.AddText("New Note", keys.CmdOrCtrl("n"), func(_ *menu.CallbackData) {
		// Emit event to frontend
		runtime.EventsEmit(app.ctx, "menu:new-note")
	})
	fileMenu.AddSeparator()
	fileMenu.AddText("Quit", keys.CmdOrCtrl("q"), func(_ *menu.CallbackData) {
		runtime.Quit(app.ctx)
	})

	err := wails.Run(&options.App{
		Title:     "My Notes",
		Width:     1024,
		Height:    768,
		MinWidth:  600,
		MinHeight: 400,
		AssetServer: &assetserver.Options{
			Assets: assets,
		},
		OnStartup: app.startup,
		Menu:      appMenu,
		Bind:      []interface{}{app},
	})
	if err != nil {
		panic(err)
	}
}
```

## Installation

```bash
# Prerequisites: Go 1.21+, Node.js 16+
go install github.com/wailsapp/wails/v2/cmd/wails@latest

# macOS also needs Xcode command line tools
xcode-select --install

# Linux needs webkit2gtk
sudo apt install libgtk-3-dev libwebkit2gtk-4.0-dev
```


## Examples


### Example 1: Setting up Wails with a custom configuration

**User request:**

```
I just installed Wails. Help me configure it for my TypeScript + React workflow with my preferred keybindings.
```

The agent creates the configuration file with TypeScript-aware settings, configures relevant plugins/extensions for React development, sets up keyboard shortcuts matching the user's preferences, and verifies the setup works correctly.

### Example 2: Extending Wails with custom functionality

**User request:**

```
I want to add a custom go backend to Wails. How do I build one?
```

The agent scaffolds the extension/plugin project, implements the core functionality following Wails's API patterns, adds configuration options, and provides testing instructions to verify it works end-to-end.


## Guidelines

1. **Go for backend, web for UI** — Keep business logic, file I/O, database access in Go; keep UI rendering in the frontend
2. **Auto-generated bindings** — Never write API boilerplate; Wails generates TypeScript types from Go structs automatically
3. **Embed assets** — Use `//go:embed` to bundle the frontend into the binary; single-file distribution
4. **Events for async** — Use `runtime.EventsEmit` for Go→frontend communication (progress updates, background task results)
5. **Native dialogs** — Use Wails' runtime dialogs (file picker, message box) instead of HTML modals for native feel
6. **SQLite for local data** — Ship with SQLite for offline-first apps; it's a single file in the user's app data directory
7. **Dev mode for iteration** — `wails dev` provides hot reload for both Go and frontend; iterate fast
8. **Cross-compile** — Build for all platforms from one machine with `wails build -platform`; test on each OS before release

Related Skills

premium-frontend-ui

25
from ComeOnOliver/skillshub

A comprehensive guide for GitHub Copilot to craft immersive, high-performance web experiences with advanced motion, typography, and architectural craftsmanship.

power-apps-code-app-scaffold

25
from ComeOnOliver/skillshub

Scaffold a complete Power Apps Code App project with PAC CLI setup, SDK integration, and connector configuration

azure-static-web-apps

25
from ComeOnOliver/skillshub

Helps create, configure, and deploy Azure Static Web Apps using the SWA CLI. Use when deploying static sites to Azure, setting up SWA local development, configuring staticwebapp.config.json, adding Azure Functions APIs to SWA, or setting up GitHub Actions CI/CD for Static Web Apps.

windows-remote-desktop-connection-doctor

25
from ComeOnOliver/skillshub

Diagnose Windows App (Microsoft Remote Desktop / Azure Virtual Desktop / W365) connection quality issues on macOS. Analyze transport protocol selection (UDP Shortpath vs WebSocket), detect VPN/proxy interference with STUN/TURN negotiation, and parse Windows App logs for Shortpath failures. This skill should be used when VDI connections are slow, when transport shows WebSocket instead of UDP, when RDP Shortpath fails to establish, or when RTT is unexpectedly high.

developing-ios-apps

25
from ComeOnOliver/skillshub

Develops iOS/macOS applications with XcodeGen, SwiftUI, and SPM. Handles Apple Developer signing, notarization, and CI/CD pipelines. Triggers on XcodeGen project.yml, SPM dependency issues, device deployment, code signing errors (Error -25294, keychain mismatch, adhoc fallback, EMFILE, notarization credential conflict, continueOnError), camera/AVFoundation debugging, iOS version compatibility, "Library not loaded @rpath", Electron @electron/osx-sign/@electron/notarize config, notarytool, GitHub Actions secrets in conditionals, or certificate/provisioning problems. Use when building iOS/macOS apps, fixing Xcode build failures, deploying to real devices, or configuring CI/CD signing pipelines.

sleek-design-mobile-apps

25
from ComeOnOliver/skillshub

Use when the user wants to design a mobile app, create screens, build UI, or interact with their Sleek projects. Covers high-level requests ("design an app that does X") and specific ones ("list my projects", "create a new project", "screenshot that screen").

shopify-apps

25
from ComeOnOliver/skillshub

Expert patterns for Shopify app development including Remix/React Router apps, embedded apps with App Bridge, webhook handling, GraphQL Admin API, Polaris components, billing, and app extensions. Use when: shopify app, shopify, embedded app, polaris, app bridge.

multi-platform-apps-multi-platform

25
from ComeOnOliver/skillshub

Build and deploy the same feature consistently across web, mobile, and desktop platforms using API-first architecture and parallel implementation strategies.

frontend-ui-dark-ts

25
from ComeOnOliver/skillshub

Build dark-themed React applications using Tailwind CSS with custom theming, glassmorphism effects, and Framer Motion animations. Use when creating dashboards, admin panels, or data-rich interfaces with a refined dark aesthetic.

frontend-security-coder

25
from ComeOnOliver/skillshub

Expert in secure frontend coding practices specializing in XSS prevention, output sanitization, and client-side security patterns. Use PROACTIVELY for frontend security implementations or client-side security code reviews.

frontend-mobile-security-xss-scan

25
from ComeOnOliver/skillshub

You are a frontend security specialist focusing on Cross-Site Scripting (XSS) vulnerability detection and prevention. Analyze React, Vue, Angular, and vanilla JavaScript code to identify injection poi

frontend-mobile-development-component-scaffold

25
from ComeOnOliver/skillshub

You are a React component architecture expert specializing in scaffolding production-ready, accessible, and performant components. Generate complete component implementations with TypeScript, tests, s