Building Progressive Web Apps in 5 Simple Steps

Progressive Web Apps (shortly PWA) have recently been introduced by Google in an attempt to combine web browsers and mobile applications. According to Addy Osmani from Google:

“Progressive Web Apps use modern web capabilities to deliver an app-like user experience. They evolve from pages in browser tabs to immersive, top-level apps, maintaining the web’s low friction at every moment.”

In fact, they are websites which take advantage of the features that mobile applications have to offer. This makes them better than typical mobile applications and one step ahead of the ordinary web pages on mobile. What are the benefits of progressive web apps:

  • Responsive. Work on any device.
  • Work offline. Don’t need an Internet connection. Can download information quickly even if the connection is weak.
  • Discoverable. Can be easily found by search engines.
  • Installable. Can be installed on smartphones immediately, without any app stores.
  • Support push-notifications
  • Update automatically
  • Framework-friendly

What you get by using PWA is an app-like behavior, the Splash screen with your graphic and the possibility of being installed to the home screen. In addition, you can implement the PWA principles to any existing website. Sounds appealing, right? Then let’s go into details.

What Makes Progressive Web Apps Better?

One of the main principles of Progressive Apps is the Application Shell architecture. It means that the User Interface (Application Shell) is separated from the dynamic content.

This is what provides the ability to cache the Application Shell as well as work offline. Thanks to this, your app can work without any internet connection. Even if the application itself has recently been closed. Moreover, if the user visits it repeatedly, Progressive Web App loads significantly faster as all resources are cached.

However, let’s move from theory to practice. To give you a basic understanding of Progressive Web Apps in practice, we will create a simple working sample.

(drum roll please) Ladies and Gentlemen, please welcome the To-do List App!

Step 1: Let us build a simple To-Do List App

We will not attempt to reinvent the wheel. We are going to use a well-known practice and an ordinary set of source code, displaying the Progressive Web App benefits along the way.

Imagine we are working on an MVP (Minimum Viable Product). However, there will be no frameworks, libs or packages. Our goal is to understand the Progressive Web App approach, not to produce perfect code.

Creating a To-do List App is considered to be one step above the usual “Hello World”, which is the “standard” example people use when teaching a new language or technology.

Our to-do list will provide a user experience with post-it notes, which can be used anytime, even when you do not have an internet connection. The App will be simple and easy to use via the desktop icon, looking native.

Step 2: Which Boilerplate to Use?

The Google developers provide us with a few different boilerplates for interesting apps. However, we will not use any boilerplate in order to better learn how to create our own. This building process will allow us to dive deeper into the PWA technology basics.

First, we will use the simplest and clearest Web App (Basic WEB-Technology stack: JS + HTML + CSS). There are a few files which are basic for the app creation. Like a regular website skeleton, there is nothing new.

  • app.js – To-do List app code
  • inline.css – file of styles
  • index.html – markup file, listed below:
<!DOCTYPE html>
<html>
<head>
         <meta charset="utf-8">
         <meta http-equiv="X-UA-Compatible" content="IE=edge">
         <meta name="viewport" content="width=device-width, initial-scale=1.0">
         <title>Todo list</title>
         <link rel="stylesheet" type="text/css" href="styles/inline.css">
</head>
<body>
         <header class="header">
                  <h1 class="header__title">
                          Todo list
                  </h1>
         </header>
         <main class="main">
         </main>
         <script src="scripts/app.js" async></script>
</body>
</html>

For an MVP To-Do app the simplest “TO-DO in HTML5 and plain JavaScript” by Gabor Szabo will be enough as a skeleton. We will add a filtering idea and our beautiful corporate style to build a sample. All of the code is placed into the app.js file.

Step 3: Let’s Make the App Progressive

There are two main things which are the “magic pillars” of the whole Application Shell.

  • manifest.json – a simple W3C standard JSON file
  • service-worker.js – a transparent Javascript events logic file, which provides offline experiences

Step 3.1: How to Add a Web App Manifest

The W3C Web App manifest can make your app indexable by search engines. Furthermore, indexable not as a usual website, but as a web app. It provides the ability to:

  • present your app by means of a few icons
  • make it discoverable
  • customize its layout and appearance
  • add a homescreen (splashscreen)
  • make it easily installable, without any app stores

How does a simple manifest.json look?

