kiwi/frontend/vite.config.ts
pyr0ball b86b7732dc
Some checks are pending
CI / Backend (Python) (push) Waiting to run
CI / Frontend (Vue) (push) Waiting to run
Mirror / mirror (push) Waiting to run
fix(pwa): set start_url/scope from VITE_BASE_URL so install launches /kiwi/ not site root
2026-04-25 12:59:59 -07:00

108 lines
3.3 KiB
TypeScript

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { VitePWA } from 'vite-plugin-pwa'
import { fileURLToPath, URL } from 'node:url'
// Ensure start_url/scope match the deployment base path so the PWA launches
// at the correct URL (e.g. /kiwi/ in cloud, / in local dev) rather than the
// site root (which on menagerie.circuitforge.tech is the account page).
const rawBase = process.env.VITE_BASE_URL ?? '/'
const appBase = rawBase.endsWith('/') ? rawBase : rawBase + '/'
export default defineConfig({
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: appBase,
start_url: appBase,
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 ?? '/',
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
build: {
rollupOptions: {
output: {
entryFileNames: 'assets/[name]-[hash:16].js',
chunkFileNames: 'assets/[name]-[hash:16].js',
assetFileNames: 'assets/[name]-[hash:16].[ext]',
},
},
},
server: {
host: '0.0.0.0',
port: 5173,
proxy: {
'/api': {
target: 'http://localhost:8512',
changeOrigin: true,
},
},
},
})