A minimal example demonstrating how to build desktop applications with Wails v2 and Svelte 5, featuring a Pokemon API integration.
Wails is a framework for building desktop applications using Go for the backend and web technologies (HTML, CSS, JavaScript) for the frontend. Think of it as Electron, but with Go instead of Node.js - resulting in smaller binaries and better performance.
├── main.go # Wails app entry point
├── wails.json # Wails configuration
├── go.mod # Go module dependencies
├── internal/ # Private application code
│ ├── app/
│ │ └── app.go # Core app structure and Wails bindings
│ ├── models/
│ │ └── pokemon.go # Data models and types
│ └── services/
│ └── pokemon.go # Business logic and API calls
└── frontend/ # Svelte frontend
├── src/
│ ├── routes/
│ │ └── +page.svelte # Main Pokemon component
│ └── lib/
│ └── wailsjs/ # Auto-generated Go bindings
└── svelte.config.js # Svelte configuration
The backend follows a clean architecture pattern with clear separation of concerns:
internal/app/
): Wails bindings and application entry pointsinternal/services/
): Business logic and external API integrationinternal/models/
): Data structures and types// This Go method becomes available in the frontend
func (a *App) GetRandomPokemon() (*Pokemon, error) {
// Fetch from external API
// Return structured data
}
import { GetRandomPokemon } from '$lib/wailsjs/go/main/App';
// Call Go method directly
const pokemon = await GetRandomPokemon();
Wails automatically:
go install github.com/wailsapp/wails/v2/cmd/wails@latest
# Clone the repository
git clone <your-repo-url>
cd wails-svelte-pokemon
# Install Go dependencies
go mod tidy
# Install frontend dependencies
cd frontend
npm install
cd ..
# Run in development mode with hot reload
wails dev
This starts:
# Build desktop application
wails build
Creates a native executable in the build/bin/
directory.
Any public method on your App struct becomes available in the frontend:
// app.go
func (a *App) MyMethod(param string) (string, error) {
return "Hello " + param, nil
}
// frontend
import { MyMethod } from '$lib/wailsjs/go/main/App';
const result = await MyMethod("World");
func (a *App) startup(ctx context.Context) {
a.ctx = ctx
// App initialization logic
}
The startup method runs when the app launches, giving you access to the Wails runtime context.
wails.json
controls build settings:
{
"name": "MyApp",
"outputfilename": "MyApp",
"frontend:install": "npm install",
"frontend:build": "npm run build",
"frontend:dev:watcher": "npm run dev"
}
$state()
for reactive variablesonclick
instead of on:click
{#await}
blocks for loading statesThis example shows a clean pattern for integrating external APIs:
api.go
)pokemon.go
)func (a *App) MyMethod() (*Data, error) {
data, err := externalAPI.Fetch()
if err != nil {
return nil, fmt.Errorf("failed to fetch: %v", err)
}
return data, nil
}
{#await myAsyncFunction()}
<div>Loading...</div>
{:then result}
<div>Success: {result}</div>
{:catch error}
<div>Error: {error}</div>
{/await}
// Wait for image to load
await new Promise((resolve, reject) => {
const img = new Image();
img.onload = resolve;
img.onerror = reject;
img.src = imageUrl;
});
wails dev
- Hot reload developmentwails doctor
- Check system requirementswails build -debug
- Debug build with DevToolswails build
- Optimized production buildwails build -platform windows/amd64
- Cross-platform buildswails build -upx
- Compress with UPXThis example demonstrates the core concepts of Wails development. The combination of Go's performance and Svelte's reactivity creates powerful desktop applications with minimal complexity.