Mobile Overview
Build iOS and Android apps from the same Go codebase as your desktop app
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:
| 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.