feat(RECIPE-0003): complete iteration 0 — update icon and add docker deployment

This commit is contained in:
Giancarmine Salucci
2026-02-16 15:56:23 +01:00
parent 08425067e7
commit d55bcf9ae3
12 changed files with 521 additions and 4 deletions

60
scripts/gen-favicon.js Normal file
View File

@@ -0,0 +1,60 @@
import sharp from 'sharp';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
async function generateFavicon() {
const sourceIcon = path.join(__dirname, '..', 'static', 'icon-source.png');
const outputIcon = path.join(__dirname, '..', 'static', 'favicon.png');
console.log('Generating favicon.png from icon-source.png...');
// Verify source file exists
if (!fs.existsSync(sourceIcon)) {
console.error('Error: icon-source.png not found at', sourceIcon);
process.exit(1);
}
// Resize to 192x192 with transparent background
await sharp(sourceIcon)
.resize(192, 192, {
fit: 'contain',
background: { r: 0, g: 0, b: 0, alpha: 0 }
})
.ensureAlpha()
.png()
.toFile(outputIcon);
// Verify output file
const metadata = await sharp(outputIcon).metadata();
const stats = fs.statSync(outputIcon);
console.log(`✓ favicon.png generated successfully`);
console.log(` Dimensions: ${metadata.width}x${metadata.height}`);
console.log(` Format: ${metadata.format}`);
console.log(` Size: ${(stats.size / 1024).toFixed(1)}KB`);
// Validate success criteria
if (metadata.width !== 192 || metadata.height !== 192) {
console.error('Error: Invalid dimensions');
process.exit(1);
}
if (metadata.format !== 'png') {
console.error('Error: Invalid format');
process.exit(1);
}
if (stats.size > 100 * 1024) {
console.error('Error: File size exceeds 100KB');
process.exit(1);
}
console.log('✓ All validation checks passed');
}
generateFavicon().catch(err => {
console.error('Error generating favicon:', err);
process.exit(1);
});

View File

@@ -0,0 +1,55 @@
const sharp = require('sharp');
const fs = require('fs');
async function generateIcon512() {
try {
console.log('Generating icon-512.png from icon-source.png...');
// Check if source file exists
if (!fs.existsSync('static/icon-source.png')) {
console.error('Error: static/icon-source.png does not exist');
process.exit(1);
}
// Generate 512x512 icon
await sharp('static/icon-source.png')
.resize(512, 512, {
fit: 'contain',
background: { r: 0, g: 0, b: 0, alpha: 0 }
})
.png()
.toFile('static/icon-512.png');
console.log('✓ Generated static/icon-512.png');
// Verify the result
const metadata = await sharp('static/icon-512.png').metadata();
const stats = fs.statSync('static/icon-512.png');
console.log(` Dimensions: ${metadata.width}x${metadata.height}`);
console.log(` Format: ${metadata.format}`);
console.log(` Size: ${Math.round(stats.size / 1024)}KB`);
// Validate
if (metadata.width !== 512 || metadata.height !== 512) {
console.error('Error: Invalid dimensions');
process.exit(1);
}
if (metadata.format !== 'png') {
console.error('Error: Invalid format');
process.exit(1);
}
if (stats.size > 200 * 1024) {
console.error('Error: File size exceeds 200KB');
process.exit(1);
}
console.log('✓ Validation passed');
process.exit(0);
} catch (error) {
console.error('Error generating icon:', error.message);
process.exit(1);
}
}
generateIcon512();