From 39feb722f51a199cd422fbd9c76428ef5d10fc8c Mon Sep 17 00:00:00 2001 From: Dorian Date: Tue, 3 Feb 2026 00:26:31 +0000 Subject: [PATCH] Fix PWA installation for Brave/Android - Complete rewrite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Critical fixes for PWA installation: 1. ✅ Use proper Vite PWA registration with virtual:pwa-register 2. ✅ Simplified manifest.json (removed verbose name, fixed orientation) 3. ✅ Added 'any maskable' dual-purpose icon for better compatibility 4. ✅ Removed crossorigin from manifest link (causes issues) 5. ✅ Simplified start_url to just '/' 6. ✅ Added msapplication-TileColor meta tag 7. ✅ Set injectRegister: 'auto' in Vite config 8. ✅ Use public/manifest.json directly instead of generating This should now work on Brave Browser Android with proper 'Install App' prompt. Test: Clear site data, visit site, should see install prompt within 30 seconds. Co-authored-by: Cursor --- index.html | 4 +++- public/manifest.json | 21 ++++++++++++--------- src/main.ts | 20 ++++++++++++-------- vite.config.ts | 38 ++------------------------------------ 4 files changed, 29 insertions(+), 54 deletions(-) diff --git a/index.html b/index.html index 2375fff..0424bf3 100644 --- a/index.html +++ b/index.html @@ -14,8 +14,10 @@ + + - +
diff --git a/public/manifest.json b/public/manifest.json index 0a5f175..29dcb30 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,26 +1,23 @@ { - "name": "IndeedHub - Decentralized Media Streaming", + "name": "IndeedHub", "short_name": "IndeedHub", "description": "Stream films and content on the decentralized web powered by Nostr and Bitcoin", - "start_url": "/?source=pwa", + "start_url": "/", "scope": "/", "display": "standalone", - "orientation": "any", + "orientation": "portrait-primary", "background_color": "#0a0a0a", "theme_color": "#0a0a0a", - "prefer_related_applications": false, "icons": [ { "src": "/icons/icon-192.png", "sizes": "192x192", - "type": "image/png", - "purpose": "any" + "type": "image/png" }, { "src": "/icons/icon-512.png", "sizes": "512x512", - "type": "image/png", - "purpose": "any" + "type": "image/png" }, { "src": "/icons/icon-192-maskable.png", @@ -33,9 +30,15 @@ "sizes": "512x512", "type": "image/png", "purpose": "maskable" + }, + { + "src": "/icons/icon-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "any maskable" } ], - "categories": ["entertainment", "video", "streaming"], + "categories": ["entertainment"], "lang": "en-US", "dir": "ltr" } diff --git a/src/main.ts b/src/main.ts index f22791c..804fbae 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,6 +3,7 @@ import { createPinia } from 'pinia' import router from './router' import App from './App.vue' import './style.css' +import { registerSW } from 'virtual:pwa-register' const app = createApp(App) @@ -11,11 +12,14 @@ app.use(router) app.mount('#app') -// Register PWA service worker -if ('serviceWorker' in navigator) { - window.addEventListener('load', () => { - navigator.serviceWorker.register('/sw.js').catch(() => { - // Service worker registration failed, that's okay - }) - }) -} +// Register PWA service worker with auto-update +const updateSW = registerSW({ + immediate: true, + onNeedRefresh() { + // Auto-reload when new content is available + updateSW(true) + }, + onOfflineReady() { + console.log('App ready to work offline') + }, +}) diff --git a/vite.config.ts b/vite.config.ts index ce16e19..25a82bf 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -8,46 +8,12 @@ export default defineConfig({ vue(), VitePWA({ registerType: 'autoUpdate', + injectRegister: 'auto', includeAssets: ['icons/*.png', 'assets/fonts/*.otf'], devOptions: { enabled: false }, - manifest: { - name: 'IndeedHub - Decentralized Media Streaming', - short_name: 'IndeedHub', - description: 'Stream films and content on the decentralized web powered by Nostr and Bitcoin', - theme_color: '#0a0a0a', - background_color: '#0a0a0a', - display: 'standalone', - start_url: '/', - scope: '/', - icons: [ - { - src: '/icons/icon-192.png', - sizes: '192x192', - type: 'image/png', - purpose: 'any' - }, - { - src: '/icons/icon-512.png', - sizes: '512x512', - type: 'image/png', - purpose: 'any' - }, - { - src: '/icons/icon-192-maskable.png', - sizes: '192x192', - type: 'image/png', - purpose: 'maskable' - }, - { - src: '/icons/icon-512-maskable.png', - sizes: '512x512', - type: 'image/png', - purpose: 'maskable' - } - ] - }, + manifest: false, // Use public/manifest.json instead workbox: { maximumFileSizeToCacheInBytes: 10 * 1024 * 1024, // 10 MB limit globPatterns: ['**/*.{js,css,html,ico,png,svg,jpg,jpeg,woff,woff2,otf}'],