Tutorial Chat Web App Client (PWA) Demonstrating Advanced Web APIs (WebSockets, Service Workers, Web Push, and IndexedDB)

Last updated on 7 July 2026

Quick Info

Live Demo: Tutorial Chat Web App (PWA) ↗ (Deployed on free tier Netlify)


Contents


Introduction

This tutorial chat app demonstrates how to build resilient real-time communication web clients using Advanced Web APIs (WebSockets, Service Workers, Web Push and IndexedDB). It is designed as a responsive Progressive Web App (PWA) that functions on desktop and mobile devices.

Core Features:

  • Stateful WebSockets: Instead of short-lived HTTP requests, uses WebSockets for long-lived, bidirectional communication, while gracefully managing lifecycle events like offline drops, network restorations, and server outages.
  • App Shell Caching: Using a Service Worker with a Network-First/Cache-Fallback strategy for offline app loading (App UI is shown to user even when offline).
  • IndexedDB Message Queueing: Acting as a reliable, offline-capable write-ahead log and persistent chat history store.
  • Foreground Sync: Automatically sending pending client messages to the server when the open application regains connectivity with the server (using WebSocket auto reconnect with exponential backoff).
  • Background Sync: Sending pending client messages when the network returns, even if the application has been closed by the user.
  • Web Push Notifications: Subscribing to push notifications on user request and handling server push notification responses.
  • Cloud Deployment Workarounds: Overcoming real-world hosting quirks, such as server cold starts, ephemeral disk wipes, load balancer proxy masking, and delayed socket closures.

To maximize educational value, this client is coded in plain JavaScript and avoids heavy abstractions like Socket.IO or Google Workbox, as well as UI frameworks like React. It interacts directly with raw browser APIs, with the single exception of the lightweight idb library (used strictly to enable modern async/await syntax for IndexedDB). This "zero-magic" approach exposes the exact underlying mechanics of modern web capabilities.

All Advanced Web APIs used in this app are documented as fully supported by Chromium-based browsers (like Chrome and Edge), and the app has been validated using Google Chrome on Windows 11 desktop PC and Android 12 mobile (Samsung M21). With the exception of the Background Sync API, all other Advanced Web APIs used by the app are documented as being fully supported by other major browsers like Firefox and Safari.

The Vite build tool is used only for environment variable support and JavaScript minification.

The backend is an intentionally minimal "delayed echo server" developed using node.js and libraries like express and ws. Its sole purpose is to easily test the above client's features. With a server-side artificial 5 seconds delay, the app does not show real-time communication. But if the artificial delay of 5 seconds is removed then the client-server send and receive messages are in real-time. So the programming part of the client is as needed for real-time communication with a server over WebSockets.


Instructions To Test Offline, Background, And Push Features Of App

Before getting into testing instructions, given below are small sections on ways to use/install the app on mobile and desktop.

Using/Installing App On Mobile

You may use the app on your mobile in two main ways:

  1. Install the app on your mobile device as a full screen standalone PWA. This option is recommended if you want to use push notifications.

    Procedure to install app on Android mobile as standalone PWA

    1. In the browser app, open the application with an active internet connection.
    2. If you are shown an "Install App" prompt, accept it. If not, click the 'Add to home screen' menu item or equivalent in browser's menu. In the next popup, choose to install the app. Don't choose the create shortcut option. Wait for a minute or few minutes till you are shown a notification that the app has been installed.
    3. Close the browser tab in which you opened the app.
    4. Locate the installed app in your apps list and open it like you open other native Android apps. The app should show a splash screen and then a full screen UI (browser address bar will not be shown).

    This app has not been tested on iOS and so it is not known if it will install as a standalone PWA on iOS.

  2. Use the app in a regular tab in the browser. In this option, push notifications may be unreliable.

Using/Installing the App on Desktop

Note: In the context of this app, "Desktop" refers to both laptop and desktop computers. 

Similar to mobile devices, the app can be used on a desktop computer either within a standard browser tab or installed as a standalone application. However, unlike mobile operating systems, desktop environments generally process background push notifications reliably in both scenarios.

To install the application on a desktop (verified on Windows 11 using Google Chrome), open the app in a browser tab and locate the install icon at the far right of the address bar. Clicking this icon installs the application at the operating system level, allowing it to open in a dedicated, standalone window. On Windows 11, the installed application can then be pinned directly to the Start menu and the Taskbar for native-like access.

