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
Generate the project
wails3 init -n myapp
cd myapp
This creates a new project with the default Vanilla + Vite template (HTML/CSS/TypeScript with the 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.ts # Frontend TypeScript
│ ├── public/
│ │ └── style.css # Styles
│ ├── package.json # Frontend dependencies
│ ├── tsconfig.json # TypeScript configuration
│ └── vite.config.ts # Vite bundler config
├── build/ # Build configuration
└── Taskfile.yml # Build tasksRun the app
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.
How It Works
Let’s understand the code that makes this work.
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
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
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
Let’s add a new feature to understand the workflow.
Add a “Greet Many” Feature
Add the method to GreetService
Add this to 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 dev will automatically rebuild your Go code and restart the app.
Use it in the frontend
Add this to 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
When you’re ready to distribute your app:
wails3 build
What this does:
- Compiles Go code with optimizations
- Builds frontend for production (minified)
- Creates a native executable in
bin/
Output: bin/myapp.exe
Double-click to run. No dependencies needed (WebView2 is part of Windows).
Output: bin/myapp.app
Drag to Applications folder or double-click to run.
Output: bin/myapp
Run with ./bin/myapp or create a .desktop file for your launcher.
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.