- Install vite-plugin-pwa and workbox-window for PWA functionality - Configure Vite with full PWA manifest (name, icons, theme, display) - Add service worker caching for static assets only (no API cache) - Create app icons (192x192, 512x512, apple-touch-icon) - Generate iOS splash screens for multiple device sizes - Add iOS-specific meta tags (apple-mobile-web-app-capable, etc.) - Implement InstallPWA component with dual platform support: - Android/Chrome: beforeinstallprompt event with custom UI - iOS Safari: manual installation instructions with icons - Add dismissal logic with 7-day localStorage persistence - Update documentation to reflect 90% project completion PWA implementation focuses on installability and static asset caching while avoiding offline API cache (WebRTC requires active connection).
99 lines
2.5 KiB
JavaScript
99 lines
2.5 KiB
JavaScript
import { defineConfig } from 'vite'
|
|
import react from '@vitejs/plugin-react'
|
|
import { VitePWA } from 'vite-plugin-pwa'
|
|
|
|
// Parse allowed hosts from environment variable
|
|
const getAllowedHosts = () => {
|
|
const hosts = process.env.VITE_ALLOWED_HOSTS;
|
|
|
|
// If set to 'all', allow all hosts
|
|
if (hosts === 'all') {
|
|
return 'all';
|
|
}
|
|
|
|
// If set, parse comma-separated list
|
|
if (hosts) {
|
|
return hosts.split(',').map(h => h.trim());
|
|
}
|
|
|
|
// Default: localhost only
|
|
return ['localhost'];
|
|
};
|
|
|
|
// https://vite.dev/config/
|
|
export default defineConfig({
|
|
plugins: [
|
|
react(),
|
|
VitePWA({
|
|
registerType: 'autoUpdate',
|
|
includeAssets: ['favicon.ico', 'robots.txt', 'apple-touch-icon.png'],
|
|
manifest: {
|
|
name: 'spotlight.cam - Dance Event Video Exchange',
|
|
short_name: 'spotlight',
|
|
description: 'P2P video exchange platform for dance event participants',
|
|
theme_color: '#6366f1',
|
|
background_color: '#ffffff',
|
|
display: 'standalone',
|
|
orientation: 'portrait',
|
|
scope: '/',
|
|
start_url: '/',
|
|
icons: [
|
|
{
|
|
src: '/icons/icon-192x192.png',
|
|
sizes: '192x192',
|
|
type: 'image/png',
|
|
purpose: 'any maskable',
|
|
},
|
|
{
|
|
src: '/icons/icon-512x512.png',
|
|
sizes: '512x512',
|
|
type: 'image/png',
|
|
purpose: 'any maskable',
|
|
},
|
|
{
|
|
src: '/icons/apple-touch-icon.png',
|
|
sizes: '180x180',
|
|
type: 'image/png',
|
|
},
|
|
],
|
|
},
|
|
workbox: {
|
|
// Cache only static assets (no API caching)
|
|
globPatterns: ['**/*.{js,css,html,ico,png,svg,woff2}'],
|
|
runtimeCaching: [
|
|
{
|
|
// Cache images from ui-avatars.com
|
|
urlPattern: /^https:\/\/ui-avatars\.com\/.*/i,
|
|
handler: 'CacheFirst',
|
|
options: {
|
|
cacheName: 'avatar-images',
|
|
expiration: {
|
|
maxEntries: 100,
|
|
maxAgeSeconds: 60 * 60 * 24 * 7, // 7 days
|
|
},
|
|
cacheableResponse: {
|
|
statuses: [0, 200],
|
|
},
|
|
},
|
|
},
|
|
],
|
|
navigateFallback: null, // Disable offline fallback (app requires internet)
|
|
},
|
|
devOptions: {
|
|
enabled: false, // Disable in dev to avoid conflicts
|
|
},
|
|
}),
|
|
],
|
|
server: {
|
|
host: '0.0.0.0',
|
|
port: 5173,
|
|
allowedHosts: getAllowedHosts(),
|
|
watch: {
|
|
usePolling: true,
|
|
},
|
|
hmr: {
|
|
clientPort: 8080,
|
|
},
|
|
},
|
|
})
|