Shipping a Web Game with Capacitor

Updated June 2026
Capacitor wraps your HTML5 web game in a native iOS or Android shell, letting you submit to the App Store and Google Play while keeping your entire game in JavaScript. This guide walks through the full process from initial project setup through release-ready builds, covering the game-specific adjustments that most generic Capacitor tutorials skip.

Capacitor is the successor to Apache Cordova, built by the Ionic team with a modern architecture that uses the system WebView on each platform. For game developers, the most important thing to understand is that Capacitor does not modify your game code. It creates a native app that loads your game's HTML file in a full-screen WebView, and it provides JavaScript APIs for accessing native device features through plugins. Your game runs exactly as it does in a browser, with the addition of native capabilities.

Set Up the Capacitor Project

Start with a working web game that builds to a single output directory containing an index.html file and all necessary assets. Capacitor needs to know where this directory is so it can copy the files into the native projects.

Install the Capacitor CLI and core package in your game's project directory. If your game uses a bundler like Webpack, Vite, or Rollup, Capacitor integrates naturally into the build pipeline. If your game is a standalone HTML file with script tags, you can still use Capacitor by pointing it at the directory containing your game files.

Run npx cap init to create the Capacitor configuration file. You will be asked for your app's name (the display name on the device home screen), the app ID (a reverse-domain identifier like com.yourstudio.yourgame), and the web directory path. The app ID must be unique across all apps on the platform, and you cannot change it after submitting to the stores, so choose it carefully.

The resulting capacitor.config.ts file controls how Capacitor loads your game. For games specifically, you should configure the server settings to disable the URL bar, enable full-screen mode, and set the background color to match your game's loading screen. The backgroundColor setting prevents a white flash during startup, which is particularly noticeable on games with dark themes.

Prepare Your Game Build

Mobile devices introduce constraints that your browser-tested game may not handle yet. Before adding native platforms, address these issues in your web code.

Viewport sizing is the most critical adjustment. Mobile screens have different aspect ratios, pixel densities, and safe area insets (the notch on iPhones, the camera cutout on Android devices). Your game canvas should resize dynamically based on the available viewport dimensions. Use window.innerWidth and window.innerHeight for the drawable area, and account for env(safe-area-inset-top) and similar CSS environment variables to avoid rendering under system UI elements.

Touch input replaces mouse input on mobile. If your game uses mouse events, add equivalent touch event handlers or use pointer events which unify both. Multi-touch matters for games with virtual joysticks, two-finger gestures, or simultaneous button presses. Test that your game correctly handles touchstart, touchmove, touchend, and touchcancel events, and prevent default behavior on the document body to stop the browser's pull-to-refresh and elastic scrolling gestures from interfering with gameplay.

Audio on mobile requires user interaction before playing. Both iOS and Android WebViews block audio playback until the user taps the screen. Add a tap-to-start screen or detect the first user interaction and resume your audio context at that point. The Web Audio API's AudioContext.resume() method handles this unlock, but you must call it in response to a genuine user gesture.

Build your game to the output directory configured in capacitor.config.ts. Every file your game needs at runtime, including HTML, JavaScript, CSS, images, audio, fonts, and data files, must be in this directory or a subdirectory of it.

Add Native Platforms

Run npx cap add ios and npx cap add android to generate the native project files. This creates an ios/ directory containing an Xcode project and an android/ directory containing a Gradle project. These are real, full native projects that you can open and modify in the platform's standard IDE.

After adding platforms, run npx cap sync to copy your web build into the native projects and install any Capacitor plugins. You need to run sync whenever you update your game's web build or add/remove plugins. During development, npx cap copy is faster if you only changed web files and did not add new plugins.

The generated native projects include Capacitor's runtime, which handles WebView initialization, plugin loading, and the JavaScript bridge. You generally do not need to modify these runtime files, but the projects are fully editable if you need to add custom native code, modify the app manifest, or integrate third-party native SDKs.

Configure Native Projects

