Turning a static Hugo site to a Progressive Web Application

After learning the basics of Progressive Web Applications (PWAs) at work, I decided to update this site to fill the requirements of a PWA. The commit with those changes can be found here. This post contains the basic details required to turn a static Hugo site like this one into a PWA.

‘Additional’ requirements for a PWA Link to heading

Beyond what is listed here, a PWA has other requirements a well - for example the site must be served over HTTPS - but these are the ‘additional’ steps I had to take to enable the functionality on this site.

  • Broad set of icons for different platforms
  • A Manifest file site.webmanifest or manifest.json - (ref)
  • A JavaScript “service worker” - (ref)
  • Some added HTML to refer to the various icons and provide other meta data

Creating icons Link to heading

A PWA will need various sizes of icons for use with different platforms. If you already have a base image, you can feed it through favicomatic to generate all the different variations. If you don’t already have a base icon, one good resource is this launcher icon generator.

These icons need to be served along with your site, from the static folder.

Updating / creating the apps web manifest Link to heading

The name of the manifest file seems to vary, but my site was using site.webmanifest. The format should follow JSON, and the file should be provided in the static folder of your site.

The site.manifest of this site is included below and can serve as a starting point.

{
  "name": "AVIITALA.com",
  "short_name": "AVIITALA.com",
  "theme_color": "#212121",
  "background_color": "#212121",
  "display": "standalone",
  "start_url": "/",
  "orientation": "portrait",
  "icons": [
    {
      "src": "/images/favicon-128.png",
      "sizes": "128x128",
      "type": "image/png"
    },
    {
      "src": "/images/apple-touch-icon-144x144.png",
      "sizes": "144x144",
      "type": "image/png"
    },
    {
      "src": "/images/apple-touch-icon-152x152.png",
      "sizes": "152x152",
      "type": "image/png"
    },
    {
      "src": "/images/favicon-196x196.png",
      "sizes": "196x196",
      "type": "image/png"
    },
    {
      "src": "/images/splash.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "maskable"
    }
  ]
}  

Creating a minimal service worker Link to heading

For this site, I didn’t need any ‘real’ functionality from a service worker, and hence just added this minimal service worker to fill the requirement:

self.addEventListener ('fetch', function(event) {
});

Updates to the HTML Link to heading

The HTML code has to contain certain meta tags with information for PWA usage. The below sample from this page omits listing every icon but contains all other essentials.

<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-title" content="AVIITALA.com" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="application-name" content="Antti Viitala"/>

<!-- various other "apple touch-icon-precomposed" lines -->
<link rel="apple-touch-icon-precomposed" sizes="57x57" href="https://aviitala.com/images/apple-touch-icon-57x57.png" />

<!-- various other "icon" lines -->
<link rel="icon" type="image/png" href="https://aviitala.com/images/favicon-196x196.png" sizes="196x196" />

<!-- various other "msapplication" related lines -->
<meta name="msapplication-TileColor" content="#FFA500" />
<meta name="msapplication-TileImage" content="https://aviitala.com/images/mstile-144x144.png" />

<!-- load the minimal service worker -->
<script defer>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js');
};
</script>

Testing the app Link to heading

To ensure things are working properly, Lighthouse is a great extension for Google Chrome to ‘audit’ your site for crucial PWA requirements.