Add logo generation scripts and favicon base image

This commit is contained in:
Hördle Bot
2025-12-05 12:26:54 +01:00
parent 97021f016b
commit c1b448639e
4 changed files with 305 additions and 0 deletions

BIN
public/favicon-base.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 563 KiB

View File

@@ -0,0 +1,47 @@
const sharp = require('sharp');
const fs = require('fs');
const path = require('path');
async function convertSvgToPng(svgPath, pngPath, size) {
try {
const svgBuffer = fs.readFileSync(svgPath);
await sharp(svgBuffer, {
density: 300 // High DPI for better quality
})
.resize(size, size, {
fit: 'contain',
background: { r: 255, g: 255, b: 255, alpha: 0 } // Transparent background
})
.png()
.toFile(pngPath);
console.log(`✅ Created ${pngPath} (${size}x${size})`);
} catch (error) {
console.error(`❌ Error converting ${svgPath}:`, error.message);
}
}
async function main() {
const publicDir = path.join(__dirname, '..', 'public');
// Convert logo.svg to various PNG sizes
const logoPath = path.join(publicDir, 'logo.svg');
if (fs.existsSync(logoPath)) {
await convertSvgToPng(logoPath, path.join(publicDir, 'logo-512.png'), 512);
await convertSvgToPng(logoPath, path.join(publicDir, 'logo-256.png'), 256);
await convertSvgToPng(logoPath, path.join(publicDir, 'logo-128.png'), 128);
}
// Convert logo-large.svg to larger PNG sizes
const logoLargePath = path.join(publicDir, 'logo-large.svg');
if (fs.existsSync(logoLargePath)) {
await convertSvgToPng(logoLargePath, path.join(publicDir, 'logo-1024.png'), 1024);
await convertSvgToPng(logoLargePath, path.join(publicDir, 'logo-512.png'), 512);
}
console.log('\n✨ Logo conversion complete!');
}
main();

View File

@@ -0,0 +1,138 @@
const sharp = require('sharp');
const fs = require('fs');
const path = require('path');
async function createLogoWithText(faviconPath, outputPath, size) {
try {
// Load and resize favicon - smaller to leave room for text
const faviconSize = Math.floor(size * 0.65);
const faviconBuffer = await sharp(faviconPath)
.resize(faviconSize, faviconSize, {
fit: 'contain',
background: { r: 255, g: 255, b: 255, alpha: 0 }
})
.toBuffer();
// Create SVG with favicon and text
const textSize = Math.floor(size * 0.12);
const iconY = Math.floor(size * 0.10); // Logo higher up
const textY = Math.floor(size * 0.92); // Text further down
const iconX = Math.floor((size - faviconSize) / 2);
const svg = `<?xml version="1.0" encoding="UTF-8"?>
<svg width="${size}" height="${size}" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- White background -->
<rect width="${size}" height="${size}" fill="#ffffff"/>
<image href="data:image/png;base64,${faviconBuffer.toString('base64')}"
x="${iconX}"
y="${iconY}"
width="${faviconSize}"
height="${faviconSize}"/>
<text x="${size / 2}" y="${textY}"
font-family="system-ui, -apple-system, sans-serif"
font-size="${textSize}"
font-weight="bold"
fill="#000000"
text-anchor="middle"
letter-spacing="-0.5">
hördle.de
</text>
</svg>`;
// Convert SVG to PNG with white background
await sharp(Buffer.from(svg))
.resize(size, size)
.png()
.toFile(outputPath);
console.log(`✅ Created ${path.basename(outputPath)} (${size}x${size})`);
} catch (error) {
console.error(`❌ Error creating ${outputPath}:`, error.message);
}
}
async function createSVGLogo(faviconPath, outputPath, size) {
try {
// Load and resize favicon - smaller to leave room for text
const faviconSize = Math.floor(size * 0.65);
const faviconBuffer = await sharp(faviconPath)
.resize(faviconSize, faviconSize, {
fit: 'contain',
background: { r: 255, g: 255, b: 255, alpha: 0 }
})
.toBuffer();
// Create SVG with favicon and text
const textSize = Math.floor(size * 0.12);
const iconY = Math.floor(size * 0.10); // Logo higher up
const textY = Math.floor(size * 0.92); // Text further down
const iconX = Math.floor((size - faviconSize) / 2);
const svg = `<?xml version="1.0" encoding="UTF-8"?>
<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- White background covering entire image -->
<rect width="${size}" height="${size}" fill="#ffffff"/>
<image href="data:image/png;base64,${faviconBuffer.toString('base64')}"
x="${iconX}"
y="${iconY}"
width="${faviconSize}"
height="${faviconSize}"/>
<text x="${size / 2}" y="${textY}"
font-family="system-ui, -apple-system, sans-serif"
font-size="${textSize}"
font-weight="bold"
fill="#000000"
text-anchor="middle"
letter-spacing="-0.5">
hördle.de
</text>
</svg>`;
fs.writeFileSync(outputPath, svg);
console.log(`✅ Created ${path.basename(outputPath)} (${size}x${size} SVG)`);
} catch (error) {
console.error(`❌ Error creating ${outputPath}:`, error.message);
}
}
async function main() {
const faviconPath = path.join(__dirname, '..', 'app', 'favicon.ico');
const publicDir = path.join(__dirname, '..', 'public');
if (!fs.existsSync(faviconPath)) {
console.error('❌ Favicon not found at', faviconPath);
return;
}
// Extract favicon to PNG first for processing
const tempFavicon = path.join(publicDir, 'favicon-temp.png');
const faviconBuffer = fs.readFileSync(faviconPath);
// Convert ICO to PNG
await sharp(faviconBuffer)
.resize(1024, 1024, { fit: 'contain' })
.png()
.toFile(tempFavicon);
console.log('✅ Extracted favicon to PNG\n');
// Create SVG logo
await createSVGLogo(tempFavicon, path.join(publicDir, 'logo.svg'), 512);
await createSVGLogo(tempFavicon, path.join(publicDir, 'logo-large.svg'), 1024);
// Create PNG logos with text in various sizes
await createLogoWithText(tempFavicon, path.join(publicDir, 'logo-128.png'), 128);
await createLogoWithText(tempFavicon, path.join(publicDir, 'logo-256.png'), 256);
await createLogoWithText(tempFavicon, path.join(publicDir, 'logo-512.png'), 512);
await createLogoWithText(tempFavicon, path.join(publicDir, 'logo-1024.png'), 1024);
// Clean up temp file
if (fs.existsSync(tempFavicon)) {
fs.unlinkSync(tempFavicon);
}
console.log('\n✨ Logo creation complete!');
}
main();