{
     "name": "Todo List",
     "short_name": "Todo",
     "icons": [
           {
                "src": "images/icons/android-chrome-192x192.png",
                "sizes": "192x192",
                "type": "image/png"
            },
           {
                "src": "images/icons/android-chrome-512x512.png",
                "sizes": "512x512",
                "type": "image/png"
           }
     ],
     "start_url": "/index.html",
     "display": "standalone",
     "background_color": "#3E4EB8",
      "theme_color": "#2F3BA2",
}

Here we gave a name to:

  • the app
  • home screen icon
  • two icons for the splash screen
  • URL for the application start
  • full-screen display mode

The background theme color is supported only by the latest Chrome versions.

The simple example of manifest is available at the Web Starter Kit and in the Google Chrome samples. We used real favicon generator to generate the manifest, size images, favicons and iOS icons and added it to our To-Do List App.

Chromium-based browsers (Chrome, Opera, etc.) already support the manifest.

Firefox supports it too, but it is still in development. Edge is under question. WebKit/Safari haven’t said anything about the support implementation.

Step 3.2: How to Add a Service Worker (Offline Mode)

It’s time to make our To-Do List App work offline. The Service Worker is a plain JavaScript file which can run in the background, separately from web page scripts. It uses Events actions and wake-ups and works only if it’s needed. It responds to the events, including network requests.In conjunction with the Cache API, it provides our To-Do List App with the ability to work offline.

// Cache names
var dataCacheName = 'TODOData-v1.1.4'
var cacheName = 'todoPWA-1.5'
// Application shell files to be cached
var filesToCache = [
       '/',
       '/index.html',
       '/scripts/app.js',
       '/styles/inline.css',
       '/images/waverley_logo.png',
       '/images/waverley_logo_small.png',
       '/images/close.png',
       '/images/ic_add_white_24px.svg'
]
self.addEventListener('install', function (e) {
      console.log('[ServiceWorker] Install')
      e.waitUntil(
             caches.open(cacheName).then(function (cache) {
                     console.log('[ServiceWorker] Caching app shell')
                     return cache.addAll(filesToCache)
              })
      )
})
self.addEventListener('activate', function (e) {
      console.log('[ServiceWorker] Activate')
      e.waitUntil(
              caches.keys().then(function (keyList) {
                       return Promise.all(keyList.map(function (key) {
                               if (key !== cacheName && key !== dataCacheName) {
                                    console.log('[ServiceWorker] Removing old cache', key)
                                    return caches.delete(key)
                               }
                        }))
              })
      )
      return self.clients.claim()
})
self.addEventListener('fetch', function (e) {
      console.log('[ServiceWorker] Fetch', e.request.url)
      e.respondWith(
             caches.match(e.request).then(function (response) {
                     return response || fetch(e.request)
             })
       )
})

Keep in mind that it is very important to place the service worker file into the root folder of your app tree. The service worker scope is defined by the directory where it has been placed.

Don’t forget to check if the browser supports the service workers before registering. We can insert this code to the end of index.html file in the script tag or directly to the app.js file:

if ('serviceWorker' in navigator) {
     navigator.serviceWorker
             .register('./service-worker.js')
             .then(function() 
                    { console.log('Service Worker Registered'); 
             });
}

Basically, it is enough to make your app work offline.

