What is a Progressive Web App (PWA)?
A Progressive Web App (PWA) is a web application that provides an app-like experience by using modern web technologies. It combines the best features of both web and mobile apps.
Key Features of PWAs
- Progressive: Works on any browser and improves as newer technologies become available.
- Responsive: Adapts to all screen sizes, including mobile, tablet, and desktop.
- Offline Functionality: Uses service workers to cache content, allowing access without an internet connection.
- App-like Feel: Mimics the experience of a native app with smooth transitions and interactions.
- Installable: Can be added to the home screen and launched like a native app.
- Secure: Requires HTTPS to ensure a safe user experience.
Benefits of PWAs
- Faster Performance: PWAs load quickly and provide a smooth user experience.
- Lower Development Costs: One codebase serves both web and mobile users.
- Improved Engagement: Features like push notifications keep users returning.
- Cross-Platform Compatibility: Runs seamlessly across various devices and platforms.
Examples of PWAs
- Twitter Lite: Offers a fast, offline-capable experience.
- Pinterest: Enhanced user engagement through its PWA implementation.
- Uber: Lightweight app for quick bookings.
Highlights
Highlights of building a PWA for your Blogger site using this tutorial:
-
Automation
- Automatically updates and push changes to
bucket
andoutput
directory when changes are made inuploads
directory orpwa.config.ts
file using Github actions.
- Automatically updates and push changes to
-
Automatic Generation
- Automatically generates different size icons from single
favicon.png
and push it. - Automatically generates all the required files with a single config file
pwa.config.ts
and push it.
- Automatically generates different size icons from single
-
Any Blogger Site
- You can build PWA for your
blogspot.com
sites.
- You can build PWA for your
Requirements
- A Github account.
- Prepare an icon for your blog in
.png
extension with a minimum size of512x512
.
Rename the file asfavicon.png
. - Prepare few screenshots of your webpages in
.png
extension.- At least 3 screenshots for
narrow
screen devices of size540x720
. Name them in series:
screenshot-narrow-1.png
screenshot-narrow-2.png
screenshot-narrow-3.png
..and so on.. - At least 3 screenshots for
wide
screen devices of size720x540
. Name them in series:
screenshot-wide-1.png
screenshot-wide-2.png
screenshot-wide-3.png
..and so on..
- At least 3 screenshots for
Installing PWA
There are two ways of installing PWA:
- Using Cloudflare Workers: Supports Offline Page and OneSignal push notification integration.
- Using JsDelivr: Does not support Offline Page and OneSignal push notification integration.
If your DNS is not managed by Cloudflare or you are using blogspot.com
subdomain, you need to use the second method.
Follow the steps below based upon your choice.
Forking
If you want to use Cloudflare Workers, you can follow the following steps otherwise skip it:
-
Deploy the workers by clicking on the following button, this will fork this repository and deploy workers in your Cloudflare account for you:
- You need your Cloudflare Account ID and a Cloudflare API Token with
Edit Workers
permission. - You can find your Cloudflare Account ID by navigating to Workers Dashboard. It will be available in the right sidebar.
- You can create an Cloudflare API Token with
Edit Workers
permission by navigating to My Profile.
Click on Create Token.
UseEdit Cloudflare Workers
template. - Note that it will fork this repository in your Github account.
- You need your Cloudflare Account ID and a Cloudflare API Token with
-
After deploying the workers, we need to create a workers route.
-
Go to Websites section in Cloudflare Dashboard and select your domain.
-
Now go to Workers Routes section and then click on Add Route and input the fields as shown:
-
Routes:
www.your-domain.com/app/*
, make sure to use your domain and subdomain. -
Service: Select
blogger-pwa-kv
workers if you want to use Cloudflare KV,blogger-pwa-github
workers if you want to fetch assets from github repository (Repository must be public). -
Environment:
production
-
Routes:
If you don’t want to use Cloudflare Workers, then follow these steps:
- Fork this repository.
- Go to forked repository. Go to Actions tab.
- Enable workflows by clicking on I understand my workflows, go ahead and enable them.
Making Changes
Now whenever you commit any changes to the repository, this will redeploy your workers automatically and push updated files.
Uploading Favicon
- Go to the forked repository.
- Upload your
favicon.png
that you have created earlier inuploads
directory.
Uploading Screenshots
- Go to the forked repository.
- Upload your narrow screen preview screenshots of size
540x720
inuploads/screenshots/narrow
directory. - Upload your wide screen preview screenshots of size
720x540
inuploads/screenshots/wide
directory.
Configuring App
You can now configure your PWA by making changes in pwa.config.ts
file.
import type { Config } from './types';
export default {
version: '1.0',
id: '/',
name: 'My Blog',
shortName: 'My Blog',
description: 'My blog description goes here...',
direction: 'auto',
language: 'en-US',
backgroundColor: '#fff',
themeColor: '#fff',
display: 'standalone',
orientation: 'any',
scope: '/',
startUrl: '/?utm_source=homescreen',
appleStatusBarStyle: 'black-translucent',
preferRelatedApplications: false,
shortcuts: [
{
name: 'Shortcut 1',
shortName: 'Shortcut 1',
description: 'Shortcut 1 description goes here...',
url: '/search/label/shortcut-1?utm_source=homescreen',
},
{
name: 'Shortcut 2',
shortName: 'Shortcut 2',
description: 'Shortcut 2 description goes here...',
url: '/search/label/shortcut-2?utm_source=homescreen',
},
],
pwa: {
logs: true,
// OneSignal is not available if you are not using cloudflare workers
oneSignalEnabled: false,
oneSignalConfig: {
appId: '********-****-****-****-************',
allowLocalhostAsSecureOrigin: true,
},
},
// Please replace with your blog url if you are using CDN (JsDelivr)
origin: 'https://hello-example.blogspot.com',
} satisfies Config;
Description:
key | type | default value | required | description |
---|---|---|---|---|
version |
string |
'1.0' |
yes | Version of your app |
id |
string |
'/' |
no | Id of your app |
name |
string |
'My App' |
yes | Name of your app (Blog name) |
shortName |
string |
'My App Short Name' |
yes | Short name of your app |
description |
string |
'My App description' |
yes | Description of your app |
direction |
'auto' | 'ltr' | 'rtl' |
'auto' |
no | Direction of your app |
language |
string |
'en-US' |
no | Language of your app |
backgroundColor |
string |
'#fff' |
no | HEX background color of the app |
themeColor |
string |
'#fff' |
no | HEX theme color of the app |
display |
'fullscreen' | 'standalone' | 'minimal-ui' | 'browser' |
'standalone' |
no | Display mode of the app |
orientation |
'any' | 'natural' | 'portrait' | 'landscape' |
'any' |
no | Orientation of the app |
scope |
string |
'/' |
no | Scope of the app |
startUrl |
string |
'/' |
no | Url to open when app is launched |
appleStatusBarStyle |
'black-translucent' | 'default' | 'black' |
'black-translucent' |
no | Content of apple-mobile-web-app-status-bar-style meta tag |
preferRelatedApplications |
boolean |
false |
no | Prefer related application or not? |
shortcuts |
Array<{ name: string, shortName: string, description: string, url: string }> |
[] |
no | List of all shortcuts of the app |
origin |
string |
undefined |
no | The origin of your blog (required when using CDN) |
OneSignal Integration
If you are using Cloudflare Workers, you can integrate OneSignal push notification. Follow the given steps:
[!WARNING] Not applicable for AMP templates since it uses OneSignal JavaScript SDK.
- Go to OneSignal Dashboard.
- Go to your existing Web App or Create a new App using their Documentation.
- Go to the App settings.
- Select Typical Site in Choose Integration Settings.
- Toggle On Service Workers in Advance Push Settings.
- Input the fields as given below:
-
Path to service worker files:
/app/
-
Main service worker filename:
onesignalworker.js
-
Updater service worker filename:
onesignalworker.js
-
Service worker registration scope:
/app/onesignal/
-
Path to service worker files:
- Find App’s
App Id
and note it down. - Add your
App Id
inpwa.config.ts
file and commit the changes. - Also set
oneSignalEnabled
totrue
.
[!WARNING] Do not add any code provided by OneSignal in the Template XML because I have already added it as per requirement in
pwa.js
.
Edit Blogger Theme XML
After making all the above changes, workflows will run and it will commit new changes with a message update: generated bucket and output
, please wait for all the jobs to complete.
Now, it’s time to edit your blogger theme XML and add required codes.
- Go Blogger Dashboard. Go to Theme section.
- Click on Edit HTML.
Add the codes specified in next steps.
Add Meta Tags
- Find the following file in your forked repository based on conditions:
- If you are using Cloudflare workers:
output/pwa-metatags.html
or
output/pwa-metatags-no-splash.html
- If you are not using Cloudflare workers:
output/cdn-metatags.html
or
output/cdn-metatags-no-splash.html
- If you are using Cloudflare workers:
- Copy all the contents of above file based on your selection and paste it below
<head>
, if you didn’t find it, it would have been probably parsed which is<head>
. - Delete existing similar codes.
AMP Template
Follow these steps only if you are using an AMP template and Cloudflare Workers otherwise skip it.
-
Add the following code just below the meta tags you have added in previous steps:
<script async='async' custom-element='amp-install-serviceworker' src='https://cdn.ampproject.org/v0/amp-install-serviceworker-0.1.js'/>
-
Paste the following codes above to
</body>
:<amp-install-serviceworker data-iframe-src='/app/fallback/' layout='nodisplay' src='/app/serviceworker.js'/>
Non-AMP Template
Follow these steps only if you are using a Non-AMP template and Cloudflare Workers otherwise skip it.
-
Add the following code just below the meta tags you have added in previous steps:
<!--[ Start: Progressive Web App Script ]--> <script async='' defer='' type='module' src='/app/pwa.js'></script> <!--[ End: Progressive Web App Script ]-->
Save changes, and visit your blog!
Custom Install Button (Optional)
You may want to add a custom button on your site which shows the installation prompt on click. You can use the following css and javascript codes to create a beautiful install button.
[!WARNING] You should not use it if you are using an AMP template.
-
Add the following css in Template XML just above to
</head>
:<style>/*<![CDATA[*/ /*! Custom PWA install button by Fineshop Design */ .pwa-button{position:fixed;z-index:999;left:20px;bottom:75px;display:flex;align-items:center;justify-content:center;width:40px;height:40px;border:none;border-radius:50%;background:#1900ff;visibility:visible;opacity:1;transition:visibility .5s,opacity .5s} .pwa-button[hidden]{display:flex;visibility:hidden;opacity:0} .pwa-button:not([disabled])::before{content:'';position:absolute;z-index:-1;inset:0;background:inherit;border-radius:inherit;animation:1s cubic-bezier(0,0,.2,1) infinite pwa-button-ping} .pwa-button svg.flash{width:22px;height:22px;fill:none;stroke:#fff;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.4} @keyframes pwa-button-ping{75%,to{transform:scale(1.6);opacity:0}} /*]]>*/</style>
-
Add the following javascript just above to
</body>
:<script type='module'>/*<![CDATA[*/ /*! Custom PWA install button by Fineshop Design */ (({button:t,onInstall:n})=>{let i=null;var e=()=>{i&&(t.disabled=!0,i.prompt().then(e=>{"accepted"===e.outcome&&o()}).finally(()=>{t.disabled=!1}),i=null)},l=e=>{e.preventDefault(),i=e,t.hidden=!1};const o=()=>{t.hidden=!0,t.removeEventListener("click",e),window.removeEventListener("beforeinstallprompt",l)};t instanceof HTMLElement&&(t.hidden=!0,t.addEventListener("click",e),window.addEventListener("beforeinstallprompt",l));const d=e=>{t instanceof HTMLElement&&o(),"function"==typeof n&&n(e),window.removeEventListener("appinstalled",d)};window.addEventListener("appinstalled",d)})({ button: document.getElementById("app_install_button")||Object.assign(document.body.appendChild(document.createElement("button")),{hidden:!0,type:"button",className:"pwa-button",innerHTML:"<svg class='flash' viewBox='0 0 24 24'><path d='M6.08998 13.28H9.17998V20.48C9.17998 22.16 10.09 22.5 11.2 21.24L18.77 12.64C19.7 11.59 19.31 10.72 17.9 10.72H14.81V3.52002C14.81 1.84002 13.9 1.50002 12.79 2.76002L5.21998 11.36C4.29998 12.42 4.68998 13.28 6.08998 13.28Z' stroke-miterlimit='10'></path></svg>"}), onInstall(){ /** * Do something on app installed * i.e. Display a Thank You message in UI */ } }); /*]]>*/</script>
-
Save the changes, now an install button will appear on your site.
Purging Cache
If you are using JsDeliver then you may need to purge cache.
JsDelivr caches files on their server so if you update any file on GitHub, it will not be updated on the server instantly.
In that case you manually need to tell JsDelivr to purge cache. You can use this JsDelivr’s Purge Cache Tool to do so.
Caveats
If you are not using Cloudflare Workers, following features will not be available since it requires resources from same origin:
-
Offline Page: The app will show default interface of the web view when user is not connected to internet.
- It is because it needs Server Worker (which cannot be registered from different origin).
-
Push Notification: You cannot use third party Push Notification services (i.e. OneSignal) to send push notifications from same domain of the app.
- Push notifications are possible with Service Worker.
Conclusion
⭐ Star this repository if you find it useful and working method.
🐞 If you are facing any problem, feel free to open an issue.
License
This project is licensed under MIT License.