Open the iOS project in Xcode with npx cap open ios. Set your app icons by providing images at all required sizes (Xcode's asset catalog shows exactly which sizes are needed). Design a launch storyboard or provide splash screen images. Lock the screen orientation to landscape or portrait if your game requires a fixed orientation, which most games do.

In the iOS project's Info.plist, configure the status bar behavior. Most games hide the status bar entirely to maximize screen space. Set UIStatusBarHidden to YES and UIViewControllerBasedStatusBarAppearance to NO. If your game supports both orientations, configure the supported orientations array accordingly.

For Android, open the project with npx cap open android. Set app icons in the res/mipmap directories at all required densities. Configure the splash screen theme, lock the orientation in AndroidManifest.xml if needed, and set the app to use full-screen immersive mode to hide the system navigation bar during gameplay. The android:screenOrientation attribute in the activity tag controls orientation locking.

Both platforms need a bundle version number that increments with each store submission. Set this in Xcode's project settings for iOS and in the app-level build.gradle for Android. Use semantic versioning like 1.0.0 for the display version and an incrementing integer for the build number.

Add Game-Relevant Plugins

Capacitor's plugin ecosystem provides the bridge between your JavaScript game code and native device features. Install only the plugins your game actually needs to keep the build lean and avoid unnecessary permission prompts.

The @capacitor/haptics plugin adds vibration feedback that dramatically improves game feel on mobile. Call Haptics.impact() for collision effects, Haptics.vibrate() for general feedback, and Haptics.notification() for success or failure events. The haptic engine on modern iPhones produces surprisingly precise and satisfying feedback that players notice immediately.

The @capacitor/preferences plugin provides persistent key-value storage that survives app updates and reinstalls on most devices. Use it for save data, player settings, and progression state. For larger save files, the @capacitor/filesystem plugin gives you full access to the app's sandboxed file system.

The @capacitor/screen-orientation plugin lets you lock and unlock orientation programmatically. Lock to landscape during gameplay and unlock for menus if your game supports both. The @capacitor/status-bar plugin controls status bar visibility and style from JavaScript rather than requiring native configuration changes.

For monetization, community plugins like capacitor-admob handle ad integration, and capacitor-purchases (RevenueCat) or the community IAP plugin manage in-app purchases across both platforms with a unified JavaScript API. These plugins handle the complex platform differences in payment processing, receipt validation, and subscription management.

Test on Devices

Emulators and simulators are useful for layout testing but do not represent real game performance. Always test on physical devices, especially for WebGL games where GPU capabilities vary dramatically between devices.

Use npx cap run ios and npx cap run android to deploy to connected devices. During development, enable live reload by configuring the Capacitor server to point to your development server's URL. This way, changes to your game code appear on the device immediately without rebuilding the native project.

Test these game-specific scenarios on each platform: startup performance and splash screen transitions, touch responsiveness and input latency, audio playback including background audio behavior when the app loses focus, frame rate stability during intense gameplay moments, memory usage during extended play sessions, and behavior when the app goes to background and returns to foreground. Pay particular attention to how your game handles interruptions like phone calls, notifications, and system alerts.

On Android, test on at least one budget device from the last two to three years. These devices have weaker GPUs and less RAM, and they represent a significant portion of the global Android install base. If your game runs smoothly on a mid-range phone, it will run on most devices your players actually use.

Build for Release

For iOS, open the Xcode project, select a distribution provisioning profile, and create an archive through Product > Archive. Xcode validates the archive against App Store requirements and then lets you upload directly to App Store Connect. You need an Apple Developer account ($99/year) and must configure code signing with a distribution certificate.

For Android, open the Android Studio project and build a signed App Bundle (AAB format, required by Google Play) through Build > Generate Signed Bundle. You need a keystore file for signing, and you should keep this keystore safe because losing it means you cannot update your app. Google Play Developer accounts cost a one-time $25 fee.

Before submitting, run your game through each platform's pre-submission checklist. For iOS, ensure your app meets the Human Interface Guidelines, provides a privacy policy URL, and declares which data your app collects. For Google Play, complete the content rating questionnaire, provide a privacy policy, and fill out the data safety section describing what data your app accesses.

After your first submission, subsequent updates follow the same build and upload process. Increment the version number and build number each time. Store review typically takes one to three days for iOS and a few hours to one day for Google Play, though these times vary.

Key Takeaway

Capacitor wraps your web game without modifying it. The majority of the work is in preparing your game for mobile constraints (touch input, viewport sizing, audio unlock) rather than in Capacitor-specific configuration. Once those mobile adaptations are in place, Capacitor's project generation, plugin system, and build pipeline handle the native packaging cleanly.