npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cloudsignal/pwa-sdk

v2.1.3

Published

CloudSignal PWA SDK - Progressive Web App features with push notifications, JWT/HMAC authentication, installation management, device tracking, offline queue, wake lock, and notification analytics

Readme

CloudSignal PWA SDK

Progressive Web App SDK for CloudSignal platform with push notifications, installation management, comprehensive device tracking, offline resilience, and notification analytics.

Features

Core Features

  • PWA Installation - Automatic install prompt handling with iOS manual instructions
  • Push Notifications - Web Push Protocol with VAPID authentication
  • Device Detection - 35+ device/browser/OS detection fields
  • Heartbeat - Real-time online status tracking
  • Service Worker - Badge management, notification history, offline support
  • TypeScript - Full type definitions included

v1.2.0 Features

  • JWT Authentication - User-linked registrations via JWT tokens (Supabase, Firebase, Auth0, Clerk)
  • Dual Auth Mode - HMAC for anonymous users, JWT for authenticated users
  • Smart Notification Routing - Enable in-app vs web push based on user online status
  • Token Refresh - Automatic retry on 401 with onTokenExpired callback

v1.1.0 Features

  • Screen Wake Lock - Prevent screen sleep during critical operations
  • Offline Request Queue - IndexedDB-backed queue with auto-retry when online
  • iOS Install Banner - Beautiful modal guiding iOS Safari users to install
  • Network-Aware Heartbeat - Auto-adjusts based on connection quality (4G/3G/2G)
  • Battery-Aware Heartbeat - Pauses when battery <15% to save power
  • Notification Analytics - Track displayed/clicked/dismissed events

Installation

npm

npm install @cloudsignal/pwa-sdk

CDN

<!-- Latest version -->
<script src="https://cdn.cloudsignal.io/CloudSignalPWA.js"></script>

<!-- Specific version -->
<script src="https://cdn.cloudsignal.io/cloudsignal-pwa.v1.0.0.js"></script>

Quick Start

Basic Usage

import { CloudSignalPWA } from '@cloudsignal/pwa-sdk'

const pwa = new CloudSignalPWA({
  organizationId: 'your-org-uuid',
  organizationPublishableKey: 'pk_your_publishable_key',
  serviceId: 'your-service-uuid',
  debug: true
})

// Initialize (downloads config, registers service worker)
await pwa.initialize()

// Get device information
const deviceInfo = pwa.getDeviceInfo()
console.log('Device:', deviceInfo.deviceModel, deviceInfo.browser)

// Check installation state
if (pwa.canInstall()) {
  await pwa.showInstallPrompt()
}

// Register for push notifications
const registration = await pwa.registerForPush({
  userEmail: '[email protected]'
})

CDN Usage

<script src="https://cdn.cloudsignal.io/CloudSignalPWA.js"></script>
<script>
const pwa = new CloudSignalPWA.CloudSignalPWA({
  organizationId: 'your-org-uuid',
  organizationPublishableKey: 'pk_your_publishable_key',
  serviceId: 'your-service-uuid'
})

pwa.initialize().then(() => {
  console.log('PWA initialized')
})
</script>

JWT Authentication (v1.2.0)

For authenticated user registrations, use JWT instead of HMAC:

import { CloudSignalPWA } from '@cloudsignal/pwa-sdk'
import { supabase } from './supabase' // Your Supabase client

const pwa = new CloudSignalPWA({
  organizationId: 'your-org-uuid',
  userToken: (await supabase.auth.getSession()).data.session?.access_token,
  serviceId: 'your-service-uuid',
  onTokenExpired: async () => {
    // Refresh token when 401 received
    const { data } = await supabase.auth.refreshSession()
    return data.session?.access_token || ''
  }
})

await pwa.initialize()

// Registration will be linked to the authenticated user
const registration = await pwa.registerForPush()

Upgrading from Anonymous to Authenticated:

