Search by

Config-driven Drupal 11 PWA module: web app manifest, service worker, offline page and install hooks.

Package info

gitlab.com/Proton.Systems/drupal/pwa

Issues

Type:drupal-module

pkg:composer/protonsystems/pwa

Statistics

Installs: 3

Dependents: 0

Suggesters: 0

Stars: 0

v1.0.0 2026-10-06 11:31 UTC

This package is not auto-updated.

Last update: 2026-10-07 14:47:32 UTC


README

Reusable, config-driven Drupal 11 module that turns a site into a Progressive Web App: web app manifest, service worker with a privacy-safe offline strategy, a themeable offline page, and install/update hooks for the theme.

Purpose

The module is intended to be reused across Drupal 11 projects by installing it as a Composer package and enabling it in the target site. It replaces the per-project, dev-only hbk_pwa / uni_li_pwa modules: nothing is hardcoded to a project, everything is editable in the admin UI and exportable with config sync.

Requirements

  • Drupal 11.3+
  • PHP 8.3+
  • HTTPS in production (browsers only register service workers on HTTPS or localhost)

Features

  • Language-aware manifest at /manifest.webmanifest (/de/manifest.webmanifest, ...), with lang/dir and translatable name/description
  • Service worker at /service-worker.js: network-first navigations, stale-while-revalidate assets, per-language offline page, optional offline reading of visited pages, optional precached pages
  • Offline reading never stores logged-in users' pages (see Privacy model)
  • Kill switch: disabling the module's setting makes installed workers remove themselves and their caches
  • Every cache rebuild (drush cr, i.e. every deployment) rolls the client cache revision, so theme changes reach returning visitors
  • Install meta tags (theme color, Apple touch icon, standalone capability), manifest shortcuts, status report checks
  • Drupal.pwa JS API and pwa:* window events so a theme can build its own "Install app" button
  • Off by default; switch on per environment from settings.php

Structure

  • src/PwaManager.php, src/IconResolver.php, src/ManifestBuilder.php, src/ServiceWorkerBuilder.php contain the core logic.
  • src/Controller/ serves the manifest, the worker, and the offline page.
  • src/EventSubscriber/ flags which HTML responses the worker may cache.
  • src/Hook/ contains the OOP hook implementations (page attachments, theme, rebuild, status report).
  • src/Form/ contains the admin settings form.
  • js/ contains the worker (service-worker.js, service-worker-kill.js), the registration script, and the offline page behavior.
  • templates/ and css/ contain the offline page markup and default styling.
  • config/ contains shipped defaults and config schema.
  • docs/module-architecture.md documents how the module is built.

Installation

composer require protonsystems/pwa
drush en pwa

Configure at /admin/config/system/pwa (permission: administer pwa), then drush cex to keep the configuration in config/sync.

  1. Put square icons somewhere in the codebase or files directory (at least 192×192 and 512×512) and enter their locations on the Icons tab.
  2. Enable the PWA — either tick the box, or force it per environment:

    // settings.php (or settings.local.php)
    $config['pwa.settings']['enabled'] = TRUE;
    
  3. Check /admin/reports/status for "Progressive Web App" and "PWA: icons".

⚠️ Web server: /service-worker.js and /manifest.webmanifest are Drupal routes, not files. Make sure nginx/Apache pass them to index.php instead of answering 404 for a missing static .js file (the default Drupal vhost configs do).

Theme Integration

No theme changes are needed: the manifest link, meta tags, and registration script are attached to every non-admin page automatically.

Optional hooks for the theme:

// Needs "Defer the browser install prompt" enabled on the settings form.
window.addEventListener('pwa:installable', () => installButton.hidden = false);
installButton.addEventListener('click', () => Drupal.pwa.promptInstall());

window.addEventListener('pwa:updated', () => showToast('New version available'));

<html data-pwa-display="standalone"> is set when running as an installed app. To restyle the offline page, override pwa-offline.html.twig and disable css/pwa-offline.css with libraries-override.

See docs/module-architecture.md for the request flows, privacy model, configuration reference, and how to extend it.

Notes

  • Not supported (by design, for now): push notifications, background sync.
  • Before uninstalling the module, disable the PWA setting and let it run for a while — once the module is gone nothing can tell installed workers to remove themselves.