Weather with attitude. Material 3 UI whose color scheme is generated live from the sky.
- 6 weather sources, cross-checked: Open-Meteo, MET Norway, WeatherAPI.com, plus ECMWF / NOAA GFS / DWD ICON models. Current conditions are the median; the Source check card shows who agrees.
- Material 3 dynamic color: the whole palette re-seeds from the current conditions (clear, rain, snow, storm, golden hour, night), light/dark/auto.
- Today / Forecast / Map / Air / Sky tabs: hourly + 10-day, model-confidence, rain nowcast, AQI, pollen, UV, alerts (NWS, Meteoalarm, WeatherAPI), moon, planets, ISS, meteor showers.
- Map (MapLibre, all keyless): themed vector basemap from OpenFreeMap or Esri satellite imagery; RainViewer radar (proxied through
/api/radarfor CORS + CDN caching); live EUMETSAT infrared satellite clouds (/api/sat, Meteosat every 15 min, global ring elsewhere); a 24 h temperature field and animated wind streamlines from an Open-Meteo lattice (/api/grid, fixed 8×8 blocks so responses cache across users). - Design: Material 3 Expressive with dynamic color seeded from the sky, plus a Tomato brand layer (Tomato is a red rabbit: logo + mascot geometry in
lib/rabbit.ts, static icons regenerated withnode scripts/gen-icons.mjs; shape masks generated byscripts/gen-shapes.py). MapLibre's worker is copied topublic/maplibreonnpm install(scripts/copy-maplibre.mjs). - Tomato: AI chat + daily summary (OpenRouter and a keyless provider race with retries; if both fail, the summary is built from the forecast and chat uses offline quips). Three attitudes: mild, rude, feral.
npm install
cp .env.example .env # then fill in keys
npm run dev| Variable | Purpose |
|---|---|
WEATHER_API |
WeatherAPI.com key (extra source, alerts, AQI). Optional but recommended. |
AI_KEY |
OpenRouter key (sk-or-…) for Tomato. Optional; without it a keyless provider is used. |
Everything else is keyless.