Files
route-commerce/src/lib/pwa.ts
T
tyler 7dfaba6e3d feat: complete launch & marketing layer
- Add marketing pages: blog, changelog, roadmap, waitlist, security, maintenance
- Add GDPR cookie consent banner with preference modal
- Add referral system with API routes for code generation/tracking
- Add waitlist API with referral support
- Add PWA support: manifest, service worker, install prompt
- Add onboarding flow with 6-step guided tour
- Add in-app notification center with bell dropdown
- Add admin launch checklist (32 items across 8 categories)
- Update landing page with trust badges
- Add Open Graph image and favicon
- Configure ESLint for PWA install patterns
- Add LAUNCH_CHECKLIST.md with go-to-market guide

Supabase migrations for:
- blog_posts and blog_categories tables
- waitlist_signups table
- roadmap_items table
- launch_checklist_items table
2026-06-02 06:19:56 +00:00

67 lines
1.9 KiB
TypeScript

// PWA Registration and Service Worker management
export function registerServiceWorker() {
if (typeof window === 'undefined' || !('serviceWorker' in navigator)) {
return;
}
window.addEventListener('load', async () => {
try {
const registration = await navigator.serviceWorker.register('/sw.js', {
scope: '/',
});
// Handle updates
registration.addEventListener('updatefound', () => {
const newWorker = registration.installing;
if (newWorker) {
newWorker.addEventListener('statechange', () => {
if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
// New content available, prompt user to refresh
window.dispatchEvent(new CustomEvent('sw-update-available'));
}
});
}
});
console.log('Service Worker registered:', registration.scope);
} catch (error) {
console.error('Service Worker registration failed:', error);
}
});
}
export async function subscribeToPush(_registration: ServiceWorkerRegistration) {
// Push subscription disabled for now - requires VAPID key setup
return null;
}
// Check if app is installed (PWA)
export function isPWAInstalled(): boolean {
if (typeof window === 'undefined') return false;
return (
window.matchMedia('(display-mode: standalone)').matches ||
(window.navigator as { standalone?: boolean }).standalone === true
);
}
// Share API for native sharing
export async function shareContent(content: {
title: string;
text: string;
url?: string;
}): Promise<boolean> {
if (typeof window === 'undefined' || !navigator.share) {
return false;
}
try {
await navigator.share(content);
return true;
} catch (error) {
if ((error as Error).name !== 'AbortError') {
console.error('Share failed:', error);
}
return false;
}
}