// Start with HMAC (anonymous)
const pwa = new CloudSignalPWA({
  organizationId: 'your-org-uuid',
  organizationPublishableKey: 'pk_your_publishable_key',
  serviceId: 'your-service-uuid'
})

await pwa.initialize()
await pwa.registerForPush() // Anonymous registration

// Later, when user logs in:
const userToken = await getUserJWT()
pwa.setUserToken(userToken)
await pwa.registerForPush() // Re-register with user identity

API Reference

Constructor

new CloudSignalPWA(config: PWAConfig)

Config Options:

| Option | Type | Required | Description | |--------|------|----------|-------------| | organizationId | string | Yes | CloudSignal organization UUID | | organizationPublishableKey | string | No* | Organization publishable key pk_* (HMAC mode) | | userToken | string | No* | JWT token from identity provider | | onTokenExpired | function | No | Callback to refresh JWT on 401 | | serviceId | string | Yes | PWA service UUID | | serviceUrl | string | No | Service URL (default: https://pwa.cloudsignal.app) | | debug | boolean | No | Enable debug logging | | serviceWorker | object | No | Service worker config | | heartbeat | object | No | Heartbeat config |

*Either organizationPublishableKey or userToken must be provided

Initialization

// Initialize the PWA client
await pwa.initialize(): Promise<InitializeResult>

// Download service configuration
await pwa.downloadConfig(): Promise<PWAServiceConfig | null>

Installation

// Show install prompt (Chrome/Edge)
await pwa.showInstallPrompt(): Promise<InstallResult>

// Check if PWA can be installed
pwa.canInstall(): boolean

// Check if PWA is already installed
pwa.isInstalled(): boolean

// Get installation state
pwa.getInstallationState(): InstallationState

// Get install steps for current platform
pwa.getInstallSteps(): string[]

Push Notifications

// Register for push notifications
await pwa.registerForPush(options?: RegisterOptions): Promise<Registration | null>

// Unregister from push notifications
await pwa.unregisterFromPush(): Promise<boolean>

// Update notification preferences
await pwa.updatePreferences(prefs: NotificationPreferences): Promise<boolean>

// Check registration status
await pwa.checkRegistrationStatus(): Promise<RegistrationStatusResponse | null>

// Request notification permission
await pwa.requestPermission(): Promise<NotificationPermission>

// Check if registered
pwa.isRegistered(): boolean

// Get registration ID
pwa.getRegistrationId(): string | null

Device Information

// Get comprehensive device info (35+ fields)
pwa.getDeviceInfo(): DeviceInfo

// Get PWA capabilities
pwa.getCapabilities(): PWACapabilities

Heartbeat

// Start heartbeat for online status tracking
pwa.startHeartbeat(): void

// Stop heartbeat
pwa.stopHeartbeat(): void

// Get current interval (may vary with network conditions)
pwa.getHeartbeatInterval(): number

// Get network connection info
pwa.getNetworkInfo(): NetworkConnectionInfo

// Get battery info (if available)
await pwa.getBatteryInfo(): Promise<BatteryInfo | null>

Authentication (v1.2.0)

// Get current authentication mode
pwa.getAuthMode(): 'hmac' | 'jwt'

// Set/upgrade JWT token (for authenticated users)
pwa.setUserToken(token: string): void
// After calling setUserToken, call registerForPush() again to link registration to user

Screen Wake Lock (v1.1.0)

// Request screen wake lock (prevents screen from sleeping)
await pwa.requestWakeLock(): Promise<boolean>

// Release wake lock
pwa.releaseWakeLock(): void

// Get current state
pwa.getWakeLockState(): WakeLockState
// Returns: { isSupported: boolean, isActive: boolean }

Offline Request Queue (v1.1.0)

// Queue a request for later (when offline)
await pwa.queueOfflineRequest(url, method, body?, headers?): Promise<string | null>

// Process queued requests
await pwa.processOfflineQueue(): Promise<QueueProcessResult>

// Get queue statistics
await pwa.getOfflineQueueStats(): Promise<OfflineQueueStats>

// Clear all queued requests
await pwa.clearOfflineQueue(): Promise<void>

iOS Install Banner (v1.1.0)

// Show iOS install guidance banner
pwa.showIOSInstallBanner(): void

// Hide banner
pwa.hideIOSInstallBanner(): void

// Check if previously dismissed
pwa.wasIOSBannerDismissed(): boolean

// Reset dismissal state
pwa.resetIOSBannerDismissal(): void

Badge Management

// Clear app badge
pwa.clearBadge(): void

// Set app badge count
pwa.setBadge(count: number): void

Events

// Subscribe to events
pwa.on(event: PWAEvent, handler: (data) => void): void

// Unsubscribe from events
pwa.off(event: PWAEvent, handler: (data) => void): void

Available Events:

| Event | Description | |-------|-------------| | install:available | Install prompt is available | | install:accepted | User accepted install | | install:dismissed | User dismissed install | | install:completed | PWA was installed | | push:registered | Push registration successful | | push:unregistered | Push unregistration successful | | push:error | Push operation failed | | permission:denied | Notification permission denied | | config:loaded | Service config downloaded | | config:error | Config download failed | | heartbeat:sent | Heartbeat sent successfully | | heartbeat:error | Heartbeat failed | | heartbeat:intervalChanged | Heartbeat interval adjusted (v1.1.0) | | heartbeat:pausedForBattery | Heartbeat paused due to low battery (v1.1.0) | | heartbeat:resumedFromBattery | Heartbeat resumed (v1.1.0) | | wakeLock:acquired | Screen wake lock acquired (v1.1.0) | | wakeLock:released | Screen wake lock released (v1.1.0) | | wakeLock:error | Wake lock operation failed (v1.1.0) | | offlineQueue:queued | Request added to offline queue (v1.1.0) | | offlineQueue:processed | Queued request processed (v1.1.0) | | offlineQueue:flushed | All queued requests processed (v1.1.0) | | iosBanner:shown | iOS install banner shown (v1.1.0) | | iosBanner:dismissed | iOS install banner dismissed (v1.1.0) | | iosBanner:installClicked | User clicked install on iOS banner (v1.1.0) | | auth:tokenUpdated | JWT token updated/upgraded (v1.2.0) | | network:online | Network came online | | network:offline | Network went offline | | sw:registered | Service worker registered | | sw:updated | Service worker updated |

Service Worker Setup

Copy the service worker to your app's root directory:

# If using npm
cp node_modules/@cloudsignal/pwa-sdk/dist/service-worker.js public/

Or download from CDN:

curl -o public/service-worker.js https://cdn.cloudsignal.io/service-worker.v1.0.0.js

PWA Manifest

Create a manifest.json in your app's root:

{
  "name": "Your App Name",
  "short_name": "App",
  "start_url": "/",
  "display": "standalone",
  "theme_color": "#000000",
  "background_color": "#ffffff",
  "icons": [
    {
      "src": "/icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}

Add to your HTML:

<link rel="manifest" href="/manifest.json">

Device Information

The SDK detects 35+ device attributes:

const info = pwa.getDeviceInfo()

// Operating System
info.os           // 'iOS', 'Android', 'Windows', 'macOS', 'Linux'
info.osVersion    // '17.2', '14.0', 'Windows 10/11'

// Device
info.deviceType   // 'iPhone', 'iPad', 'Phone', 'Tablet', 'Desktop'
info.deviceModel  // 'iPhone 15 Pro', 'Samsung Galaxy S24'
info.isMobile     // true/false
info.isTablet     // true/false
info.isDesktop    // true/false

// Browser
info.browser        // 'Chrome', 'Safari', 'Firefox', 'Edge'
info.browserVersion // '120.0.6099.43'

// PWA Capabilities
info.supportLevel          // 'full', 'partial', 'basic', 'none'
info.hasPushManager        // true/false
info.hasServiceWorker      // true/false
info.hasBadgeAPI           // true/false
info.notificationPermission // 'granted', 'denied', 'default'

// Network
info.isOnline        // true/false
info.connectionType  // '4g', '3g', '2g', 'unknown'

Example: React Integration

import { useEffect, useState } from 'react'
import { CloudSignalPWA } from '@cloudsignal/pwa-sdk'

const pwa = new CloudSignalPWA({
  organizationId: process.env.REACT_APP_ORG_ID,
  organizationPublishableKey: process.env.REACT_APP_CLOUDSIGNAL_PUBLISHABLE_KEY,
  serviceId: process.env.REACT_APP_SERVICE_ID
})

function App() {
  const [canInstall, setCanInstall] = useState(false)
  const [isRegistered, setIsRegistered] = useState(false)

  useEffect(() => {
    pwa.initialize().then(() => {
      setCanInstall(pwa.canInstall())
      setIsRegistered(pwa.isRegistered())
    })

    pwa.on('install:available', () => setCanInstall(true))
    pwa.on('push:registered', () => setIsRegistered(true))
  }, [])

  const handleInstall = async () => {
    const result = await pwa.showInstallPrompt()
    if (result.accepted) {
      setCanInstall(false)
    }
  }

  const handleEnableNotifications = async () => {
    const registration = await pwa.registerForPush({
      userEmail: '[email protected]'
    })
    if (registration) {
      setIsRegistered(true)
    }
  }

  return (
    <div>
      {canInstall && (
        <button onClick={handleInstall}>Install App</button>
      )}
      {!isRegistered && (
        <button onClick={handleEnableNotifications}>
          Enable Notifications
        </button>
      )}
    </div>
  )
}

Browser Support

| Browser | PWA Install | Push Notifications | |---------|-------------|-------------------| | Chrome | ✅ | ✅ | | Edge | ✅ | ✅ | | Firefox | ❌ | ✅ | | Safari (macOS) | ❌ | ✅ (macOS 13+) | | Safari (iOS) | Manual | ✅ (iOS 16.4+) | | Samsung Internet | ✅ | ✅ |

TypeScript

Full TypeScript support with exported types:

import { 
  CloudSignalPWA,
  PWAConfig,
  DeviceInfo,
  InstallationState,
  Registration,
  PWAEvent,
  // v1.1.0 types
  WakeLockState,
  WakeLockConfig,
  OfflineQueueConfig,
  IOSInstallBannerConfig,
  NetworkConnectionInfo,
  BatteryInfo,
  QueueProcessResult,
  OfflineQueueStats,
} from '@cloudsignal/pwa-sdk'

v1.1.0 Configuration

const pwa = new CloudSignalPWA({
  organizationId: 'your-org-uuid',
  organizationPublishableKey: 'pk_your_publishable_key',
  serviceId: 'your-service-uuid',
  
  // Wake Lock (prevents screen sleep)
  wakeLock: {
    enabled: true,
    autoRequest: false,  // Request manually when needed
    reacquireOnVisibility: true,
  },
  
  // Offline Queue (stores failed requests)
  offlineQueue: {
    enabled: true,
    maxQueueSize: 100,
    maxAgeTTLHours: 24,
    autoProcessOnOnline: true,
  },
  
  // iOS Install Banner
  iosInstallBanner: {
    enabled: true,
    appName: 'My PWA',
    showOnFirstVisit: true,
    showDelay: 3000,
    dismissRememberDays: 7,
  },
  
  // Notification Analytics
  notificationAnalytics: {
    enabled: true,
    endpoint: 'https://api.example.com/analytics',  // Optional custom endpoint
  },
})

License

MIT License - Copyright (c) 2024-2025 CloudSignal