Skip to main content

PWA

Weblisk provides progressive web app primitives for offline support, push notifications, and installability.

Offline State

Track connectivity as a reactive signal:

js
import { online, syncStatus, pendingCount } from 'weblisk/pwa/offline.js';

effect(() => {
  if (!online()) {
    showBanner('You are offline. Changes are saved locally.');
  }
});

effect(() => {
  const status = syncStatus(); // 'idle', 'syncing', 'error'
  const count = pendingCount();
  if (count > 0) {
    statusEl.textContent = `${count} changes pending sync`;
  }
});

Manual Sync

js
import { triggerSync } from 'weblisk/pwa/offline.js';

await triggerSync('todos');       // Sync a specific collection
await triggerSync();              // Sync all collections

Periodic Sync

Register background sync that runs on an interval (Chromium only):

js
import { registerPeriodicSync } from 'weblisk/pwa/offline.js';

const success = await registerPeriodicSync('content-refresh', 12 * 60 * 60 * 1000);

Push Notifications

js
import { requestPermission, subscribe, notify, permission } from 'weblisk/pwa/push.js';

// Check current permission
effect(() => console.log('Permission:', permission()));

// Request permission
const result = await requestPermission();

// Subscribe to push (server needs to store the subscription)
const sub = await subscribe('YOUR_VAPID_PUBLIC_KEY');
await fetch('/api/push/subscribe', {
  method: 'POST',
  body: JSON.stringify(sub),
});

// Show a local notification
await notify('New message', {
  body: 'You have a new message from Alice',
  icon: '/icon-192.png',
});

Web App Manifest

Generate and inject a manifest at runtime:

js
import { manifest, injectManifest, setThemeColor } from 'weblisk/pwa/manifest.js';

const m = manifest({
  name: 'My App',
  short_name: 'App',
  start_url: '/',
  display: 'standalone',
  theme_color: '#2563eb',
  background_color: '#ffffff',
  icons: [
    { src: '/icon-192.png', sizes: '192x192', type: 'image/png' },
    { src: '/icon-512.png', sizes: '512x512', type: 'image/png' },
  ],
});

injectManifest(m);

// Update theme color dynamically (e.g., dark mode)
setThemeColor('#1e293b');