Follow Us On Google News. Follow Now!

How to build a Progressive Web App (PWA) for Blogger

Create a Progressive Web App for your blogger website to easily improve your visitors' experience.
Hello Blogmate's How are you ? I hope you are doing great. Most of you somehow will have experienced Add To Home Screen" prompt? on many Websites. It's Nothing But Just PWA.

In this article, I will guide you to easily create a PWA (Progressive Web Application) for your website. So, before you start setting up PWA for your website, you need to know what PWA is  and why it is important for your website.

What are Progressive Web App's  (PWA's)

Progressive Web Apps (PWAs) are web apps that use service workers, manifests, and other web platform capabilities in combination with progressive improvements to provide users with an experience comparable to native apps.

Progressive Web Apps, a fusion between website and mobile app functionality, are one of the best ways to do this. The main advantages they offer are their speed, the ability to work offline and access directly from the browser. Users can add them to their mobile home screen as a typical native app, bypassing app markets and saving valuable storage space, especially on low-end devices. Users are now more likely to try a PWA as they have become quite reluctant to download new apps in the past few years.They treat their mobile devices like cameras, computers, notepads, assistants and most importantly like a treasure trove of memories. If downloading an app means sacrificing valuable photos or messages, think thrice before hitting yes.

Progressive web apps don't force users to make such difficult decisions as they are much lighter than native apps. Also, users don't see the typical installation process. You click a special button and a shortcut is created on the home screen. Of course, PWAs also "steal" some fun with downloaded content

Features – PWA's

  • Progressive – Regardless of the browser, the app works for different users as it is developed with progressive improvements.
  • Responsive: Seamless performance across all devices, whether desktop, mobile, tablet or the next.
  • Standalone Connectivity: Works both offline and on low-quality networks with advanced service workers.
  • App-like: Provides app-like features that separate functionality from app content. Fresh: Always up to date thanks to the service worker update process.
  • Secure: HTTPS to ensure best security practices.
  • Visible - Search engines can find applications because they are identifiable as an "application" based on the W3C Manifesto and Service Worker Registry.
  • It allows users to add apps they find most useful to their home screen without the hassle of an app store. 
  • Linkable: Just share the app by URL, no complex installation needed.

Why PWA's

PWAs increase the speed of development, reduce costs and even simplify the user experience. They offer a better mobile experience with easier access to data sources and the ability to create content as a single-purpose app.

Requirements For PWA

  1. Favicons  in .png extension with a size of 512px × 512px .
  2. 5 Screenshots of your Web Pages in .png extension.
  3. GitHub Repository.
  4. Cloudflare Connected To Your Website. 

Prepare Icons

  1. First, create your favicon in 512px × 512px size in PNG format.
  2. Open Favicon Generator Tool.
  3. After clicking on choose file select your favicon png image. 
  4. Click on Create Favicon.
  5. Once Favicon is generated , Click on “Download Generated Favicon”.
  6. Extract the downloaded file
  7. Delete unnecessary files like: browserconfig.xml & manifest.json
  8. Create Repository On GitHub i.e icon-thetaluat
  9. Upload All Created Favicon Files.
  10. Then Click on Commit File.

Upload the original file as well, i.e. android-icon-512x512.png.Total number of icons will be approximately 26.

Uploading Screenshots

Prepare 5 screenshots of your Web Pages in .png extension , those appears when install button appears for PWA installation.

Name the screenshots in series:

  • scr1.png
  • scr2.png
  • scr3.png
  • scr4.png
  • scr5.png
