iOS showed a letter tile ('N') when adding to the Home Screen. The live files were fine, but a
reverse proxy in front of the app serves static files with a long cache lifetime (live icon.svg
and sw.js were stale) and iOS remembers a failed icon per URL.
- New versioned URLs no proxy/phone has cached; old paths kept for existing installs
- apple-touch-icon declared at 180/167/152/120 (opaque 8-bit RGB PNGs) for app and dashboard
- 180px icon also listed in both manifests; notification icons and root fallbacks use v2
- Service worker cache bumped
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- setup/recover/settings pages now declare the dashboard touch icon and 'Station' title
- /apple-touch-icon.png, /apple-touch-icon-precomposed.png and /favicon.ico serve real icons
(iOS falls back to these when a page declares none; they used to 404/204)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Install banner (phones), Settings guide and dialog with iPhone/iPad and Android steps,
native Install button where supported; steps also on the dashboard Account page
- apple-touch-icon now a PNG (iOS ignores SVG icons)
- Shared pwa-safe.css: dark cap behind the status bar/Dynamic Island in the installed app,
inset-aware offline banner, pull-to-refresh, bottom bars, full-screen map, dialogs
- Landscape-aware content gutters; measured top-bar height; viewport-fit=cover on every page
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- One slate/blue palette across the app, dashboard, account/login pages (data colours
stay orange = warm, blue = cool on the dashboard)
- Slim sticky top bar with location chip, gear (settings) and ? (learn); 4-tab nav
(Now, Station, Map, Alerts) with a thumb-reach bottom bar on phones
- Hero sky gradient by condition/time with rain, storm, snow and star effects
(respects reduced motion); keeps the searched city and badges when temps come from your station
- One-line summary, 'Next 2 hours' bars and rain countdown from 15-minute precipitation,
rain/cold-aware 'Bring' chips; yesterday + 'vs usual' context from the station
- Scrubbable hourly chart (temp, rain chance, wind), 7-day range bars, AQI gauge,
details tiles instead of drawers, taller radar with location marker + alert polygons
- Skeleton loading instead of a full-screen spinner, sticky section headers, safe areas
- Server: minutely_15 precipitation, public /api/station/summary
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- data/users.json store; existing single account migrates to first admin
- Roles: admin (settings, import, users) and viewer (read-only, own password)
- Live role/disabled lookup; per-user session epoch so password changes,
resets and disabling sign that user out everywhere
- Login brute-force lockout (5 fails -> 5 min), constant-time unknown-user check
- /api/users CRUD with last-admin and self-lockout safeguards
- Account page (own password + admin user management); role-aware header
- Min password length 8; recovery token resets the primary admin and clears lockouts
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Protected /dashboard route with PBKDF2 password + HMAC-signed cookies
- First-run setup flow at /dashboard/setup
- Records Ambient station readings to daily JSONL files in app/data/station/
- Deduplicates on dateutc so 1-min polling never writes duplicate rows
- Dashboard charts: temp, humidity/dew, wind+gusts, wind rose, pressure,
rain rate, rain accumulation, UV, solar radiation
- History range selector: 1h / 6h / 24h / 7d / 30d / 90d / 1y / 2y / 3y
- Auto-downsamples to 720 points for long ranges
- Cron interval changed from 10 min to 1 min (with dedup guard)
- app/data/ added to .gitignore (contains keys and session secret)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>