Extend a web app into Android and iOS apps using Ionic Capacitor

//Extend a web app into Android and iOS apps using Ionic Capacitor

Extend a web app into Android and iOS apps using Ionic Capacitor

In this article, we’ll convert a web app into Android and iOS apps using Ionic Capacitor. We’ll build a dummy web app and then move that web app into a native mobile app, without any additional effort. We’ll define a workflow that renders certain features only on the native app or only on the web app. This will let us add device-centric features, enhancing the end user’s experience.

Table of Contents

  • The Native route
  • Ionic Capacitor
  • Understanding the Web app to Native app workflow
  • Extending Web apps to Native apps

Technical Requirements

To follow along with the instructions in this article, you will need to have the following (depending on the platforms you want to deploy too):

  • For the Android App: Android Studio on Windows, Linux, or Mac
  • For the iOS App: XCode and a Mac

To develop apps for iOS, officially, you need to do so on a Mac with macOS. However, if you aren’t currently developing for iOS, you can still follow along as many of the steps are similar and you can make the step towards iOS later with the required hardware.

Source files for this article are available at the following repository: https://github.com/PacktPublishing/PacktPlus/tree/main/Ionic/Extend-a-web-app-into-Android-and-iOS-apps-using-Ionic-Capacitor

The Native route

There are two approaches available to developers when we build new web apps that need to cater to a mobile audience as well. We either use the responsive web route, where the user accesses our web app through a mobile web browser, or we pick the native mobile app route, where we build native mobile apps for each mobile operating system.

The native apps approach have certain advantages over responsive web app approach:

  • Better performance
  • Better security
  • Offline capabilities
  • Access to device features
  • Seamless experience when on a mobile/tablet

Let’s look at how we can leverage these advantages while building a web app, without any additional effort.

Ionic Capacitor

Before we begin building an app, let’s understand what Ionic Capacitor is. Capacitor’s describes itself as,

“A brand new approach to building native apps with the Web — now even faster, more modular, and more enjoyable to build with than ever.”

Capacitor introduces us to a new world of apps, Native Web apps. These apps behave like native apps on a mobile device and like progressive web apps when on the web.

You can read more about the latest version of Capacitor 3.0 here: Announcing Capacitor 3.0

Understanding the Web app to Native app workflow

In this section, we’ll look at a workflow that helps us reuse a web app code base to build a native mobile app using Ionic Capacitor.

Figure 1 – Web app to native mobile app workflow

Considering the above workflow, we will start with a web app that we have spent our time and energy over. The web app we have built is a responsive web app that can be rendered on all devices in a responsive way.

Important Note

The web app that we have built follows a Single Page App architecture. This approach of adding native app capabilities to a web app can be achieved on a SPA and not on monolithic apps.

Typically, we build web apps and deploy it to a server, which can be accessed over web browsers.

For mobile, we’ll add Ionic Capacitor to the same code base. This will take care of wrapping the web app in a native shell and using that shell, we can build and deploy the native app to the stores.

Now that we’ve established the workflow, We can follow the steps required to building and deploying our native mobile apps.

Extending Web apps to Native apps

Now that we have a high-level understanding of what we are going to achieve, let’s list the steps to achieve it.

For the sake of this tutorial, we aren’t going to build a web app from scratch. We’ll leverage a Next.js Blog starter template instead. We’ll follow this broad overview to build and deploy the native mobile apps:

  1. Install Node.js
  2. Clone web app: https://github.com/timlrx/tailwind-nextjs-starter-blog
  3. Setup export process
  4. Add Capacitor
  5. Add Android and iOS platforms
  6. Deploy and test Android and iOS Apps
  7. Workflow to add native only features

As part of our workflow, we are going to integrate a Capacitor plugin with the web app that will work only in the native environment. More on this when we reach line item 7.

So, let’s get started with our 7 steps

Step 1: Install Node.js

You can install the latest version of Node.js by downloading it from here: Node.js Download.

For this tutorial, I’ve used version v14.17.0, as you can see in the following output :

❯ node -v


❯ npm -v


Step 2: Clone web app

Next, we’ll clone a simple blog web app, built on Next.js. To work with this approach, the web app need not be the sample app as the one used in this tutorial. We can use any headless app that can be converted to a static site and can be hosted on its own.

To clone the web app, run the following command:

$ npx degit https://github.com/timlrx/tailwind-nextjs-starter-blog.git

The above command will clone the web app to the tailwind-nextjs-starter-blog folder. Next, change directory into this folder and run the following command:

$ npm install

This will install the required dependencies to run the starter blog template.

To view the app in action, run

$ npm start

And when we navigate to http://localhost:3000/ we should see something like Figure 2.

Figure 2 – the deployed web app

This app comes out of box with a blog template and has light and dark mode. You can read more it here.

Now that our production ready web app is up and running, let’s move on to the next step.

Step 3: Setup export process

In this step, we’ll convert and export our Next.js SPA a static site. This way, the static website that gets exported from this code base will be moved into the native app.

Important Note

This export process is specific to Next.js, if you are using Angular or React or any other SPA libraries or frameworks, you’ll have to use instructions for how to build a static site from the code base specific to those frameworks.

For us to successfully export the static site, let’s follow these steps:

  1. Update the json scripts section and add the following line:

...// snipp

"export": "next export",

...// snipp

  1. Update config.js > withBundleAnalyzer function with the following line:

...// snipp

