How to Wrap an Angular App with Capacitor and Firebase¶
If you already have an Angular web app, you can wrap it into a native iOS and Android app without rewriting your entire codebase. In this guide, we use a real demo app called Trip Expenses to walk through the full process with Capacitor, Ionic, Firebase, and a handful of native plugins.
Get the code
The complete source code is available on GitHub, free to clone and adapt for your own project.
The demo covers the parts most production apps need: trip and expense management, receipt attachments as images or PDFs, image compression before upload, profile pictures via the device camera, and custom icons and splash screens for both platforms. The stack is Angular 21 with Ionic 8 for the UI, Capacitor 8 for the native runtime, and Firebase (Cloud Firestore and Cloud Storage) for data and files.
On the Capacitor side, we rely on the Camera and Splash Screen plugins from the Capacitor team, together with the File Picker, File Compressor, Firebase Cloud Firestore, and Firebase Cloud Storage plugins from Capawesome.
Note
The example uses Angular, but the same concepts apply to any web project — Capacitor is framework-agnostic.
Important Definitions for Your First Capacitor App¶
Before jumping into the code, let's clarify a few concepts and answer some common questions, especially if this is your first time working with Capacitor.
What Is Capacitor?¶
Capacitor is an open-source runtime developed by the Ionic team that lets you run your web app as a native iOS and Android app. It wraps your built web assets in a native shell, so your Angular code still powers the UI and business logic. You keep a single codebase for most features, access native device APIs through plugins as you need them, and ship updates through the standard app store workflow — adding native capabilities progressively over time.
Angular Web vs Mobile Runtime: Key Differences¶
Before you start, it helps to know what changes when your Angular app runs inside Capacitor. The app runs inside a native WebView rather than a browser tab, which means iOS and Android permission models now apply (Info.plist and AndroidManifest.xml). File handling looks different too: native paths like file:// and content:// enter the picture, and memory constraints matter more than they do on the web. And instead of a web deploy, releases involve native binaries and the regular app store workflow.
Your Angular code still drives most of the product, but the quality of the native integration directly affects reliability, UX, and performance.
What Is a Capacitor Plugin?¶
A Capacitor plugin is the bridge between your TypeScript code and native iOS and Android APIs. It typically ships a TypeScript API along with native iOS and Android implementations, plus an optional web implementation so the same code path works in the browser. In this project, that means using native integrations where they matter most — camera, file picking, Firebase on device — while keeping a single Angular codebase.
Is Ionic Required?¶
No, Ionic is optional. It's a mobile UI toolkit that gives you production-ready components and app-like UX patterns out of the box, but if your team already has a design system, you can use Capacitor with plain Angular.
Add Capacitor to Your Angular Project¶
Install the Capacitor core and CLI packages, then initialize the project:
The CLI will prompt you for your app name (e.g. Trip Expenses), app ID (e.g. io.tripexpenses.app), and web output directory (www or your Angular dist/ directory) — use your own values here.
Next, add the iOS and Android platforms:
That's it. Your Angular web app is now wrapped in a native shell and ready to run on both platforms.
Build, Sync, and Run¶
The Capacitor development workflow takes a couple of tries to get used to, but the loop is short. Whenever you change web code, rebuild and sync the changes into the native projects:
To open the native projects in Xcode or Android Studio:
Or run directly on a simulator or device:
Generate App Icons and Splash Screens¶
You can generate icons and splash screens for both platforms with the @capacitor/assets tool. Install it as a dev dependency, drop your own icon-only.png and splash.png into the resources/ folder, and let the CLI do the rest:
npm install -D @capacitor/assets@latest
npx capacitor-assets generate --ios
npx capacitor-assets generate --android
This produces all the required platform assets. The tool has more configuration options if you need finer control — check its README.
Set Up Your Own Firebase Project¶
If you clone the demo app, you'll need to create your own Firebase project before running it.
1) Create Firebase Resources¶
In the Firebase Console, create a new project and enable both Cloud Firestore and Cloud Storage.
2) Register App Clients¶
Under the same Firebase project, register a Web app for the Angular runtime, an Android app with package name io.tripexpenses.app, and an iOS app with bundle ID io.tripexpenses.app. Replace those identifiers with your own.
3) Configure Web Firebase Values¶
Add your Web SDK config to src/environments/environment.ts and src/environments/environment.prod.ts.
4) Configure Native Firebase Files¶
When you registered the Android and iOS apps in step 2, you had the option to download the native config files. Place google-services.json at android/app/google-services.json and GoogleService-Info.plist at ios/App/App/GoogleService-Info.plist, then run:
Integrate Firebase with Capacitor¶
With your Firebase project ready, the next step is wiring it into the app. We use native Firebase plugins rather than the web SDKs, which gives us better reliability inside the WebView, native file upload paths, and noticeably better performance with large files.
To install them, see the Installation section of the Firebase Cloud Firestore plugin and the Installation section of the Firebase Cloud Storage plugin.
Adding Native Features¶
The demo app includes a couple of native feature touchpoints to make the migration realistic.
Profile Picture Upload¶
On the profile screen, users can update their profile picture by taking a photo or picking one from the gallery. The Angular UI stays exactly the same — the Camera plugin from the Capacitor team takes care of calling the native camera on iOS and Android, and ships a web fallback so the same code path works in the browser too.
Expense Attachment Flow¶
When creating an expense, users can attach a receipt image or PDF. Three plugins work together for this flow: the File Picker plugin handles native file selection, the File Compressor plugin shrinks images before upload, and the Firebase Cloud Storage plugin uploads the result on device. All of the related code lives in src/app/core/services/storage.service.ts.
For a deeper look at file handling on Capacitor — including memory pitfalls and best practices — see The File Handling Guide for Capacitor.
That covers everything needed to bring your Angular app to mobile. The rest is just Angular and Ionic UI to build out your product.
Production Delivery with Capawesome Cloud¶
Once the app runs reliably on real devices, the next step is automating delivery. Capawesome Cloud handles the parts that would otherwise eat your time: Native Builds produces reproducible iOS and Android binaries in a consistent environment, Live Updates ships fixes and improvements to the web layer without going through app store review every time, and App Store Publishing delivers builds straight to TestFlight or Google Play.
A pattern that works well in practice is combining the two release tracks — ship stable native builds through the stores, and use Live Updates for fast iteration on the web layer in between. Wire it all into your repo with the GitHub integration and your pipeline triggers builds and deployments automatically on commit, branch, or tag.
See the Capawesome Cloud documentation for setup details, or browse the video walkthroughs for each step.
Try Capawesome Cloud¶
Stop fighting with manual builds and slow release cycles. Capawesome Cloud handles native builds, live updates, and app store publishing for your Capacitor apps in one place.
Conclusion¶
Wrapping an Angular app for iOS and Android with Capacitor isn't a rewrite — it's an extension of what you already have. Your Angular code keeps powering the UI and business logic; you just add native capabilities where they matter and ship through the regular app store workflow.
This means your team can move faster, reduce duplication, and ship features consistently across web, iOS, and Android without the overhead of maintaining separate apps.
Once you have this setup in place, you can start extending your app with more advanced features, such as adding push notifications to keep users engaged, implementing in-app purchases to monetize your app, or building secure authentication flows using OAuth and biometrics.
For a deeper look at how to roll out updates safely once you're in production, see The App Update Delivery Guide for Capacitor. If you have questions, join the Capawesome Discord server and connect with the community. To stay up to date on the latest news, subscribe to the Capawesome newsletter.