Mobile Overview
Wails v3 runs on iOS and Android using the same main.go and frontend you already write for desktop. There is no separate mobile project, no code-sharing bridge, and no rewrite: the Go binary is compiled for the mobile target and a native WebView renders your existing frontend.
WKWebView + UIKit host. Assets served via a custom wails:// scheme — no open ports.
Requires macOS with full Xcode.
Android WebView + WebViewAssetLoader. Go compiled as libwails.so via the NDK.
Works on macOS, Linux, and Windows.
See it running: Kitchen Sink example
The best way to understand what’s possible is to look at the Kitchen Sink — a single Wails app that runs identically on iOS, Android and desktop from one codebase:
It demonstrates every major mobile API surface across 7 tabs — and it runs on desktop too. The Mobile and Hardware tabs are hidden on desktop via a platform check in the frontend; the Go side registers no handlers for common:* mobile events when built for desktop. This is the recommended pattern for shipping one codebase everywhere.
| Tab | Platforms | What it shows |
|---|---|---|
| Bindings | all | JS → Go service calls returning values, structs, and errors |
| Events | all | Go → JS clock, JS → Go → JS ping/pong, OS system events (battery, network, theme) |
| Dialogs | all | Native message dialogs on each platform |
| System | all | Clipboard, screen metrics, device info |
| Mobile | iOS + Android | Share sheet, keep-awake, torch, brightness, biometrics, local notifications, secure storage |
| Hardware | iOS + Android | Haptics, geolocation, accelerometer, proximity, text-to-speech |
| Native | iOS + Android | iOS: haptics + WKWebView toggles · Android: vibrate + toast |
To run it yourself:
git clone https://github.com/wailsapp/wails.git
cd wails/v3/examples/mobile
wails3 task ios:run # iOS Simulator (macOS + Xcode required)
wails3 task android:run # Android Emulator
wails3 task run # Desktop
How it works
The same application model applies on every platform:
- Go backend — your services, event handlers and application logic compile unchanged for
GOOS=iosandGOOS=android. - Frontend — the exact same HTML/JS/CSS. The
@wailsio/runtimepackage works identically; service bindings, events, dialogs and the clipboard all route through the same in-process transport. - WebView host — on iOS a
WKWebViewinside aUIViewController; on Android aWebViewinside anActivity. Wails wires up the message bridge automatically. - In-process asset serving — assets are served directly from Go memory, not a localhost server. No open ports, no loopback, no extra latency.
Platform-specific behaviour lives in files guarded by //go:build ios or //go:build android, keeping your shared code clean.
Prerequisites at a glance
| Requirement | iOS | Android |
|---|---|---|
| Operating system | macOS only | macOS, Linux, Windows |
| Toolchain | Full Xcode (not just CLI tools) | Android SDK + NDK 26.3.x + JDK |
| Go | 1.25+ | 1.25+ |
| npm | ✅ | ✅ |
| Verify with | wails3 doctor |
wails3 doctor |
What’s supported
Both platforms share the same core feature set:
| Feature | iOS | Android |
|---|---|---|
| Service bindings (JS → Go) | ✅ | ✅ |
| Events (both directions) | ✅ | ✅ |
| Message dialogs | ✅ UIAlertController | ✅ AlertDialog |
| Open file dialogs | ✅ UIDocumentPicker | ✅ Storage Access Framework |
| Save file dialogs | ❌ write to sandbox instead | ❌ write to sandbox instead |
| Clipboard | ✅ UIPasteboard | ✅ ClipboardManager |
| Screens / safe-area metrics | ✅ | ✅ |
| Lifecycle events | ✅ events.IOS.* |
✅ events.Android.* |
| Haptics | ✅ IOS.Haptics.* |
✅ Android.Haptics.Vibrate |
| Device info | ✅ IOS.Device.Info() |
✅ Android.Device.Info() |
| Native tabs (iOS) | ✅ UITabBar | — |
| Toast messages (Android) | — | ✅ Android.Toast.Show |
| Multiple windows | ❌ first window only | ❌ first window only |
| Window geometry / menus / tray | intentional no-ops | intentional no-ops |
Build tag rules
Two important rules to know when writing platform-conditional code:
iosimpliesdarwin— a file tagged//go:build darwinwill also compile for iOS. To target macOS-only, use//go:build darwin && !ios.androidimplieslinux— a file tagged//go:build linuxwill also compile for Android. To target desktop-Linux-only, use//go:build linux && !android.
At runtime, runtime.GOOS returns "ios" and "android" respectively.
Runtime platform detection
Build tags are for code that can only compile on a given platform. For ordinary
branching in shared code, use application.System — it’s available in every build
(no build tags needed) so the same file works everywhere:
import "github.com/wailsapp/wails/v3/pkg/application"
if application.System.IsMobile() {
// iOS or Android
} else if application.System.IsDesktop() {
// macOS, Windows or Linux
}
// Or test a single target directly:
if application.System.IsPlatform(application.PlatformIOS) {
// iOS only
}Available: IsMobile(), IsDesktop(), IsServer() (the server build tag), and
IsPlatform(application.PlatformMacOS | PlatformWindows | PlatformLinux | PlatformIOS | PlatformAndroid | PlatformServer).
The frontend has the matching helpers in @wailsio/runtime:
import { System } from "@wailsio/runtime";
if (System.IsMobile()) { /* iOS or Android */ }
if (System.IsIOS()) { /* … */ } // also IsAndroid, IsMac, IsWindows, IsLinux, IsDesktopNext steps
Take a desktop Wails app and run it on iOS Simulator or Android Emulator in minutes.
Full iOS toolchain setup, simulator, device builds, signing, configuration and API reference.
Full Android SDK/NDK setup, emulator, APK signing, Play Store packaging and API reference.