The boilerplate includes comprehensive PWA support with installability, offline capabilities, and push notifications. Users can install the app on their devices and receive real-time alerts even when not actively using the application.
Installability
The app can be installed as a PWA on mobile and desktop devices. The manifest is dynamically generated using app configuration values.
PWA Icons
| File | Size | Purpose |
|---|---|---|
public/icons/icon-192.svg |
192×192 | Standard app icon |
public/icons/icon-512.svg |
512×512 | High-resolution icon |
public/icons/icon-192-maskable.svg |
192×192 | Maskable with safe zone |
public/icons/icon-512-maskable.svg |
512×512 | Maskable with safe zone |
public/icons/badge-72.svg |
72×72 | Notification badge |
Offline Support
The service worker is powered by Serwist, a modern service worker library optimized for Next.js.
The service worker is configured in lib/sw/index.ts and registered automatically. It handles precaching of static assets at build time and applies runtime caching strategies for API responses and dynamic content. No additional environment variables are needed for offline support; the service worker configuration is entirely code-based.
Caching Strategies
- Precaching: Static assets bundled at build time
- Stale-while-revalidate: Fast responses with background updates
- Network-first: Fresh API data with offline fallback
- Offline page:
/offlineshown for uncached navigation
Serwist doesn't support Turbopack yet. The service worker is disabled in development mode. Run npm run build && npm start to test PWA features.
Push Notifications
Full push notification infrastructure using Web Push API with VAPID authentication. Users can enable notifications in the My Account page and configure preferences.
Setup
To enable push notifications, generate VAPID keys using the web-push library and add them to your environment variables as VAPID_PUBLIC_KEY and VAPID_PRIVATE_KEY (both server-only — no NEXT_PUBLIC_ prefix; the browser fetches the public key at runtime via GET /api/push/vapid-key). Generate them with npx web-push generate-vapid-keys. The push notification infrastructure handles subscription management, permission requests, and server-side notification dispatch automatically.
Notification Types
| Type | Description | Default |
|---|---|---|
workspace_invitation |
Team/workspace invitations | ✓ Enabled |
credit_alert |
Low credits warning | ✓ Enabled |
subscription_update |
Subscription changes | ✓ Enabled |
system_announcement |
Platform announcements | ✓ Enabled |
ai_completion |
AI task completions | ✗ Disabled |
API Routes
| Route | Method | Auth | Purpose |
|---|---|---|---|
/api/push/subscribe |
POST | Required | Register push subscription |
/api/push/unsubscribe |
POST | Required | Remove subscription |
/api/push/preferences |
GET/PATCH | Required | Get/update notification preferences |
/api/push/vapid-key |
GET | Public | Get VAPID public key for client |
/api/push/track |
POST | Required | Track notification interactions |
Sending Notifications
Server-side notification sending uses the web-push library with your VAPID credentials. Notifications are dispatched from server code by calling sendNotificationToUser(userId, payload) (or helpers like sendLowCreditsAlert()) from lib/push/index.ts — there is no public send endpoint. The payload accepts title, body, icon, and URL, and it is delivered to all of the target user's subscribed devices (respecting their quiet-hours and per-type preferences). Users manage those preferences from the My Account page.
User Preferences
Users can configure notification preferences including:
- Per-type toggles: Enable/disable each notification type
- Low credits threshold: When to trigger credit alerts
- Quiet hours: Block notifications during specified times
Database Tables
| Table | Purpose |
|---|---|
push_subscriptions |
Per-device push subscriptions (endpoint, keys, device info) |
notification_preferences |
User notification settings (toggles, quiet hours) |
notification_log |
Notification history for analytics (sent, clicked, errors) |
All push API routes that modify data require authentication via apiSecurity.authenticated(). RLS policies ensure users can only access their own subscriptions and preferences.