Progressive Web to Native Mobile with Capacitor

Stefan WeberStefan Weber
8 min read

Apple and the EU Digital Markets Act

With iOS Update 17.4, Apple addresses the requirements of the European Union Digital Markets Act (DMA). In short, this EU regulation forces companies like Apple to open their platforms to third-party providers in order to foster competition. Personally, I believe this is a well-intentioned move by the EU. Unfortunately, every regulation has some downsides. As a side effect of allowing third-party browser engines in iOS, this update will drop support for Home Screen Web Apps. You can read the full announcement by Apple here: Update on apps distributed in the European Union - Support - Apple Developer.

iPhone users in the European Union will still be able to open web pages from the Home screen via bookmarks using their preferred browser engine. However, they will no longer be able to run Progressive Web Applications in a dedicated application window, which also restricts the available features of these applications, like long-term storage or notifications.

In summary, Progressive Web Applications on iOS are no longer viable. In my opinion, they never truly thrived on iOS ๐Ÿ˜‚ To me, PWAs have always been a Chrome feature, where they perform quite well.

๐Ÿ’ก
Update - End of February Apple announced that they will not drop Progressive Web Application support in iOS 17.4. Read the full announcement here: Update on apps distributed in the European Union - Support - Apple Developer

However, this article is not about lamenting the changes Apple introduced to comply with the Digital Markets Act, nor is it about discussing the pros and cons of Progressive Web Applications and native applications distributed through the Apple App Store. It also does not discuss whether Apple will reverse the change or if the European Union should or will amend the DMA.

Instead, let's focus on how we can address the issue of Progressive Web Applications ceasing to function on iOS. Assuming that Apple will release the update in early March, time is of the essence. One might argue that organizations can delay the update, and they might do so, but since updates also include security fixes, any postponement won't last very long.

If you've read some of my articles, you know that I primarily work with the OutSystems Low-Code Application Platform. You might think that I'm going to recommend migrating Progressive Web Applications to OutSystems. And yes, I would love to do so. In OutSystems, choosing between a Progressive Web App and a Cordova-based native mobile app is more or less a matter of a few clicks and configurations.

However, if you have a large number of developed applications and, more importantly, skilled developers with an established development process, this option may not be feasible for you. Undoubtedly, adding a new platform to your environment, training developers, and then migrating your existing applications requires significant effort. Nonetheless, it's something you may consider for the future ๐Ÿ˜

An alternative option that allows you to maintain your current software development process and most parts of your existing development stack could be Capacitor by Ionic. And guess what? Ionic got acquired by OutSystems in 2022 ๐Ÿ˜Š

Capacitor is an open-source native runtime for building cross-platform iOS, Android, and Progressive Web Applications. It's an excellent choice for converting existing Progressive Web Applications into native mobile applications.

๐Ÿ’ก
By native, we mean that the web application runs in a native container on iOS or Android and can interact with native capabilities using JavaScript.

The best part is that with Capacitor, you gain multi-target capability. This means you can use your application as both a Progressive Web Application and a native application, all with a single codebase.

From PWA to Native Mobile by Example

Let's go through a simple example. You'll see that it can take just a matter of minutes to transform your PWA into a native mobile app. However, the time required ultimately depends on the complexity of your specific PWA.

Prerequisites

In this article, I am using a Windows 11 system, so what I am showing here are the steps to create a Capacitor native mobile application for Android devices. The individual actions are similar for iOS; you just need a different environment (Xcode instead of Android Studio).

Follow the Environment Setup instructions in the Capacitor Documentation.

Walkthrough

I created a very simple Progressive Web Application using Vite (React) and Vite PWA. You can find the initial code (pre-Capacitor) at stefan-d-p/cap-sample-pwa (github.com).

The sample PWA allows to store contact information - name and address - in an IndexedDB database.

Clone Sample Progressive Web Application

Clone the GitHub repository if you want to follow the individual steps.

The repository has two branches

  • main contains the initial Progressive Web Application

  • capacitor contains the final application with Capacitor

After cloning the repository locally, run npm install in the project root directory of the main to install the dependencies. Next run npm run dev to start a development server. During the first start, you will be asked to import a self-signed certificate that enabled https support. Explore the application using the provided URL. Notice the "Install App" icon in the browser bar, which allows you to install the PWA on your system.

Finally, run npm run build in the project directory. This generates the distribution files of the PWA in the dist folder.

The contents of the dist folder are the artifacts you should publish via a web server to make the app accessible to your users.

In the next step we add Capacitor to our project.

Install Capacitor