However, we need to mention one more important thing: Service Worker functionality is only available on pages accessed via HTTPS (http://localhost and equivalents will also work, to facilitate the testing process). The good thing is that our app will be secure.

Good news, Chromium-based browsers (Chrome, Opera, etc.) and Firefox support Service Workers now. Edge have publicly announced their interest in implementing the technology. WebKit/Safari have included this support to their 5-year plan.

Step 3.3: How to enable push notifications in Progressive Web Apps?

Push notifications have always been a huge advantage of native applications in comparison with ordinary websites. However, starting from Chrome 42 this feature became available for web developers. At first, it started with the support of Push API and Notification API. It has provided a chance to re-engage users, let them stay in touch in a timely manner with the help of customizable notifications.

In order to be able to take full advantage of this feature, you need to have a manageable backend which you can customize and trigger push notifications to each user. We will show you how to make the simplest notifications and observe how it works.
In comparison with the previous PWA parts, Push Notification is a more complicated feature, and it takes more effort.

One way to do this is to use Firebase Cloud Messages. As you remember, we have deployed our app to the Firebase project. Now it’s time to use one of the Firebase features – Firebase Cloud Messaging.

1. You need to go to the Firebase console and select your project.
2. In the project settings, under the Cloud Messaging tab you will see the Sender Id and Secret Key

3. Insert the Sender Id to the end of the manifest.json file
“gcm_sender_id”: “”
4. Save the Secret Key, we will use it a little bit later to send the actual messages.

In order to configure To-Do list app for push notifications, we need to do a lot of checking and preparing steps, to support features, permission actions and subscriptions in our App. There is a ponderable piece of code, described in detail in the article by Matt Gaunt from Google Developers, with final code samples available on Github.
After all the steps are done, users of the app will be able to allow push notifications activation in their browsers:

Triggering the Firebase Cloud Message
Usually triggering of the FCM is managed by the server (back-end). However, in our investigation steps we can use the simple way, to show the real feature workability. We can use the terminal CURL command to send the message

curl --header "Authorization: key=" --header
"Content-Type: application/json" https://android.googleapis.com/gcm/send -d
"{\"registration_ids\":[\"\"]}"

Where Authorization key is the Firebase Secret Key from the Firebase configuration, registration Id is your running app identificador, for the message to be sent.
A basic notification looks like this:

You are able to modify the notifications on your own via the client side implementation. You can forward users to your website by one click, or fetch some data to be shown from the Web, it’s a very powerful feature. However, there is one disadvantage. Browser push notifications do not allow any data to be attached. Nothing at all.

Push notifications are now still in the active development process. In the future we will be able to simply use Push notifications in the iOS and Webkit browsers. But now, while it isn’t completely implemented, we can use FCM API to test Push notifications. This feature is supported by Google Chrome browser version 42 and later.

Step 4: How to Add PWA to the Home Screen banner

Progressive Web Apps not only provide installation ability, but also the ability to put them on a homescreen banner like a native web app.

Engineers from Google collected the required criteria:

  • to have a web app manifest file, which defines how your app will appear in the user’s system and how it should be launched
  • the manifest must have a `short_name`, a name to be displayed in the banner
  • to have a loadable start URL (e.g. / or index.html)
  • PNG icon should be at least 144x144
  • icon declarations should include a mime type of image/png
  • to have a Service Worker registered on your site. We recommend a simple custom offline page service worker
  • Your site needs to be served over HTTPS (service worker requires HTTPS for security concerns)
  • Your site must have at least 2 user visits with at least five minutes between them

However, please keep in mind that this criteria will change over time.
Only Chrome for Android (starting from Chrome 42) allows users to quickly install your Web App.

The last thing left to make our app work: HTTPS (as required by Service Worker).

Step 5: How to Deploy a Progressive Web App to the Firebase

Firebase is the cloud service tool and infrastructure you need to build your App into the Web. It provides simple usage of storage, hosting, push notification services and many other opportunities. Besides this, it secures your App with HTTPS.

To deploy our Progressive Web App to Firebase we need to do the following:

  1. Sign in to FireBase
      • If you are new to Firebase – create an account
      • Install the Firebase console tools (npm install -g firebase-tools)
    1. Create an App using your account
    2. Deploy the app to Firebase
      • If this is the first time you’re installing Firebase tools, update your credentials (firebase login)
      • Initialize your App in the root directory (firebase init)
      • Deploy your app to the cloud service (firebase deploy)

That is it! It’s time to finally try our newly-created Progressive Web App. You can go to the app URL via a browser from the desktop or a mobile device to discover it. You can easily share it, use offline, and just enjoy its wonderful app-like behavior.

As an Epilogue

Browser support casts a shadow on this new trend. So far the complete experience is available for the Chrome browser only. Opera and Mozilla have certain limitations, having not implemented some features yet. Edge is in development now, and looks like it’s coming soon. Safari – no support at all.

Nevertheless, in our opinion, Progressive Web Apps allow us to do big things. They bring ordinary websites to a new level and make them much more user-friendly. Keep in mind, it is not a separate solution, just an enhancement of an existing one, but for sure a cool, powerful and useful enhancement.

P.S. We decided to help Google and suggested how the logo for PWA technology could look like 🙂

About the Author