Skip to content

Your First App

We will build a simple greeting application that demonstrates the core Wails concepts:

  • Go backend managing logic
  • Frontend calling Go functions
  • Type-safe bindings
  • Hot reload during development

Time to complete: 10 minutes

  1. Generate the project

    Terminal window
    wails3 init -n myapp
    cd myapp

    This creates a new project with the default Vanilla + Vite template (plain HTML/CSS/JS with Vite bundler).

  2. Understand the project structure

    myapp/
    ├── main.go # Application entry point
    ├── greetservice.go # Greet service
    ├── frontend/ # Your UI code
    │ ├── index.html # HTML entry point
    │ ├── src/
    │ │ └── main.js # Frontend JavaScript
    │ ├── public/
    │ │ └── style.css # Styles
    │ ├── package.json # Frontend dependencies
    │ └── vite.config.js # Vite bundler config
    ├── build/ # Build configuration
    └── Taskfile.yml # Build tasks
  3. Run the app

    Terminal window
    wails3 dev

    The app opens showing a greeting interface. Enter your name and click “Greet” - the Go backend processes your input and returns a greeting.

Let’s understand the code that makes this work.

Open greetservice.go:

greetservice.go
package main
import (
"fmt"
)
type GreetService struct{}
func (g *GreetService) Greet(name string) string {
return fmt.Sprintf("Hello %s, It's show time!", name)
}

Key concepts:

  1. Service - A Go struct with exported methods
  2. Exported method - Greet is capitalized, making it available to the frontend
  3. Simple logic - Takes a name, returns a greeting
  4. Type safety - Input and output types are defined

Open main.go and find the service registration:

main.go
err := application.New(application.Options{
Name: "myapp",
Services: []application.Service{
application.NewService(&GreetService{}),
},
// ... other options
})

This registers your GreetService with Wails, making all its exported methods available to the frontend.

Open frontend/src/main.js:

frontend/src/main.js
import {GreetService} from "../bindings/changeme";
window.greet = async () => {
const nameElement = document.getElementById('name');
const resultElement = document.getElementById('result');
const name = nameElement.value;
if (!name) {
return;
}
try {
const result = await GreetService.Greet(name);
resultElement.innerText = result;
} catch (err) {
console.error(err);
}
};

Key concepts:

  1. Auto-generated bindings - GreetService is imported from generated code
  2. Type-safe calls - Method names and signatures match your Go code
  3. Async by default - All Go calls return Promises
  4. Error handling - Errors from Go are caught in try/catch

Let’s add a new feature to understand the workflow.

  1. Add the method to GreetService

    Add this to greetservice.go:

    greetservice.go
    func (g *GreetService) GreetMany(names []string) []string {
    greetings := make([]string, len(names))
    for i, name := range names {
    greetings[i] = fmt.Sprintf("Hello %s!", name)
    }
    return greetings
    }
  2. The app will auto-rebuild

    Save the file and wails3 dev will automatically rebuild your Go code and restart the app.

  3. Use it in the frontend

    Add this to frontend/src/main.js:

    frontend/src/main.js
    window.greetMany = async () => {
    const names = ['Alice', 'Bob', 'Charlie'];
    const greetings = await GreetService.GreetMany(names);
    console.log(greetings);
    };

    Open the browser console and call greetMany() - you’ll see the array of greetings.

When you’re ready to distribute your app:

Terminal window
wails3 build

What this does:

  • Compiles Go code with optimizations
  • Builds frontend for production (minified)
  • Creates a native executable in build/bin/

Output: build/bin/myapp.exe

Double-click to run. No dependencies needed (WebView2 is part of Windows).

Project Structure

  • main.go for Go backend
  • frontend/ for UI code
  • Taskfile.yml for build tasks

Services

  • Create Go structs with exported methods
  • Register with application.NewService()
  • Methods automatically available in frontend

Bindings

  • Auto-generated TypeScript definitions
  • Type-safe function calls
  • Async by default (Promises)

Development Workflow

  • wails3 dev for hot reload
  • Go changes auto-rebuild and restart
  • Frontend changes hot-reload instantly

Questions? Join Discord and ask the community.