View File

@@ -0,0 +1,120 @@
const sharp = require('sharp');
const fs = require('fs');
const path = require('path');
async function createLogoWithText(faviconPath, outputPath, size, includeText = true) {
try {
const favicon = await sharp(faviconPath)
.resize(size * 0.7, size * 0.7, {
fit: 'contain',
background: { r: 255, g: 255, b: 255, alpha: 0 }
})
.toBuffer();
// Create SVG with favicon and text
const textSize = Math.floor(size * 0.15);
const spacing = Math.floor(size * 0.05);
const iconSize = Math.floor(size * 0.7);
const iconY = Math.floor(includeText ? size * 0.25 : size * 0.5);
const textY = Math.floor(size * 0.85);
// For now, we'll create a composite image
// First, create the favicon part
const svg = includeText ? `
<svg width="${size}" height="${size}" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="faviconPattern" x="0" y="0" width="1" height="1">
<image href="data:image/png;base64,${favicon.toString('base64')}"
x="${(size - iconSize) / 2}"
y="${iconY - iconSize / 2}"
width="${iconSize}"
height="${iconSize}"/>
</pattern>
</defs>
<rect width="${size}" height="${size}" fill="url(#faviconPattern)"/>
<text x="${size / 2}" y="${textY}"
font-family="system-ui, -apple-system, sans-serif"
font-size="${textSize}"
font-weight="bold"
fill="#000000"
text-anchor="middle"
letter-spacing="-0.5">
Hördle
</text>
</svg>
` : `
<svg width="${size}" height="${size}" xmlns="http://www.w3.org/2000/svg">
<image href="data:image/png;base64,${favicon.toString('base64')}"
x="${(size - iconSize) / 2}"
y="${(size - iconSize) / 2}"
width="${iconSize}"
height="${iconSize}"/>
</svg>
`;
// Convert SVG to PNG
await sharp(Buffer.from(svg))
.png()
.toFile(outputPath);
console.log(`✅ Created ${outputPath} (${size}x${size})`);
} catch (error) {
console.error(`❌ Error creating ${outputPath}:`, error.message);
}
}
async function main() {
const faviconPath = path.join(__dirname, '..', 'app', 'favicon.ico');
const publicDir = path.join(__dirname, '..', 'public');
if (!fs.existsSync(faviconPath)) {
console.error('❌ Favicon not found at', faviconPath);
return;
}
// Extract favicon to PNG first
const tempFavicon = path.join(publicDir, 'favicon-temp.png');
const faviconBuffer = fs.readFileSync(faviconPath);
// Convert ICO to PNG
await sharp(faviconBuffer)
.resize(1024, 1024, { fit: 'contain' })
.png()
.toFile(tempFavicon);
console.log('✅ Extracted favicon to PNG');
// Create logos with text in various sizes
await createLogoWithText(tempFavicon, path.join(publicDir, 'logo-128.png'), 128);
await createLogoWithText(tempFavicon, path.join(publicDir, 'logo-256.png'), 256);
await createLogoWithText(tempFavicon, path.join(publicDir, 'logo-512.png'), 512);
await createLogoWithText(tempFavicon, path.join(publicDir, 'logo-1024.png'), 1024);
// Create SVG version
const faviconPng = await sharp(faviconBuffer)
.resize(512, 512, { fit: 'contain' })
.png()
.toBuffer();
const svgContent = `<?xml version="1.0" encoding="UTF-8"?>
<svg width="512" height="512" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<image id="faviconImg" href="data:image/png;base64,${faviconPng.toString('base64')}" width="358" height="358" x="77" y="77"/>
</defs>
<use href="#faviconImg"/>
<text x="256" y="430" font-family="system-ui, -apple-system, sans-serif" font-size="48" font-weight="bold" fill="#000000" text-anchor="middle" letter-spacing="-0.5">
Hördle
</text>
</svg>`;
fs.writeFileSync(path.join(publicDir, 'logo.svg'), svgContent);
console.log('✅ Created logo.svg');
// Clean up temp file
fs.unlinkSync(tempFavicon);
console.log('\n✨ Logo creation complete!');
}
main();