----------
Now let us look at testing instructions.

1. Testing Online Messaging and History Creation

This initial test verifies the core WebSocket communication and the automatic logging of messages into the local database.

  1. Open the application in a browser tab or open the installed PWA app, ensuring you have an active internet connection.
  2. Type a message into the chat input and press Enter or click Send.
  3. Observation: The message appears in the chat interface immediately.
  4. Wait for approximately 5 seconds.
  5. Observation: The uppercase echo response from the server appears in the chat. Both the outgoing message and the server's response are automatically saved to the local IndexedDB storage in the background.
  6. Observation: If this is the first time the app has been opened on a device, a successful open should install the service worker and load the pre-cache files in the application cache. It will also create the IndexedDB database and its object stores. In the Chrome browser on a desktop PC, these can be viewed in the DevTools -> Application panel by clicking the Service workers, IndexedDB, and Cache storage left sidebar items.

2. Testing Chat History Persistence (IndexedDB)

This test demonstrates that the application successfully retrieves previous chat sessions from local storage upon initialization, ensuring data is not lost between sessions.

  1. Ensure there are existing messages visible in the chat interface from the previous test.
  2. Completely close the application browser tab or PWA app.
  3. Reopen the application URL in a new browser tab or reopen the PWA app.
  4. Observation: The previously sent and received messages instantly populate the chat interface, confirming the successful retrieval of persistent history from IndexedDB.

3. Testing Offline App Shell Caching

This test verifies that the Service Worker successfully intercepts network requests and serves the application UI from the local cache when a network connection is unavailable.

  1. If the application has not been opened before on a device, then open the application in the browser and wait for a few minutes for the service worker and related installation to complete. You may also choose to install the application as a PWA app. For installation details, see the sections, "Using/Installing App On Mobile" and/or "Using/Installing the App on Desktop" given earlier in this post.
  2. Disconnect the device from the internet. This can be done on a mobile device by turning off mobile data or enabling Airplane Mode, and on a desktop PC by turning off WiFi adapter. (Chrome DevTools Offline setting has a quirk that interferes with some tests.)
  3. Observation:The connection status bar at the top of the app shows that you are offline.
  4. Refresh the browser tab or completely close and reopen the application URL. In case of PWA app, completely close and reopen the app.
  5. Observation: The application UI loads successfully and displays the chat interface as well as the chat messages history, despite the lack of internet connectivity.

4. Testing Foreground Sync

This test demonstrates the application's ability to queue messages in IndexedDB while offline and automatically transmit them over a re-established WebSocket connection once the network is restored, all while the application remains open.

  1. Ensure the application is open, then disconnect the device from the internet. How to disconnect Internet?
  2. Observation:The connection status bar at the top of the app shows that you are offline.
  3. Type a message into the chat input and press Enter or click Send.
  4. Observation: The message appears in the chat window immediately. It is safely stored in the local IndexedDB as a pending message.
  5. Reconnect the device to the internet.
  6. Observation: The application detects the network restoration, automatically reconnects to the server, and transmits the queued message. After the server's 5-second delay, the echoed uppercase response appears in the chat. At this point, the message is no longer viewed as a pending message in the local IndexedDB.

5. Testing Background Sync

This test confirms that the Background Sync API can wake up the Service Worker to process pending messages stored in IndexedDB even after the user has completely closed the application.

Note: Background Sync may not be supported in some browsers like Firefox and Safari. But it is supported by Chromium-based browsers like Chrome and Edge.
  1. Ensure the application is open, then disconnect the device from the internet. How to disconnect Internet?
  2. Observation:The connection status bar at the top of the app shows that you are offline.
  3. Type a message into the chat input and press Enter or click Send.
  4. Observation: The message appears in the chat window immediately. It is safely stored in the local IndexedDB as a pending message.
  5. Close the application tab or PWA app. On a mobile browser, close the browser entirely.
  6. Reconnect the device to the internet.
  7. Wait approximately 15 to 20 seconds to allow the operating system to fire the background sync event to the Service Worker and further processing by Service Worker till server response is received.
  8. Reopen the application in a browser tab or reopen the PWA app.
  9. Observation: The server's response is shown immediately in the chat history, proving that the pending message was resent to server and server's response was received and processed while the app was closed.