images: {

   loader: 'imgix',

   path: 'https://example.com/myaccount/',


...// snipp


To understand more about step 2 above, please refer to the following links:
1. Next.js 10 Image Optimisation Component and next-optimized-images, a brief comparison
2. Image Component and Image Optimization

  1. Finally run the following commands to export the static site to out folder

$ npm run build

$ npm run export

Once done, the out directory should look like Figure 3:

Figure 3 – the Out directory for the static site

This is the static version of our website that can be run on any environment that supports JavaScript.

Step 4: Adding Capacitor

The next step on our list is to add Capacitor to our existing web app code. Before we do that, please make sure you have completed the Environment setup.

To add capacitor to our existing code base, run the following commands:

$ npm install --save-dev @capacitor/core @capacitor/cli

$ npx cap init

The second command will create the capacitor.config.json file at the root of the project once we answer the questions presented to us.

The contents of the capacitor.config.json file should look like the following:


"appId": "com.example.app",

"appName": "tailwind-nextjs-starter-blog",

"webDir": "out",

"bundledWebRuntime": false


Do note that I have updated the webDir property to point to the folder where the static site is generated.

Step 5: Adding Android and iOS platforms

Now that the capacitor configuration has been completed, we will add the Android and iOS platform related code setup to our web app code base.

Run the following commands for Android:

$ npm install @capacitor/android

$ npx cap add android

Run the following commands for iOS:

$ npm install @capacitor/ios

$ npx cap add ios

If everything works properly, we should see 2 new folders, android and ios that will have native code for the static website.

You can read more about Android and iOS Capacitor support here: Capacitor Android Documentation and Capacitor iOS Documentation.

Step 6: Deploy and test Android and iOS Apps

Now that we have the Android and iOS apps setup, we will run them to view the output.

iOS App

To deploy an app to iOS, you will need to use XCode on a Mac. If you have the setup, follow these instructions to deploy the app, starting with the following command:

$ npx cap open ios

And then you can use the XCode IDE to run the app.

If you would like to run the app via command line without opening the code in XCode, run the following code on a Mac.

$ npx cap run ios

And we should see the output shown in Figure 4.

Figure 4 – the deployed iOS app

Android App

To deploy the Android app, open the code base in Android Studio by running the following command:

$ npx cap open android

And then you can use the Android Studio IDE to run the app.

If you would like to run the app via command line without opening the code in Android Studio, run the following command:

$ npx cap run android

And we should see the output shown in Figure 5.

Figure 5 – the deployed Android app

Step 7: Workflow to add native only feature

Now that we’ve learned to convert a web app to a native app with all the features of the web one, let’s look at customizing the app to add native only features on top of the web app and make this code run only on the native app.

To explore this option, we are going to implement the Share plugin (https://capacitorjs.com/docs/apis/share) which lets users share posts directly to native apps. We don’t want to use this plugin or behaviour in the web app but only inside the native app.

To achieve this, we need to add the share plugin to our web app and set up the plugin to run the code only when the app is deployed as a like a native app.

  1. To install the Share plugin, run the following commands:

$ npm install @capacitor/share

$ npx cap sync

  1. Next, open tailwind-nextjs-starter-blog/pages/index.js and add the following import statement to the plugin at top:

import { Share } from '@capacitor/share'

  1. Next, we need to identify if the current app is executed as a web app or a native app. For that we are going to use the following snippet

const IS_CORDOVA_APP = typeof window === 'undefined' ? undefined : !!window.cordova

IS_CORDOVA_APP will be true when we run on devices, using Ionic Capacitor and false when we run on the web

  1. Next, I am going to create a component to display a “Share” link based on the type of device

const MobileNativeShare = ({ frontMatter }) => {

const { slug, title, summary } = frontMatter

const showNativeShare = async () => {

   if (IS_CORDOVA_APP) {

     await Share.share({


       text: summary,

       dialogTitle: slug,




return IS_CORDOVA_APP ? <button onClick={showNativeShare}>Share</button> : ''


  1. And finally after the “Read more” link, we will add the native share link

<MobileNativeShare frontMatter={frontMatter}></MobileNativeShare>

  1. Now we’ll build, export and sync the code base. Once done, we will run the app on Android and iOS to validate. Run the following comments to do this:

$ npm run build

$ npm run export

$ npx cap sync

$ npx cap open android

$ npx cap open ios

And now in the native app, we should see the Share link:

Figure 6 – The native app with a Share option

  1. If we tap on it, we should see the share sheet for each device, as shown below

Figure 7 – Share sheets for Android and iOS

With that, our native mobile app is done!


In this article, we learned to convert an existing single page app style web app to a native app and add native app only features, to enhance the experience, without losing the cross-platform reusability using Capacitor. This cross-platform development approach is highly suitable for projects where we want to publish our app as a native app and at the same time deploy a web version with the same code base.


About the Author

Arvind Ravulavaru is a platform architect at Ubiconn IoT Solutions, with over 9 years of experience in software development and 2 years in hardware & product development. For the last 5 years, he has been working extensively on JavaScript, both on the server side and the client side. Over the past couple of years his focus has been on IoT, building a platform for rapidly developing IoT solutions, named The IoT Suitcase. Prior to that, Arvind worked on big data, cloud computing, and orchestration.

By | 2021-09-27T10:34:30+00:00 September 27th, 2021|Uncategorized|0 Comments

About the Author:

Leave A Comment