feat(cannaiq): Add PWA support with vite-plugin-pwa
- Add vite-plugin-pwa for service worker and manifest generation - Configure workbox for asset caching and API runtime caching - Add sharp for icon generation from SVG - Create generate-icons.js script to create 192x192 and 512x512 PNGs - Update build script to auto-generate icons before build App is now installable as a PWA with offline support. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,8 @@
|
||||
"scripts": {
|
||||
"dev": "vite --host",
|
||||
"dev:admin": "vite --host --port 8080",
|
||||
"build": "tsc && vite build",
|
||||
"generate-icons": "node scripts/generate-icons.js",
|
||||
"build": "node scripts/generate-icons.js && tsc && vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -26,6 +27,8 @@
|
||||
"postcss": "^8.4.32",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"typescript": "^5.3.3",
|
||||
"vite": "^5.0.8"
|
||||
"vite": "^5.0.8",
|
||||
"vite-plugin-pwa": "^0.21.1",
|
||||
"sharp": "^0.33.5"
|
||||
}
|
||||
}
|
||||
|
||||
37
cannaiq/scripts/generate-icons.js
Normal file
37
cannaiq/scripts/generate-icons.js
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Generate PWA icons from favicon.svg
|
||||
*
|
||||
* Run: node scripts/generate-icons.js
|
||||
*/
|
||||
|
||||
import sharp from 'sharp';
|
||||
import { readFileSync, writeFileSync } from 'fs';
|
||||
import { join, dirname } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const publicDir = join(__dirname, '..', 'public');
|
||||
|
||||
const svgPath = join(publicDir, 'favicon.svg');
|
||||
const svg = readFileSync(svgPath);
|
||||
|
||||
const sizes = [192, 512];
|
||||
|
||||
async function generateIcons() {
|
||||
console.log('Generating PWA icons from favicon.svg...');
|
||||
|
||||
for (const size of sizes) {
|
||||
const outputPath = join(publicDir, `icon-${size}.png`);
|
||||
|
||||
await sharp(svg)
|
||||
.resize(size, size)
|
||||
.png()
|
||||
.toFile(outputPath);
|
||||
|
||||
console.log(` Created icon-${size}.png`);
|
||||
}
|
||||
|
||||
console.log('Done!');
|
||||
}
|
||||
|
||||
generateIcons().catch(console.error);
|
||||
@@ -1,8 +1,61 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import { VitePWA } from 'vite-plugin-pwa';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
plugins: [
|
||||
react(),
|
||||
VitePWA({
|
||||
registerType: 'autoUpdate',
|
||||
includeAssets: ['favicon.svg'],
|
||||
manifest: {
|
||||
name: 'CannaIQ',
|
||||
short_name: 'CannaIQ',
|
||||
description: 'Cannabis dispensary analytics and management',
|
||||
theme_color: '#059669',
|
||||
background_color: '#1f2937',
|
||||
display: 'standalone',
|
||||
scope: '/',
|
||||
start_url: '/',
|
||||
icons: [
|
||||
{
|
||||
src: '/icon-192.png',
|
||||
sizes: '192x192',
|
||||
type: 'image/png',
|
||||
},
|
||||
{
|
||||
src: '/icon-512.png',
|
||||
sizes: '512x512',
|
||||
type: 'image/png',
|
||||
},
|
||||
{
|
||||
src: '/icon-512.png',
|
||||
sizes: '512x512',
|
||||
type: 'image/png',
|
||||
purpose: 'maskable',
|
||||
},
|
||||
],
|
||||
},
|
||||
workbox: {
|
||||
// Cache all assets
|
||||
globPatterns: ['**/*.{js,css,html,ico,png,svg,woff,woff2}'],
|
||||
// Runtime caching for API calls
|
||||
runtimeCaching: [
|
||||
{
|
||||
urlPattern: /^https:\/\/cannaiq\.co\/api\/.*/i,
|
||||
handler: 'NetworkFirst',
|
||||
options: {
|
||||
cacheName: 'api-cache',
|
||||
expiration: {
|
||||
maxEntries: 100,
|
||||
maxAgeSeconds: 60 * 5, // 5 minutes
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
],
|
||||
server: {
|
||||
host: true,
|
||||
port: 8080,
|
||||
|
||||
Reference in New Issue
Block a user