How to convert any website/webpage into an installable progressive web app (PWA)
Tags: pwa, webdev, javascript, webapp
Published: 2021-02-16 19:44:38

Hi there!
Thinking about how to convert any website/webpage to an **installable progressive web app**? read on.

In this tutorial, we are going to convert an HTML5 based game into an installable web application, which can be installed on Android or iOS devices.

Made this classic [simon game,](https://simons-game.now.sh/) which is really simple in nature but quite addictive. You can [fork](https://github.com/zippytyro/Simon-game) or [star](https://github.com/zippytyro/Simon-game) this repository to make it your own or suggest any further improvements.

![Simon-game PWA screenshot](https://dev-to-uploads.s3.amazonaws.com/i/le1898nzynyo1lgtm3qf.jpg)

## What is a PWA?
> A progressive web app (PWA) is the set of mobile web application development techniques that entails building apps that feel and look like native ones. Using a web stack (JS, HTML, and CSS), progressive web apps combine rich functionality and a smooth user experience associated with native apps. Simply put, PWA is the web app with the native-app flavor: After the installation, a user clicks on its icon on a device's home screen and gets straight to the website.
 
One of the best features of PWA's is that it is installable on user's devices like native apps, and work in offline mode too.

## Steps to take - 
* Create a service worker file.
* Update the main document to check if the functionality is supported.
* Create manifest.json for app metadata.
* Use Chrome dev tools to debug the app.

### 1. Service worker
Create a `service-worker.js` file in the root directory of the project, it is important to put it in the root directory to help us store static content in cache storage. You can almost store any kind of media in cache storage like mp3, mp4, video maybe? and obviously the static file HTML, CSS, and JS.

```javascript
// Installing service worker
const CACHE_NAME  = 'Simon-game';

/* Add relative URL of all the static content you want to store in
 * cache storage (this will help us use our app offline)*/
let resourcesToCache = ["./", "./img/game.png", "./game.js", "./styles.css"];

self.addEventListener("install", e=>{
    e.waitUntil(
        caches.open(CACHE_NAME).then(cache =>{
            return cache.addAll(resourcesToCache);
        })
    );
});
```
> NOTE: change the `CACHE_NAME` const to your own app's name

Add two more event listeners - 
```javascript
// Cache and return requests
self.addEventListener("fetch", e=>{
    e.respondWith(
        caches.match(e.request).then(response=>{
            return response || fetch(e.request);
        })
    );
});

// Update a service worker
const cacheWhitelist = ['Simon-game'];
self.addEventListener('activate', event => {
    event.waitUntil(
      caches.keys().then(cacheNames => {
        return Promise.all(
          cacheNames.map(cacheName => {
            if (cacheWhitelist.indexOf(cacheName) === -1) {
              return caches.delete(cacheName);
            }
          })
        );
      })
    );
  });
```
> NOTE: Replace the `cacheWhiteList` variable with your own app's name

###2. Check for availability (update index.html)
In the case of a static website, update the main HTML document to check for the availability of service workers, and register our app using the `service-worker.js` file.

```javascript
  <script>
    if('serviceWorker' in navigator){
      navigator.serviceWorker.register('/service-worker.js');
    } else {
      console.log("Service worker is not supported");
    }
  </script>
```

###3. Create manifest.json file
Create a `manifest.json` file, we need to link that to our main HTML document.
```html
<link rel="manifest" href="manifest.json">
```
Now, this file contains metadata about our app, like App name, icons reference, URL to open on the opening of the app, etc.
```JSON
{
    "name": "Simon Game",
    "short_name": "Simon Game",
    "start_url": "/",
    "background_color": "#FFDCB5",
    "theme_color": "#1E003D",
    "icons": [
        {
            "src": "img/512.png",
            "sizes": "512x512",
            "type": "image/png",
            "purpose": "maskable any"
        },
        {
            "src": "img/192.png",
            "sizes": "192x192",
            "type": "image/png",
            "purpose": "maskable any"
        }
    ],
    "display": "standalone",
    "orientation":"portrait"
}
```
Copy/paste the above code in the manifest and change your app details. You can reference a single icon or use icons of multiple sizes, as devices differ in screen sizes.

###4. Use dev tools to debug

Now open the chrome dev tool (`ctrl+shirt+i`) and click on the applications tab to check if the service worker and manifest file are detected by the browser.
As you can see below the logo and name of the app are shown. 

![Dev tools](https://dev-to-uploads.s3.amazonaws.com/i/34z8tr2ryyo31686iygm.PNG)

The `background_color` property sets the splash screen color and `theme_color` the notification bar.
![Splash screen simon-game](https://dev-to-uploads.s3.amazonaws.com/i/rievmmshxb9i1n33f0gr.jpg)

You can also check if your app meets the standard for PWA, in the lighthouse tab and click generate the report.

![Lighthouse tool](https://dev-to-uploads.s3.amazonaws.com/i/37dp1pwumgocpd5kt9bd.PNG)

This will also help you to add things that you might forget like adding this line for iPhone/Apple users.
```HTML
<link rel="apple-touch-icon" href="img/game.png"/>
```
![PWA compatible](https://dev-to-uploads.s3.amazonaws.com/i/cp6qlpmo3cxij7pmys6i.PNG)

BOOM, we are done! You have successfully converted a website/game into a PWA.

### How to install on devices?
On chrome, you'll have this small add icon on the URL bar, which prompts you to install the app on your device.
![Install icon on URL bar](https://dev-to-uploads.s3.amazonaws.com/i/hdf24jzpaz0qmfjwvueb.PNG)

On mobile devices, you'll get a prompt (Chrome)
![Install prompt](https://dev-to-uploads.s3.amazonaws.com/i/l8goowq3i6yo382w845z.PNG)

If not then click on the 3 dots in the top right corner, an "Install app" option appears.
![3 dot menu on chrome](https://dev-to-uploads.s3.amazonaws.com/i/cfz9631sfrc1ywng02hg.jpg)

Perfectly installed on Android.
![Installed on Android device](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vued03hjhztq6jb0gd0s.png)
 

Hope it helped. Give a like :)

Cheers,
[Shashwat
Follow me on twitter](https://twitter.com/zippytyro)