6A. Testing Web Push Notifications on Desktop PC

This test validates the Push API integration, VAPID key exchange, and the Service Worker's ability to receive and display system-level notifications when the application is not in focus. This works well on Windows 11 desktop PC.

  1. Open the application with an active internet connection.
  2. If not done earlier, click 'Enable Notifications' button in app. Choose 'Allow' or equivalent in the browser's native permission prompt. After some seconds, "Notifications enabled" message will be shown instead of that button.
  3. Type a message into the chat input and press Enter or click Send.
  4. Immediately (in less than 5 seconds) close the browser tab or the PWA app on your desktop.
  5. Observation: After the server's 5-second delay, a system-level push notification appears on the desktop PC containing the echoed uppercase message.
  6. Click or tap the push notification.
  7. Observation: The browser automatically opens the chat application or the PWA app is opened. The server's response is shown immediately in the chat history.

6B. Testing Web Push Notifications on Mobile

This is a variation of the desktop test in 6A, executed on a mobile device. Testing on Android highlights the critical importance of a complete PWA installation. When installed as a proper standalone PWA (which Android dynamically converts into a deeply integrated WebAPK), push notifications seem to arrive quite promptly and reliably though at times they do get delayed.

However, if the application is only added to the home screen instead of being installed, it results in a simple browser shortcut being added to home screen. In this case as well as in the case of application being used only in a browser tab, push notifications can be highly unreliable. They may be delayed by 10 to 15 minutes or completely suppressed.

  1. Ensure that the app is properly installed on your mobile device as a standalone PWA. For installation details, see the section, "Using/Installing App On Mobile" given earlier in this post.
  2. If not done earlier, tap 'Enable Notifications' button in app. Choose 'Allow' or equivalent in the browser's native permission prompt. After some seconds, "Notifications enabled" message will be shown instead of that button.
  3. Send a message in the chat interface.
  4. Immediately (in less than 5 seconds), close the application completely by swiping it away from the device's recent apps list. This ensures the app is not merely suspended in the background but fully closed.
  5. Observation: Because the application is installed as a proper PWA, a system-level push notification containing the echoed message should be delivered to the device after the server's 5-second delay. How the device shows the notification may depend on your settings.
  6. Access the push notification on your device and tap it.
  7. Observation: The operating system automatically launches the chat application. The server's response is shown immediately in the chat history.
  8. Edge Case Note: If a notification is somehow suppressed by the OS and the app is manually reopened, the app will notice the pending message and perform a Foreground Sync. The server response will be shown after around five seconds. If the delayed push notification arrives later and is processed, a duplicate server response will be shown in the app. Because this tutorial implementation does not use unique message IDs, this edge case of showing duplicate server responses is considered acceptable.

Limitations Of Tutorial App As Compared To Production App

1. Message Payload Structure: To simplify the application, plain text message payloads are used instead of structured JSON objects. Because messages lack unique identifiers (IDs), the client cannot perform message deduplication. This can occasionally result in duplicate server responses being displayed to the user.

2. Background Synchronization Constraints: Due to the lack of unique message IDs, background synchronization is not registered when a browser tab is closed with outstanding messages. This deliberate omission prevents race conditions that would otherwise cause duplicate responses to surface via concurrent push notifications and background sync events.

3. Connection Health Monitoring: The application does not implement a WebSocket heartbeat (ping/pong) mechanism. Consequently, an unreachable server may not be immediately detected. However, during testing, it was observed that attempting to send a message on a broken connection will force a timeout and detect the server outage within approximately 20 seconds.

4. Message Correlation and Queue Management: The absence of unique message IDs prevents the client from explicitly matching a server response to its originating user message. Consequently, the application relies on a First-In, First-Out (FIFO) approach to clear pending items from the outbox queue upon receiving a server update. This strategy introduces an inherent risk: if the server processes messages out of order or network latency causes responses to transpose, the client may inadvertently remove the incorrect pending message from its tracking state, leaving the truly unacknowledged message unresolved.


Author

Author: Ravi S. Iyer with assistance from Gemini 3.1 Pro
Date: 7 July 2026

Comments