In the project root directory run the following commands to install Capacitor base components.

npm install @capacitor/core
npm install -D @capacitor/cli

Initialize Capacitor Configuration

Execute the following command and answer the prompted questions.

npx cap init

[?] What is the name of your app?
    This should be a human-friendly app name, like what you'd see in the App Store.
โˆš Name ... cap-sample-pwa
[?] What should be the Package ID for your app?
    Package IDs (aka Bundle ID in iOS and Application ID in Android) are unique identifiers for apps. They must  
    be in reverse domain name notation, generally representing a domain name that you or your company owns.      
โˆš Package ID ... one.spatium.contactspwa
โˆš Creating capacitor.config.json in C:\dev\cap-sample-paw in 3.33ms
[success] capacitor.config.json created!

Next steps:
https://capacitorjs.com/docs/getting-started#where-to-go-next
[?] Join the Ionic Community! ๐Ÿ’™
    Connect with millions of developers on the Ionic Forum and get access to live events, news updates, and more.โˆš Create free Ionic account? ... no
[?] Would you like to help improve Capacitor by sharing anonymous usage data? ๐Ÿ’–
    Read more about what is being collected and why here: https://capacitorjs.com/telemetry. You can change your 
    mind at any time by using the npx cap telemetry command.
โˆš Share anonymous usage data? ... no

Generate Native Android Application

Run the following statements in the project root folder

npm install @capacitor/android
npx cap add android

Finally execute npx cap open android to open the project in Android Studio.

๐Ÿ’ก
When opening, it takes some time for Android Studio to download additional dependencies.

In Android Studio, run the application either in the emulator or on a connected device. During the application's startup, you will notice a splash screen displaying the Capacitor logo. Refer to the Capacitor documentation for instructions on adding your own splash screen and making other configurations.

At this point we were able to turn our Progressive Web Application into a native mobile application. Or into a web application running in a native container, because that's it what Capacitor is doing.

Important to note is that we haven't changed the original code base so far. You can still build a regular PWA using the npm build.

If you want or need to go further, you can add native capabilities or replace some of your current PWA features with their native counterparts.

Capacitor offers a wide range of native cross-platform plugins, such as access to the camera or push notifications. The latter is particularly important if you have used push notifications in your PWA. In that case, you must use the Capacitor plugin.

Once you start adding and using Capacitor plugins you are no more able to use your "old" PWA build system. If you still need to create Progressive Web Applications e.g. because you intend to publish on the Microsoft App Store, then you need to switch to the PWA build system of Capacitor. Out of scope of this article, but you will find a step-by-step guide in the Progressive Web Applications Documentation.

Publishing

Capacitor based applications are Android / iOS applications. You can publish your application directly from Android Studio. See the documentation on how to do that here Publish your app | Android Studio | Android Developers.

If you're seeking a more advanced solution for building and deploying Capacitor applications, Ionic Appflow offers numerous automation options.

Summary

With Capacitor, it takes only a matter of minutes to wrap an existing Progressive Web Application in a native container and publish it to the official App Stores (or potentially upcoming 3rd party marketplaces). This is particularly true for simple PWAs. More complex ones may require additional modifications, but at least with Capacitor, you are not forced to change your entire development stack.

Thank you for reading. I hope you enjoyed it and that I've explained the important parts clearly. If not, please let me know ๐Ÿ˜Š Your feedback is greatly appreciated.

Follow me on LinkedIn to receive notifications whenever I publish something new.

2
Subscribe to my newsletter

Read articles from Stefan Weber directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Stefan Weber
Stefan Weber

As a seasoned Senior Director at Telelink Business Services EAD, a leading IT full-service provider headquartered in Sofia, Bulgaria, I lead the charge in our Application Services Practice. In this role, I spearhead the development of tailored software solutions using no-code/low-code platforms and cutting-edge cloud-ready/cloud-native solutions based on the Microsoft .NET stack. Throughout my diverse career, I've accumulated a wealth of experience in various capacities, both technically and personally. The constant desire to create innovative software solutions led me to the world of Low-Code and the OutSystems platform. I remain captivated by how closely OutSystems aligns with traditional software development, offering a seamless experience devoid of limitations. While my managerial responsibilities primarily revolve around leading and inspiring my teams, my passion for solution development with OutSystems remains unwavering. My personal focus extends to integrating our solutions with leading technologies such as Amazon Web Services, Microsoft 365, Azure, and more. In 2023, I earned recognition as an OutSystems Most Valuable Professional, one of only 80 worldwide, and concurrently became an AWS Community Builder.