Skip to content

Commit dc59f1f

Browse files
committed
feat: add multi-resolution favicons and refactor generation script to support adaptive SVG themes
1 parent ce6b124 commit dc59f1f

8 files changed

Lines changed: 3 additions & 38 deletions

generate_adaptive_assets.py

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,11 @@
11
import base64
22
import io
3-
from PIL import Image, ImageDraw
3+
from PIL import Image
44

5-
# 1. Load source images
65
logo_black = Image.open('public/ClientEcho_logo.png').convert('RGBA')
76
logo_white = Image.open('public/ClientEcho_logo_white.png').convert('RGBA')
87
w, h = logo_black.size
98

10-
# 2. Build High-DPI Obsidian Squircle Icons (Optimized for Google Search 48x48 multiples, Chrome, & Apple Touch)
11-
def create_squircle_favicon(size, output_path):
12-
scale = 4
13-
hr_size = size * scale
14-
bg = Image.new('RGBA', (hr_size, hr_size), (0, 0, 0, 0))
15-
draw = ImageDraw.Draw(bg)
16-
radius = int(hr_size * 0.225)
17-
18-
# Modern dark obsidian tile (#111116)
19-
draw.rounded_rectangle([(0, 0), (hr_size - 1, hr_size - 1)], radius=radius, fill=(17, 17, 22, 255))
20-
21-
# White logo glyph with ~15% optical margin
22-
glyph_size = int(hr_size * 0.70)
23-
glyph = logo_white.resize((glyph_size, glyph_size), Image.Resampling.LANCZOS)
24-
offset = (hr_size - glyph_size) // 2
25-
bg.paste(glyph, (offset, offset), glyph)
26-
27-
final_img = bg.resize((size, size), Image.Resampling.LANCZOS)
28-
final_img.save(output_path, 'PNG', optimize=True)
29-
print(f'Created {output_path} ({size}x{size})')
30-
return final_img
31-
32-
# Google Search multiples of 48px + standard web sizes
33-
create_squircle_favicon(48, 'public/favicon-48x48.png')
34-
create_squircle_favicon(96, 'public/favicon-96x96.png')
35-
create_squircle_favicon(144, 'public/favicon-144x144.png')
36-
create_squircle_favicon(192, 'public/favicon-192x192.png')
37-
create_squircle_favicon(512, 'public/favicon-512x512.png')
38-
ico_source = create_squircle_favicon(180, 'public/apple-touch-icon.png')
39-
40-
# Generate multi-resolution .ico for Googlebot & standard browser root
41-
ico_source.save('public/favicon.ico', format='ICO', sizes=[(16, 16), (32, 32), (48, 48)])
42-
print('Created public/favicon.ico (16/32/48)')
43-
44-
# 3. Create Adaptive SVG favicon for modern browsers
459
buf_black = io.BytesIO()
4610
logo_black.save(buf_black, format='PNG')
4711
b64_black = base64.b64encode(buf_black.getvalue()).decode('utf-8')
@@ -50,6 +14,7 @@ def create_squircle_favicon(size, output_path):
5014
logo_white.save(buf_white, format='PNG')
5115
b64_white = base64.b64encode(buf_white.getvalue()).decode('utf-8')
5216

17+
# Fully transparent background, dynamic adaptive color switching
5318
svg_content = f'''<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {w} {h}" width="{w}" height="{h}">
5419
<style>
5520
.icon-light {{ display: block; }}
@@ -65,4 +30,4 @@ def create_squircle_favicon(size, output_path):
6530

6631
with open('public/favicon.svg', 'w', encoding='utf-8') as f:
6732
f.write(svg_content)
68-
print('Created public/favicon.svg (Adaptive SVG)')
33+
print('Successfully generated adaptive public/favicon.svg (100% transparent, auto switches Black on Light / White on Dark)')

public/apple-touch-icon.png

-7.36 KB
Loading

public/favicon-144x144.png

-5.75 KB
Loading

public/favicon-192x192.png

-7.9 KB
Loading

public/favicon-48x48.png

-1.35 KB
Loading

public/favicon-512x512.png

-18 KB
Loading

public/favicon-96x96.png

-3.73 KB
Loading

public/favicon.ico

-1.97 KB
Binary file not shown.

0 commit comments

Comments
 (0)