feat(pwa): add Progressive Web App support — installable to homescreen
- vite-plugin-pwa with generateSW strategy (Workbox) - manifest.webmanifest: name, short_name, display standalone, theme_color #e8a820 - Service worker: precaches JS/CSS/HTML shell; API routes network-first (60s); Google Fonts cache-first (1 year) - Icons: 192 + 512px regular + maskable variants generated from App.vue bird SVG - index.html: theme-color meta, apple-touch-icon, apple-mobile-web-app-* tags for iOS Safari homescreen support (iOS ignores the manifest icons array) - autoUpdate mode: new versions install silently and activate on next navigation
This commit is contained in:
parent
e2c358c90a
commit
7e0722cc23
8 changed files with 4756 additions and 10 deletions
|
|
@ -2,8 +2,13 @@
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/png" sizes="192x192" href="/icons/icon-192.png" />
|
||||||
|
<link rel="apple-touch-icon" href="/icons/icon-192.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
||||||
|
<meta name="theme-color" content="#e8a820" />
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||||
|
<meta name="apple-mobile-web-app-title" content="Kiwi" />
|
||||||
<title>Kiwi — Pantry Tracker</title>
|
<title>Kiwi — Pantry Tracker</title>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
|
|
||||||
4686
frontend/package-lock.json
generated
4686
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -20,6 +20,7 @@
|
||||||
"@vue/tsconfig": "^0.8.1",
|
"@vue/tsconfig": "^0.8.1",
|
||||||
"typescript": "~5.9.3",
|
"typescript": "~5.9.3",
|
||||||
"vite": "^7.1.7",
|
"vite": "^7.1.7",
|
||||||
|
"vite-plugin-pwa": "^1.2.0",
|
||||||
"vue-tsc": "^3.1.0"
|
"vue-tsc": "^3.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
BIN
frontend/public/icons/icon-192.png
Normal file
BIN
frontend/public/icons/icon-192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
BIN
frontend/public/icons/icon-512.png
Normal file
BIN
frontend/public/icons/icon-512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
BIN
frontend/public/icons/maskable-192.png
Normal file
BIN
frontend/public/icons/maskable-192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
BIN
frontend/public/icons/maskable-512.png
Normal file
BIN
frontend/public/icons/maskable-512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
|
|
@ -1,9 +1,79 @@
|
||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
import { VitePWA } from 'vite-plugin-pwa'
|
||||||
import { fileURLToPath, URL } from 'node:url'
|
import { fileURLToPath, URL } from 'node:url'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [vue()],
|
plugins: [
|
||||||
|
vue(),
|
||||||
|
VitePWA({
|
||||||
|
registerType: 'autoUpdate',
|
||||||
|
// generateSW strategy: Workbox builds the service worker at build time.
|
||||||
|
// autoUpdate means new versions install in the background and activate
|
||||||
|
// on next navigation — no "click to reload" prompt needed.
|
||||||
|
strategies: 'generateSW',
|
||||||
|
includeAssets: ['icons/icon-192.png', 'icons/icon-512.png', 'icons/maskable-192.png', 'icons/maskable-512.png'],
|
||||||
|
manifest: {
|
||||||
|
name: 'Kiwi — Pantry Tracker',
|
||||||
|
short_name: 'Kiwi',
|
||||||
|
description: 'Track your pantry, cut food waste, get recipe ideas from what you have.',
|
||||||
|
theme_color: '#e8a820',
|
||||||
|
background_color: '#1e1c1a',
|
||||||
|
display: 'standalone',
|
||||||
|
orientation: 'portrait',
|
||||||
|
scope: '/',
|
||||||
|
start_url: '/',
|
||||||
|
icons: [
|
||||||
|
{
|
||||||
|
src: '/icons/icon-192.png',
|
||||||
|
sizes: '192x192',
|
||||||
|
type: 'image/png',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: '/icons/icon-512.png',
|
||||||
|
sizes: '512x512',
|
||||||
|
type: 'image/png',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: '/icons/maskable-192.png',
|
||||||
|
sizes: '192x192',
|
||||||
|
type: 'image/png',
|
||||||
|
purpose: 'maskable',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: '/icons/maskable-512.png',
|
||||||
|
sizes: '512x512',
|
||||||
|
type: 'image/png',
|
||||||
|
purpose: 'maskable',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
workbox: {
|
||||||
|
// Precache the built JS/CSS/HTML shell. API calls are always network-first.
|
||||||
|
globPatterns: ['**/*.{js,css,html,ico,png,svg,woff2}'],
|
||||||
|
runtimeCaching: [
|
||||||
|
{
|
||||||
|
// API: network-first, fall back to cache for 1 minute
|
||||||
|
urlPattern: /^\/api\//,
|
||||||
|
handler: 'NetworkFirst',
|
||||||
|
options: {
|
||||||
|
cacheName: 'kiwi-api-cache',
|
||||||
|
expiration: { maxEntries: 50, maxAgeSeconds: 60 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Google Fonts: cache-first (fonts rarely change)
|
||||||
|
urlPattern: /^https:\/\/fonts\.(googleapis|gstatic)\.com\//,
|
||||||
|
handler: 'CacheFirst',
|
||||||
|
options: {
|
||||||
|
cacheName: 'google-fonts',
|
||||||
|
expiration: { maxEntries: 10, maxAgeSeconds: 60 * 60 * 24 * 365 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
base: process.env.VITE_BASE_URL ?? '/',
|
base: process.env.VITE_BASE_URL ?? '/',
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue