Making an app installable

web
mobile

Streaming now live

HTML, CSS - free educational webinar for your quarantaine.

WATCH NOW

Free live lesson

Learn HTML, CSS & JavaScript fundamentals. Join now, and don't miss the livestream.

JOIN NOW

Making an app installable I: The Manifest

One of the most powerful functions that PWA offers is the ability to add our web app to a device's home screen. This feature helps to bridge the gap between native and web apps, allowing for the latter to look and feel the "native" way.

Surprisingly, it doesn't require a lot of work. We will cover everything in the upcoming lessons.

What the feature boils down to is presenting users with ability to install our app onto their homescreens. In pratice, the ability takes form of an App Install Banner - a simple browser dialog. According to the official documentation, there are only few requirements:

  • The web app is not already installed
  • the user has interacted with the domain for at least 30 seconds
  • codebase includes a web app manifest
  • App is served over HTTPS
  • Has registered a service worker with a fetch event handler (currently necessary for Chrome on Android only)

Of course the two first ones are beyond our control, it's the user who decides for how long the interactions takes place or what is or isn't installed at their homescreens. As developers, we have to take care of the last three. Let's begin with the app manifest.

What is an app manifest?

App manifest is a simple JSON file, describing some of the properties the app has to have defined to utilize the PWA charm. In that, the file resembles an App Store description of a native app. It is possible that you have already stumbled upon it in some other projects' directories, escpecially the ones created using vue-cli or create-react-app boilerplate systems.

Minimal manifest.json consists of these fields:

  • name and short_name - either one. If both are provided, short_name is used on the user's home screen, launcher, or other places where space may be limited. name is used in the app install prompt.
  • icons - an array of objects represening images, each with its src, size and type fields. Must include 192px and 512px sized icons. Chrome will automatically scale the icon for the device. If you'd prefer to scale your own icons and adjust them for pixel-perfection, provide icons in increments of 48dp
  • start_url - tells the browser where your application should start when it is launched, and prevents the app from starting on whatever page the user was on when they added your app to their home screen. Add a query string to the end of the start_url to track how often your installed app is launched
  • 
              "start_url": "/?utm_source=homescreen",
            
  • display
  • must be one of: fullscreen, standalone, or minimal-ui. It changes how much of browser UI is shown to the user and can range from "browser" (when the full browser window is shown) to "fullscreen" (when the app is full-screened).

A full list of the supported properties which can be used is found here.

Now, armed with the necessary theoretical background, let's create a manifest.json file on our own! Let's place it in the project's /static directory, hinting that we want to keep it as it is (static), rather than having it somehow processed, as we do with the .vue files, for example. Doing so in there means we no longer need the .gitkeep file, which was only ensuring the folder gets considered by the contol system we can freely get rid of it.


        {
        "short_name": "Agenda App",
        "name": "MDBootstrap Agenda App Demo",
        "icons": [
        {
        "src": "icons/Icon-36.png",
        "sizes": "36x36",
        "type": "image/png"
        },
        {
        "src": "icons/Icon-48.png",
        "sizes": "48x48",
        "type": "image/png"
        },
        {
        "src": "icons/Icon-72.png",
        "sizes": "72x72",
        "type": "image/png"
        },
        {
        "src": "icons/Icon-96.png",
        "sizes": "96x96",
        "type": "image/png"
        },
        {
        "src": "icons/Icon-120.png",
        "sizes": "120x120",
        "type": "image/png"
        },
        {
        "src": "icons/Icon-144.png",
        "sizes": "144x144",
        "type": "image/png"
        },
        {
        "src": "icons/Icon-152.png",
        "sizes": "152x152",
        "type": "image/png"
        },
        {
        "src": "icons/Icon-167.png",
        "sizes": "167x167",
        "type": "image/png"
        },
        {
        "src": "icons/Icon-180.png",
        "sizes": "180x180",
        "type": "image/png"
        },
        {
        "src": "icons/Icon-192.png",
        "sizes": "192x192",
        "type": "image/png"
        },
        {
        "src": "icons/Icon-512.png",
        "sizes": "512x512",
        "type": "image/png"
        },
        {
        "src": "icons/Icon-1024.png",
        "sizes": "1024x1024",
        "type": "image/png"
        }
        ],
        "start_url": "./index.html",
        "display": "standalone",
        "background_color": "#000000",
        "theme_color": "#4DBA87"
        }
      

Icons

As you can see, the JSON file are referencing a number of images of different sizes we do not have yet. Why do we even include them all? There is a world of screens waiting for our PWA to get installed, most of them have their own size and pixel density. To be able to cover that means preparing these images up front and including them into our web manifest. Let the app do the rest regarding picking a proper picture for viewing.

Note!

All the different sizes are mentioned to illustrate the possible pixel-perfect coverage purposes, which exceed beyond a minimal manifest example. To satisfy Lighthouse PWA Audit, which is an important benchmark (more on that in the upcoming lesson) you may want to start off small. In that case, I'd suggest beginning with a 192x192px and a 512x512px-sized icons.

Let's break the list down. The 36x36, 48x48, 72x72, 96x96, 144x144 and 192x192 pixels icons are optimized to be used on the Android platform; folks at Google made sure these sizes would play well without getting pixelated or blurry. To cover all the Andoroid needs, what we also need is a 512x512 - it's used for the splash-screens.

The sizes of icons for iOS platform are: 120x120, 152x152, 167x167 and 180x180 pixels. It's the last one that covers the most current iOS guidelines - the others are included for backward compatibility reasons. The final dimensions set you might need, 1024x1024, is used in the Apple App Store. Even though not many PWAs end up there, a large square icon might turn out handy, as it can always get scaled down by the plarform.

You'd like to have your own icon, but you do not know where to start? When it comes to the very design, the same best practices for any Android icon should be followed. In case you already have an icon for an app, but you think creating all these different files manually is a drag - you are absolutely right! There are many online tools for creating necessary icon sets for PWA - you may want to research your favorite one, or let us provide you with a zip so you don't have to. Add the (unzipped) /icons folder into the static/ directory.

Linking the manifest up

We are almost done here - the only thing that's left is actually letting the browser know the manifest is on board by including it into the >head< tag of our ./index.html file in the project's root directory.



        <head>
          <meta charset="utf-8">
          ...
          <link rel="manifest" href="/static/manifest.json" />
        </head>
      

After running yarn build or yarn deploy, you should see the /static folder copy being instilled inside the /dist directory. Having the file structure copied means the relative route, embedded explicitly in our HTML, stays the same, while the rest of the project gets prepared for a deploy.

To see whether everything works, simply yarn dev the project and refer to the devtools console (F12 or Ctrl + Shift + J depending on the browser used). All the possible problems with icon availability, caused by either a file mis-naming or improper JSON formatting should be listed there. For more holistic approach towards testing the PWA-readiness of our app, stick with us for an upcoming lesson regarding the audit.

In the next lesson, we will take care of the two other criteria on the list - HTTPS and service worker.

Something doesn't work for you? Then check the code for this lesson on our repository!


Previous lesson Download Live preview Next lesson

Spread the word:
Do you need help? Use our support forum

About the author