How to Publish a Capacitor App on the App Store
Capacitor is the modern successor to Cordova, providing a clean bridge between web apps and native mobile platforms. Whether you're wrapping a React, Vue, Angular, or plain HTML app, Capacitor generates a fully functional Xcode project. This guide covers the Capacitor-specific workflow for getting your web app into the App Store, including how to avoid common hybrid-app rejections.
Prerequisites
- A Mac with Xcode 15+ installed
- An Apple Developer Program membership ($99/year)
- Node.js 18+ installed
- Capacitor 5+ installed in your web project (@capacitor/core, @capacitor/ios)
- Your web app framework's production build working (React, Vue, Angular, etc.)
Step-by-Step Build Process
Build your web app for production
Run your framework's build command (e.g., `npm run build`, `vite build`, `ng build`). Ensure the output directory matches the `webDir` setting in capacitor.config.ts. Verify the build output is optimized and minified.
Sync web assets to iOS
Run `npx cap sync ios`. This copies the built web assets into the iOS native project and runs `pod install` for any native plugin dependencies. Always sync after changing web code or plugin dependencies.
Open and configure in Xcode
Run `npx cap open ios`. Set the development team, bundle identifier, version, and build number. Configure capabilities (Push Notifications, Background Modes, etc.) if your plugins require them.
Configure native splash screen and icons
Replace the default Capacitor splash screen and app icons. Use Xcode's Asset Catalog for app icons (AppIcon set). Configure the splash screen via LaunchScreen.storyboard or Capacitor's splash screen plugin.
Archive and upload
Select 'Any iOS Device', create an archive via Product > Archive. Validate, then distribute to App Store Connect via the Organizer.
Code Signing & Certificates
Automatic signing setup
In the App target, enable automatic signing and select your development team. Capacitor projects use a standard Xcode project structure, so signing works identically to native apps.
Entitlements configuration
If using Push Notifications, add the entitlement via Signing & Capabilities. Capacitor plugins that need specific capabilities (e.g., @capacitor/push-notifications) require corresponding entitlements and App ID configuration.
Store Submission Steps
Create app listing in App Store Connect
Create a new app with matching bundle ID. Capacitor apps are indistinguishable from native apps to Apple. Choose the most appropriate category for your web app's functionality.
Test with TestFlight
Distribute to TestFlight for real-device testing. Hybrid apps sometimes have issues with WKWebView on specific iOS versions. Test navigation, deep links, and native plugin functionality.
Prepare metadata and submit
Upload screenshots, fill in descriptions, set pricing. Ensure screenshots show the app running natively, not in a browser. Submit for App Review with any demo credentials.
Common Rejection Reasons & Fixes
Guideline 4.2 - Minimum Functionality
This is the most common rejection for Capacitor apps. Apple may flag your app as a 'web wrapper'. Use native Capacitor plugins (Camera, Haptics, Push Notifications) to demonstrate native functionality that goes beyond what Safari can offer.
WKWebView content loading issues
If your app loads external URLs, Apple may reject it as a 'web clip'. Ensure your app bundles its web content locally and only makes API calls, not full-page external loads. Set `allowNavigation` carefully in capacitor.config.ts.
Missing privacy declarations
Capacitor plugins that access device features need corresponding Info.plist entries. Ensure NSCameraUsageDescription, NSPhotoLibraryUsageDescription, etc., are set for any plugins you use.
Links to external browsers
If your app opens Safari for login, payment, or content, Apple may reject it. Use Capacitor's Browser plugin with in-app browser (SFSafariViewController) instead of opening external Safari.
Pro Tips
- Use Capacitor's native HTTP plugin (@capacitor/core HTTP API) instead of fetch/axios to bypass CORS issues and improve performance
- Implement deep links with Capacitor's App Links plugin for better user experience and Apple Universal Links support
- Add Capacitor's Status Bar plugin to control the status bar appearance for a more native look
- Use the @capacitor/keyboard plugin to handle keyboard show/hide events and prevent layout issues
- Consider using Capacitor's Local Notifications plugin for functionality that doesn't require server-side push
Skip the hassle. Let us handle it.
Publishing a Capacitor app on the App Store (iOS) involves dozens of steps, certificates, and potential rejection pitfalls. Our team handles the entire process for you — from build configuration to store approval.