Install / beforeinstallpromptPWA install prompt
unknown
The browser fires a `beforeinstallprompt` event when the PWA is eligible. iOS controls "Add to Home Screen" via share sheet (manual).
// Example: listen for beforeinstallprompt
let deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
deferredPrompt = e;
// show your install UI
});
document.getElementById('btnPrompt').addEventListener('click', async () => {
if(deferredPrompt){ await deferredPrompt.prompt(); let res = await deferredPrompt.userChoice; console.log(res); }
});
Service Worker / Offline CachingRequires service-worker.js + HTTPS or localhost
sw: unknown
This demo can attempt to register a temporary worker. For full offline caching, download the provided service-worker.js and serve it from the same folder.
// Simplified service worker caching flow (service-worker.js)
self.addEventListener('install', event => {
event.waitUntil(caches.open('demo-v1').then(c => c.addAll(['/','/pwa-demo.html'])));
});
self.addEventListener('fetch', e => {
e.respondWith(caches.match(e.request).then(r => r || fetch(e.request)));
});
Storage: localStorage & IndexedDBPersistent storage
localStorage output
IndexedDB demo also included (small wrapper). Use it for larger structured storage.
// localStorage usage
localStorage.setItem('demoKey','demoValue');
let v = localStorage.getItem('demoKey');
Camera & MicrophonegetUserMedia
Camera / mic state
// getUserMedia
const stream = await navigator.mediaDevices.getUserMedia({video:true,audio:true});
video.srcObject = stream;
GeolocationOne-time location fetch
—
iOS shows a permission dialog. Background tracking while closed is not available in PWAs on iOS.
// Geolocation
navigator.geolocation.getCurrentPosition(pos => console.log(pos.coords));
Notifications & Push (explain)Permission + subscription
perm: ?
Server required for real push. On iOS Safari it uses APNs behind the scenes. Use the provided snippet to subscribe and send a test push from a server.
// client: subscribe (example)
const reg = await navigator.serviceWorker.ready;
const sub = await reg.pushManager.subscribe({userVisibleOnly:true,applicationServerKey: '...VAPID key...'});
// send `sub` to your server and call push via web-push / APNs.
Web Share / File Picker / Clipboardshare text/files
// Web Share
if(navigator.canShare) await navigator.share({title:'Hello',text:'Share from demo'});
Vibration / Haptics & Mediavibrate, media playback
// Vibration
navigator.vibrate([200,100,200]);
Bluetooth & WebUSB (notes)very limited on iOS
Most iOS builds restrict Web Bluetooth; Desktop Chrome gives best experience.
// Web Bluetooth (desktop Chromium)
// const dev = await navigator.bluetooth.requestDevice({filters:[{services:['battery_service']}]});
WebSocket test (echo)connect to public echo (if allowed)
disconnected
ws messages
// WebSocket simple
// const ws = new WebSocket('wss://echo.websocket.org/');
// ws.onmessage = e => console.log(e.data);