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
Create Your Project
Section titled “Create Your Project”-
Generate the project
Terminal window wails3 init -n myappcd myappThis creates a new project with the default Vanilla + Vite template (plain HTML/CSS/JS with Vite bundler).
-
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 -
Run the app
Terminal window wails3 devThe app opens showing a greeting interface. Enter your name and click “Greet” - the Go backend processes your input and returns a greeting.
How It Works
Section titled “How It Works”Let’s understand the code that makes this work.
The Go Backend
Section titled “The Go Backend”Open 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:
- Service - A Go struct with exported methods
- Exported method -
Greetis capitalized, making it available to the frontend - Simple logic - Takes a name, returns a greeting
- Type safety - Input and output types are defined
Registering the Service
Section titled “Registering the Service”Open main.go and find the service registration:
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.
The Frontend
Section titled “The Frontend”Open 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:
- Auto-generated bindings -
GreetServiceis imported from generated code - Type-safe calls - Method names and signatures match your Go code
- Async by default - All Go calls return Promises
- Error handling - Errors from Go are caught in try/catch
Customize Your App
Section titled “Customize Your App”Let’s add a new feature to understand the workflow.
Add a “Greet Many” Feature
Section titled “Add a “Greet Many” Feature”-
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} -
The app will auto-rebuild
Save the file and
wails3 devwill automatically rebuild your Go code and restart the app. -
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.
Build for Production
Section titled “Build for Production”When you’re ready to distribute your app:
wails3 buildWhat 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).
Output: build/bin/myapp.app
Drag to Applications folder or double-click to run.
Output: build/bin/myapp
Run with ./build/bin/myapp or create a .desktop file for your launcher.
What we’ve learned
Section titled “What we’ve learned”Project Structure
main.gofor Go backendfrontend/for UI codeTaskfile.ymlfor 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 devfor hot reload- Go changes auto-rebuild and restart
- Frontend changes hot-reload instantly
Questions? Join Discord and ask the community.