How to publish your web app to the Play Store
Published: 2020-10-06 14:17:18

---
title: How to publish your web app to the Play Store
description: A simple guide detailing how to package any website as an Android app and submit it on the Play Store
published: true
date: 2020-09-10 00:00:00 UTC
tags: 
canonical_url: https://miguelpiedrafita.com/website-to-apk
cover_image: https://miguelpiedrafita.com/images/website-to-apk/cover.jpg
---

I recently had to figure out a way of making an Android app for one of my projects. I looked into Android Studio, Koltin, and Flutter, and quickly learned it takes a massive amount of work to make an app from scratch.

So, instead of doing that, I decided to cheat a little bit, and use my already-responsive web app as the mobile app. I even managed to package it into a real Android app and submit it to the Play Store! Here's how you can do the same.

## 1. Make your web app responsive
This is not _strictly_ required, but no one wants to use a web app that looks bad. You want to make sure your website looks great on mobile, which you can do [from your browser's developer tools](https://developers.google.com/web/tools/chrome-devtools/device-mode#viewport). I'd also recommend you to preview your website from your phone since the devtools simulator isn't always perfect.

## 2. Create a Web Manifest
This may sound complex, but it's actually pretty easy, and you can get most of the way there using almost any favicon generator.

What am I talking about? You probably know that you can change this globe icon that appears next to your website's title on your browser by adding a `favicon.ico` file with your logo. What you may not know is that your favicon is also used in many other places, like when adding your website to the home screen on iOS or Android.

While we can use the same file for everything, different platforms have different requirements, and we can provide different versions of our logo for optimal results. While we could generate all these different variations ourselves, there are plenty of tools online that can do this for us. We'll be using [favicon.io](https://favicon.io/favicon-converter/) since it's one of the few that don't look like they were designed ten years ago. We just need to upload a high-res version of our icon and click the download button, and we'll get a ZIP file with a bunch of icons and a manifest file. We'll add these to our site and copy the following tags to the head of our HTML.

```html
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
```

Finally, we'll need to tweak a few things on our manifest file, like adding the name of our app, changing the theme and background colors (which are used for the splash screen), and adding a start URL (`start_url`), which indicates which page will users see when they open your app.

```diff
{
    "name":"Example App",
    "short_name":"Example App",
    "icons":[
        {
            "src":"/android-chrome-192x192.png",
            "sizes":"192x192",
            "type":"image/png"
        },
        {
            "src":"/android-chrome-512x512.png",
            "sizes":"512x512",
            "type":"image/png"
        }
    ],
    "theme_color":"#ffffff",
    "background_color":"#ffffff",
    "display":"standalone",
+   "start_url": "/dashboard"
}
```

## 3. Add a Service Worker
The next step is to add a service worker to our website. Service workers can be used for a lot of interesting things, like background sync or push notifications, but we'll be using them to cache the pages of our app so they load while offline.

To do this, we'll first need to create our service worker file, which we'll call `sw.js`, and add the following code:

```js
const cacheName = "offline-pages";

importScripts('https://storage.googleapis.com/workbox-cdn/releases/5.0.0/workbox-sw.js');

self.addEventListener("message", (event) => {
    if (!event.data || event.data.type !== "SKIP_WAITING") return

    self.skipWaiting();
});

workbox.routing.registerRoute(
    new RegExp('/*'),
    new workbox.strategies.NetworkFirst({ cacheName })
);
```

Keep in mind this needs to be in a different file from your existing javascript, and can't be bundled alongside it.

Finally, we'll load our service worker from our website's javascript, with the following code.

```js
if ("serviceWorker" in navigator) {
  navigator.serviceWorker.register("sw.js");
}
```

## 4. Bundle everything into an app
With our manifest and service worker running in production, we're ready to make our Android app, or rather have it made for us. For this, we're gonna use [bubblewrap](https://github.com/GoogleChromeLabs/bubblewrap/tree/master/packages/cli), a CLI tool developed by the Chrome team to generate Android apps from Progressive Web Apps (which is what we just created by adding a manifest and a service worker).

Before we install it though, we need to make sure we have downloaded [JDK 8](https://adoptopenjdk.net/releases.html?variant=openjdk8&jvmVariant=hotspot) and the [Android command line tools](https://developer.android.com/studio#command-tools). We can either download and unzip these libraries individually (links in the description) or install [Android Studio](https://developer.android.com/studio) and have them be downloaded automatically. With both dependencies installed, we'll run `yarn global add @bubblewrap/cli` to install bubblewrap.

When running it for the first time, it'll ask for the dependencies we downloaded earlier. If you decided to install Android Studio (and you're on a Mac), your JDK path is `/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk` and your SDK path is `/Users/YOUR_USERNAME_HERE/Library/Android/sdk`.

Alright, with all this done, let's create a new directory and run `bubblewrap init --manifest https://YOUR_WEBSITE/site.webmanifest` from inside it. This process will ask you a few questions and generate a signing key if you don't already have one. Make sure to backup this key, and take note of the keystore password, key password, and key alias, or you won't be able to release future updates to your app.

You can build your app by running `bubblewrap build --generateAppBundle` and grabbing the `app-release-signed.apk`, which we can then go and install on our phone.[

This will also generate `app-release-bundle.aab`, which we'll need for submitting our app to the Play Store later, and `assetlinks.json`, which we'll need to upload to our website at `/.well-known/assetlinks.json` for our application to work.

## 5. Submitting your app to the Play Store
We already have an app we can install on our phone, let's now get it on the Play Store so everyone can download it. Let's head to the [Play Developer Console](https://play.google.com/console) and create a new app. If you don't have a Play Developer account yet, you'll need to accept some conditions and pay a one-time $25 fee.

After answering a few questions like the name of our app, it's main language, it's price, and whether it's an app or a game. We'll be able to create our app. We'll need to complete every task listed under _First Steps_ before we can create a release, and set up a store listing including a description for our app, a feature graphic, and at least three screenshots, which will be shown in our Play Store page.

Once that's done, we can move on to creating our first release. We'll do this from the production menu, where we'll first need to select what countries we want our app to be available on. Then we can create a new release and upload the `app-release-bundle.aab` file we created earlier. We'll also need a release name (invisible to our users) and some release notes (shown in our Play Store page).

With that filled in, we can publish our release and sit back, because the review period can last anywhere between one and twenty days. Once the review is complete, you'll get an email letting you know your app is now available for download from the Play Store.