Upload those screenshots withinside the main-branch of the identical GitHub Repository.
  • Login Your Blogger Account.
  • Then Click on Theme Menu > Edit Html. then Put the Below Code Under <head> Tag.

    Replace All The Fields Containing The Taluat & The Taluat blog as per your requirement

    Double CLick To Copy Code

    <meta content='#6200ee' name='theme-color' />
    <meta content='#6200ee' name='msapplication-navbutton-color' />
    <meta content='#6200ee' name='apple-mobile-web-app-status-bar-style' />
    <meta content='true' name='apple-mobile-web-app-capable' />
    <link href="/favicon.ico" rel='icon' type='image/x-icon' />
    <link href="/favicon.ico" rel='shortcut icon' type='image/x-icon' />
    <link href="/main/apple-icon-57x57.png" rel='apple-touch-icon' sizes='57x57' />
    <link href="/main/apple-icon-60x60.png" rel='apple-touch-icon' sizes='60x60' />
    <link href="/main/apple-icon-72x72.png" rel='apple-touch-icon' sizes='72x72' />
    <link href="/main/apple-icon-76x76.png" rel='apple-touch-icon' sizes='76x76' />
    <link href="/main/apple-icon-114x114.png" rel='apple-touch-icon' sizes='114x114' />
    <link href="/main/apple-icon-120x120.png" rel='apple-touch-icon' sizes='120x120' />
    <link href="/main/apple-icon-114x114.png" rel='apple-touch-icon' sizes='144x144' />
    <link href="/main/apple-icon-152x152.png" rel='apple-touch-icon' sizes='152x152' />
    <link href="/main/apple-icon-180x180.png" rel='apple-touch-icon' sizes='180x180' />
    <link href="/main/android-icon-192x192.png" rel='icon' sizes='192x192' type='image/png' />
    <link href="/main/favicon-32x32.png" rel='icon' sizes='32x32' type='image/png' />
    <link href="/main/favicon-96x96.png" rel='icon' sizes='96x96' type='image/png' />
    <link href="/main/favicon-16x16.png" rel='icon' sizes='16x16' type='image/png' />
    <meta content='#007fa0' name='msapplication-TileColor' />
    <meta content='/main/ms-icon-144x144.png' name='msapplication-TileImage' />
    <link href="/manifest.json" rel='manifest' />
    

    Creating Workers in Cloudflare

    • Sign in to your Cloudflare account.
    • Go to the Workers section and click Manage Workers.
    • Click on Create Service and add name to it as mentioned below  
    • Create 4 New Services
    Route Service Environment
    www.thetaluat.xyz/main/* main-worker production
    www.thetaluat.xyz/manifest.json manifest-worker production
    www.thetaluat.xyz/sw.js service-worker production
    www.thetaluat.xyz/offline.html offline-worker production
    • Delete the existing script and replace it with the following script:
    addEventListener("fetch", event => {
      event.respondWith(handleRequest(event))
    })
    
    //const BUCKET_NAME = "main"
    const BUCKET_URL = `https://cdn.statically.io/gh/thetaluat/icon-test`
    
    async function serveAsset(event) {
      const url = new URL(event.request.url)
      const cache = caches.default
      let response = await cache.match(event.request)
    
      if (!response) {
        response = await fetch(`${BUCKET_URL}${url.pathname}`)
        const headers = { "cache-control": "public, max-age=14400" }
        response = new Response(response.body, { ...response, headers })
        event.waitUntil(cache.put(event.request, response.clone()))
      }
      return response
    }
    
    async function handleRequest(event) {
      if (event.request.method === "GET") {
        let response = await serveAsset(event)
        if (response.status > 399) {
          response = new Response(response.statusText, { status: response.status })
        }
        return response
      } else {
        return new Response("Method not allowed", { status: 405 })
      }
    }
    
    addEventListener("fetch", event => {
      const data = {
        name: "The Taluat ",
        short_name: "The Taluat ",
        description: "Install Now The Taluat  - Let's fuel creativity",
        display: "standalone",
        prefer_related_applications: false,
        start_url: "\/?utm_source=homescreen",
        scope: "\/",
        background_color: "#2196f3",
        theme_color: "#2196f3",
        icons: [
          {
          src: "\/main\/android-icon-512x512.png",
          sizes: "512x512",
          type: "image\/png",
          density: "4.0",
          purpose: "any maskable"
          },
          {
          src: "\/main\/android-icon-192x192.png",
          sizes: "192x192",
          type: "image\/png",
          density: "4.0",
          purpose: "any maskable"
          },
          {
          src: "\/main\/apple-icon-144x144.png",
          sizes: "144x144",
          type: "image\/png",
          density: "3.0",
          purpose: "any maskable"
          },
          {
          src: "\/main\/android-icon-96x96.png",
          sizes: "96x96",
          type: "image\/png",
          density: "2.0",
          purpose: "any maskable"
          },
          {
          src: "\/main\/android-icon-72x72.png",
          sizes: "72x72",
          type: "image\/png",
          density: "1.5",
          purpose: "any maskable"
          },
          {
          src: "\/main\/android-icon-48x48.png",
          sizes: "48x48",
          type: "image\/png",
          density: "1.0",
          purpose: "any maskable"
          },
          {
          src: "\/main\/android-icon-36x36.png",
          sizes: "36x36",
          type: "image\/png",
          density: "0.75",
          purpose: "any maskable"
          }
        ],
        shortcuts: [
          {
          name: "The Taluat ",
          short_name: "The Taluat ",
          description: "The Best Website where you can find Blogger Widgets, Tech News, Tech Reviews, Coding related Tutorials and many more.",
          url: "\/?utm_source=homescreen",
          icons: [
              {
              src: "\/main\/android-icon-192x192.png",
              sizes: "192x192"
              }
            ]
          },
          {
          name: "The Taluat  - Blog",
          short_name: "The Taluat  - Blog",
          description: "Explore The Taluat  Blog.",
          url: "\/search?utm_source=homescreen",
          icons: [
              {
              src: "\/main\/android-icon-192x192.png",
              sizes: "192x192"
              }
            ]
          },
          {
          name: "Blogger Widgets",
          short_name: "Blogger Widgets",
          description: "Useful Widgets for your Blog.",
          url: "\/search\/label\/Widgets?utm_source=homescreen",
          icons: [
              {
              src: "\/main\/android-icon-192x192.png",
              sizes: "192x192"
              }
            ]
          }
        ],
        screenshots: [
          {
          src: "\/main\/scr1.png",
          type: "image\/png",
          sizes: "540x720"
          },
          {
          src: "\/main\/scr2.png",
          type: "image\/png",
          sizes: "540x720"
          },
          {
          src: "\/main\/scr3.png",
          type: "image\/png",
          sizes: "540x720"
          },
          {
          src: "\/main\/scr4.png",
          type: "image\/png",
          sizes: "540x720"
          },
          {
          src: "\/main\/scr5.png",
          type: "image\/png",
          sizes: "540x720"
          }
        ],
        serviceworker: {
          src: "\/sw.js"
        }
      }
    
      const json = JSON.stringify(data, null, 2)
    
      return event.respondWith(
        new Response(json, {
          headers: {
            "content-type": "application/json;charset=UTF-8"
          }
        })
      )
    })
    
    const js = `
    importScripts('https://storage.googleapis.com/workbox-cdn/releases/5.1.2/workbox-sw.js');
    if (workbox) {
    workbox.core.skipWaiting();
    workbox.core.clientsClaim();
    workbox.core.setCacheNameDetails({
      prefix: 'thn-sw',
      suffix: 'v22',
      precache: 'install-time',
      runtime: 'run-time'
    });
    
    const FALLBACK_HTML_URL = '/offline.html';
    const version = workbox.core.cacheNames.suffix;
    workbox.precaching.precacheAndRoute([{url: FALLBACK_HTML_URL, revision: null},{url: '/manifest.json', revision: null},{url: '/main/favicon.ico', revision: null}]);
    
    workbox.routing.setDefaultHandler(new workbox.strategies.NetworkOnly());
    
    workbox.routing.registerRoute(
        new RegExp('.(?:css|js|png|gif|jpg|svg|ico)$'),
        new workbox.strategies.CacheFirst({
            cacheName: 'images-js-css-' + version,
            plugins: [
                new workbox.expiration.ExpirationPlugin({
                    maxAgeSeconds: 60 * 24 * 60 * 60,
                    maxEntries:200,
                    purgeOnQuotaError: true
                })
            ],
        }),'GET'
    );
    
    workbox.routing.setCatchHandler(({event}) => {
          switch (event.request.destination) {
            case 'document':
            return caches.match(FALLBACK_HTML_URL);
          break;
          default:
            return Response.error();
      }
    });
    
    self.addEventListener('activate', function(event) {
      event.waitUntil(
        caches
          .keys()
          .then(keys => keys.filter(key => !key.endsWith(version)))
          .then(keys => Promise.all(keys.map(key => caches.delete(key))))
      );
    });
    
    }
    else {
        console.log('Oops! Workbox did not load');
    }
    `
    
    async function handleRequest(request) {
      return new Response(js, {
        headers: {
          "content-type": "application/javascript;charset=UTF-8",
        },
      })
    }
    
    addEventListener("fetch", event => {
      return event.respondWith(handleRequest(event.request))
    })
    
    const html = `<!DOCTYPE html>
    <html>
    
    <head>
      <!--[ Meta Tags ]-->
      <title>Oops, You're Offline!</title>
      <meta charset='UTF-8'/>
      <meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0' name='viewport'/>
      <meta content='IE=edge' http-equiv='X-UA-Compatible'/>
    
      <!--[ Theme Color ]-->
      <meta content='#2196f3' name='theme-color'/>
      <meta content='#2196f3' name='msapplication-navbutton-color'/>
      <meta content='#2196f3' name='apple-mobile-web-app-status-bar-style'/>
      <meta content='true' name='apple-mobile-web-app-capable'/>
    
      <!--[ Favicon ]-->
      <link href='/main/apple-icon-120x120.png' rel='apple-touch-icon' sizes='120x120'/>
      <link href='/main/apple-icon-152x152.png' rel='apple-touch-icon' sizes='152x152'/>
      <link href='/main/favicon-32x32.png' rel='icon' sizes='32x32' type='image/png'/>
      <link href='/main/favicon-96x96.png' rel='icon' sizes='96x96' type='image/png'/>
      <link href='/main/favicon-16x16.png' rel='icon' sizes='16x16' type='image/png'/>
      <link href='/main/favicon.ico' rel='icon' type='image/x-icon'/>
      <link href='/main/favicon.ico' rel='shortcut icon' type='image/x-icon'/>
    
      <!--[ Stylesheet ]-->
      <style>/*<![CDATA[*/
    /* Merriweather - Font */ @font-face{font-family: 'Merriweather'; font-style: italic; font-weight: 300; font-display: swap; src: local('Merriweather-LightItalic'), url(https://fonts.gstatic.com/s/merriweather/v22/u-4l0qyriQwlOrhSvowK_l5-eR7lXff4jvw.woff2) format('woff2'), url(https://fonts.gstatic.com/s/merriweather/v22/u-4l0qyriQwlOrhSvowK_l5-eR7lXcf8.woff) format('woff')} @font-face{font-family: 'Merriweather'; font-style: italic; font-weight: 700; font-display: swap; src: url(https://fonts.gstatic.com/s/merriweather/v22/u-4l0qyriQwlOrhSvowK_l5-eR7NWPf4jvw.woff2) format('woff2'), url(https://fonts.gstatic.com/s/merriweather/v22/u-4l0qyriQwlOrhSvowK_l5-eR71Wsf8.woff) format('woff')} @font-face{font-family: 'Merriweather'; font-style: italic; font-weight: 900; font-display: swap; src: url(https://fonts.gstatic.com/s/merriweather/v22/u-4l0qyriQwlOrhSvowK_l5-eR7NWPf4jvw.woff2) format('woff2'), url(https://fonts.gstatic.com/s/merriweather/v22/u-4l0qyriQwlOrhSvowK_l5-eR7NWMf8.woff) format('woff')} @font-face{font-family: 'Merriweather'; font-style: normal; font-weight: 300; font-display: swap; src: url(https://fonts.gstatic.com/s/merriweather/v22/u-4n0qyriQwlOrhSvowK_l521wRZWMf6.woff2) format('woff2'), url(https://fonts.gstatic.com/s/merriweather/v22/u-4n0qyriQwlOrhSvowK_l521wRpXA.woff) format('woff')} @font-face{font-family: 'Merriweather'; font-style: normal; font-weight: 700; font-display: swap; src: url(https://fonts.gstatic.com/s/merriweather/v22/u-4n0qyriQwlOrhSvowK_l52xwNZWMf6.woff2) format('woff2'), url(https://fonts.gstatic.com/s/merriweather/v22/u-4n0qyriQwlOrhSvowK_l52xwNpXA.woff) format('woff')} @font-face{font-family: 'Merriweather'; font-style: normal; font-weight: 900; font-display: swap; src: url(https://fonts.gstatic.com/s/merriweather/v22/u-4n0qyriQwlOrhSvowK_l52_wFZWMf6.woff2) format('woff2'), url(https://fonts.gstatic.com/s/merriweather/v22/u-4n0qyriQwlOrhSvowK_l52_wFpXA.woff) format('woff')}
    /* Content */ body{background:#f1f3f6;color:#1f1f1f;font-family:'Merriweather',serif;font-weight:400;-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body:focus{outline:none !important} .mainCont{margin:0 auto;position:fixed;left:0;top:0;right:0;bottom:0;display:flex;align-items:center;justify-content:center;padding:15px} .noIntPop{position:relative;overflow:hidden;text-align:center;padding:15px;border-radius:30px;background:#f1f3f6;box-shadow:inset 0 0 15px rgba(55, 84, 170, 0), inset 0 0 20px rgba(255, 255, 255, 0), 7px 7px 15px rgba(55, 84, 170, 0.15), -7px -7px 20px white, inset 0px 0px 4px rgba(255, 255, 255, 0.2)} .circle.t{top:-150px;right:-150px} .circle.b{bottom:-150px;left:-150px} .noIntCont{position:relative;z-index:1} .noIntIcon{padding:30px} .noConHead{font-weight:700;font-size:1.3rem} .noConDesc{font-size:16px;line-height:1.4em;padding-top:20px;font-weight:400;opacity:.8} .cta,.relCont{display:flex;justify-content:center;align-items:center} .relCont{padding:30px} .cta{width:66px;height:66px;background:#f1f3f6;outline:none;border:none;border-radius:690px;box-shadow:inset 0 0 15px rgba(55, 84, 170, 0), inset 0 0 20px rgba(255, 255, 255, 0), 7px 7px 15px rgba(55, 84, 170, 0.15), -7px -7px 20px white, inset 0px 0px 4px rgba(255, 255, 255, 0.2);transition:box-shadow 399ms ease-in-out} .cta:hover{box-shadow:inset 7px 7px 15px rgba(55, 84, 170, 0.15), inset -7px -7px 20px white, 0px 0px 4px rgba(255, 255, 255, 0.2)} .icon{content:'';width:25px;height:25px;display:inline-block} .iconB{content:'';width:50px;height:50px;display:inline-block} .icon.reload{background:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239dabc0' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='23 4 23 10 17 10'/><path d='M20.49 15a9 9 0 1 1-2.12-9.36L23 10'/></svg>") center / 25px no-repeat} .iconB.wifiOff{background:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231f1f1f' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><line x1='1' y1='1' x2='23' y2='23'/><path d='M16.72 11.06A10.94 10.94 0 0 1 19 12.55'/><path d='M5 12.55a10.94 10.94 0 0 1 5.17-2.39'/><path d='M10.71 5.05A16 16 0 0 1 22.58 9'/><path d='M1.42 9a15.91 15.91 0 0 1 4.7-2.88'/><path d='M8.53 16.11a6 6 0 0 1 6.95 0'/><line x1='12' y1='20' x2='12.01' y2='20'/></svg>") center / 50px no-repeat} .circle{position:absolute;z-index:1;width:280px;height:280px;border-radius:50%;background-color:#f1f3f6;box-shadow:inset 8px 8px 12px #d1d9e6, inset -8px -8px 12px #f9f9f9}
      /*]]>*/</style>
    </head>
    
    <body>
      <div class='mainCont notranslate'>
        <div class='noIntPop'>
          <div class='circle t'></div>
          <div class='circle b'></div>
          <div class='noIntCont'>
            <div class='noIntIcon'>
              <i class='iconB wifiOff'></i>
            </div>
            <div class='noConHead'>Oops, You're Offline!</div>
            <div class='noConDesc'>It looks like your network connection isn't working right now.</div>
    
            <div class='relCont'>
              <button class='cta' onclick='window.location.reload()'>
                <i class='icon reload'></i>
              </button>
            </div>
          </div>
        </div>
      </div>
    </body>
    
    </html>`
    
    async function handleRequest(request) {
      return new Response(html, {
        headers: {
          "content-type": "text/html;charset=UTF-8",
        },
      })
    }
    
    addEventListener("fetch", event => {
      return event.respondWith(handleRequest(event.request))
    })
    
    • Add the following Javascript code above to </body>
    <script type='text/javascript'>
      //<![CDATA[
    if('serviceWorker' in navigator) {
      navigator.serviceWorker
               .register('/sw.js')
               .then(function() { console.log("Service Worker Registered"); });
    }
    //]]>
    </script>

    Conclusion

    So today we have discussed about How to Migrate Your Blog From WordPress to Blogger . I hope you like this post kindly do give a comment below. If you are having problem in implementing this kindly contact me. Do visit regularly for getting more updates like this.
  • Post a Comment

    Leave your opinion or any doubt about this article. Don't try to spam, our team reviews every comment.
    Created By

    M Taluat .xyz

    All Posts are Protected By DMCA.
    Reproduction in Any Form is Strictly Prohibited!

    Developed by M Taluat