Generated proper PNG icons for Android PWA support: - icon-192.png / icon-512.png (standard icons) - icon-192-maskable.png / icon-512-maskable.png (with 10% padding for Android) - apple-touch-icon.png (180x180 for iOS) Android requires PNG icons, not SVG, for proper PWA installation. SVG-only manifests cause 'shortcut' behavior instead of full app install. Updated manifest.json, index.html, and vite.config.ts to use PNG icons. Added icon generation scripts for future updates. This should now offer proper 'Install App' on Android instead of 'Add to Home Screen'. Co-authored-by: Cursor <cursoragent@cursor.com>
65 lines
1.9 KiB
JavaScript
65 lines
1.9 KiB
JavaScript
/**
|
|
* Generate PWA Icons from SVG using Sharp
|
|
* Run: npm install sharp && node generate-pwa-icons-sharp.js
|
|
*/
|
|
|
|
import sharp from 'sharp';
|
|
import { readFileSync, mkdirSync } from 'fs';
|
|
import { join, dirname } from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = dirname(__filename);
|
|
|
|
const svgPath = join(__dirname, 'assets', 'images', 'app-icon.svg');
|
|
const iconsDir = join(__dirname, 'public', 'icons');
|
|
|
|
// Create icons directory
|
|
mkdirSync(iconsDir, { recursive: true });
|
|
|
|
const svgBuffer = readFileSync(svgPath);
|
|
|
|
const sizes = [
|
|
{ size: 192, name: 'icon-192.png', maskable: false },
|
|
{ size: 512, name: 'icon-512.png', maskable: false },
|
|
{ size: 192, name: 'icon-192-maskable.png', maskable: true },
|
|
{ size: 512, name: 'icon-512-maskable.png', maskable: true },
|
|
{ size: 180, name: 'apple-touch-icon.png', maskable: false }
|
|
];
|
|
|
|
async function generateIcons() {
|
|
console.log('Generating PWA icons...');
|
|
|
|
for (const { size, name, maskable } of sizes) {
|
|
try {
|
|
let pipeline = sharp(svgBuffer).resize(size, size);
|
|
|
|
// For maskable icons, add padding (safe zone)
|
|
if (maskable) {
|
|
const padding = Math.floor(size * 0.1); // 10% padding
|
|
const innerSize = size - (padding * 2);
|
|
|
|
pipeline = sharp(svgBuffer)
|
|
.resize(innerSize, innerSize)
|
|
.extend({
|
|
top: padding,
|
|
bottom: padding,
|
|
left: padding,
|
|
right: padding,
|
|
background: { r: 10, g: 10, b: 10, alpha: 1 } // #0a0a0a
|
|
});
|
|
}
|
|
|
|
await pipeline.png().toFile(join(iconsDir, name));
|
|
console.log(`✓ Generated ${name}`);
|
|
} catch (error) {
|
|
console.error(`✗ Failed to generate ${name}:`, error.message);
|
|
}
|
|
}
|
|
|
|
console.log('\n✓ All icons generated successfully!');
|
|
console.log('Icons saved to: public/icons/');
|
|
}
|
|
|
|
generateIcons().catch(console.error);
|