Skip to content

Commit dd020e9

Browse files
jmlwebclaude
andcommitted
feat(pwa): complete PWA icon configuration
- Add favicon.svg (vector) and favicon.png (32x32) for browser tabs - Add apple-touch-icon.png (180x180) for iOS home screen - Update HTML with proper favicon and apple-touch-icon links - Add SVG icon to manifest for better scalability - Regenerate all PNG icons from high-res source (300dpi) for improved quality - Update Service Worker to cache all icons (favicon, apple-touch-icon) - Add logo-desktop.svg for future desktop use - Add routes in API to serve new static assets - Fix type annotations in _html.py for binary cache All PWA icon requirements now met: favicon, touch icons, and manifest icons. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent d70043f commit dd020e9

14 files changed

Lines changed: 108 additions & 84 deletions

.claude/ralph-loop.local.md

Lines changed: 0 additions & 9 deletions
This file was deleted.

webstatuspi/_dashboard/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
are detected automatically without requiring a server restart.
1111
"""
1212

13-
from ._html import build_html
13+
from ._html import build_html, get_static_asset
1414

1515
# CSP nonce placeholder for runtime replacement
1616
CSP_NONCE_PLACEHOLDER = "__CSP_NONCE__"
@@ -38,4 +38,5 @@ def get_dashboard() -> str:
3838
"HTML_DASHBOARD",
3939
"CSP_NONCE_PLACEHOLDER",
4040
"get_dashboard",
41+
"get_static_asset",
4142
]

webstatuspi/_dashboard/_html.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
_template_mtime: float = 0.0
2727
_static_cache: dict[str, str] = {}
2828
_static_mtimes: dict[str, float] = {}
29+
# Cache for binary static files (PNG, etc.)
30+
_static_binary_cache: dict[str, bytes] = {}
31+
_static_binary_mtimes: dict[str, float] = {}
2932

3033

3134
def _get_template() -> Template:
@@ -69,6 +72,37 @@ def _get_static_file(key: str) -> str:
6972
return _static_cache[key]
7073

7174

75+
def get_static_asset(filename: str, binary: bool = False) -> str | bytes | None:
76+
"""Get a static asset file by name, reloading if changed.
77+
78+
Supports hot-reload: changes are detected automatically without server restart.
79+
80+
Args:
81+
filename: Name of the file in the static directory (e.g., "logo-desktop.svg").
82+
binary: If True, return bytes; if False, return string (UTF-8).
83+
84+
Returns:
85+
File content as string or bytes, or None if file doesn't exist.
86+
"""
87+
path = _STATIC_DIR / filename
88+
89+
if not path.exists():
90+
return None
91+
92+
current_mtime = path.stat().st_mtime
93+
94+
if binary:
95+
if filename not in _static_binary_cache or current_mtime != _static_binary_mtimes.get(filename):
96+
_static_binary_cache[filename] = path.read_bytes()
97+
_static_binary_mtimes[filename] = current_mtime
98+
return _static_binary_cache[filename]
99+
else:
100+
if filename not in _static_cache or current_mtime != _static_mtimes.get(filename):
101+
_static_cache[filename] = path.read_text(encoding="utf-8")
102+
_static_mtimes[filename] = current_mtime
103+
return _static_cache[filename]
104+
105+
72106
def build_html() -> str:
73107
"""Build the complete HTML dashboard from its components.
74108

webstatuspi/_dashboard/dashboard.html

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
<title>WebStatusπ // SYSTEM MONITOR</title>
1414
<!-- PWA manifest and icons -->
1515
<link rel="manifest" href="/manifest.json">
16-
<link rel="apple-touch-icon" href="/icon-192.png">
16+
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
17+
<link rel="icon" type="image/png" sizes="32x32" href="/favicon.png">
18+
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
1719
<style nonce="__CSP_NONCE__">$css
1820
</style>
1921
</head>
@@ -25,7 +27,9 @@
2527
</div>
2628
<div class="scanline-overlay" aria-hidden="true"></div>
2729
<header role="banner">
28-
<h1><span class="logo-bracket">&lt;</span><span class="logo-text">WebStatusπ</span><span class="logo-bracket">/&gt;</span></h1>
30+
<h1>
31+
<img src="/logo-desktop.svg" alt="WebStatusPI" width="47" height="16" />
32+
</h1>
2933
<div class="live-indicator" role="status" aria-live="polite" aria-label="Live feed status">
3034
<span class="live-dot" id="liveDot" aria-hidden="true"></span>
3135
<span id="liveStatusText">// LIVE FEED [10 sec]</span>
5.3 KB
Loading
773 Bytes
Loading
Lines changed: 1 addition & 0 deletions
Loading
4.95 KB
Loading
9.81 KB
Loading
Lines changed: 1 addition & 69 deletions
Loading

0 commit comments

Comments
 (0)