7665146b4464747d8fb41b6d2a1a2e03f5a97fa7
- Dashboard: account-protected station data recorder with PBKDF2 auth and HMAC-signed sessions; Chart.js time-series charts with 1h–3y range selectors; wind rose canvas; auto-refresh every 2 min; 1-min polling cron - Analytics endpoints: all-time records, rain totals (7d/30d/YTD), heating/cooling degree days, CSV export, year-over-year overlay, hourly anomaly detection - Dashboard UI: pressure trend arrow, rain tile row, HDD/CDD tiles, anomaly tile, YoY toggle, collapsible records panel, CSV export, backfill progress bar - Public conditions page at /conditions (no auth) with auto-refresh every 2 min - Rain rate push alert via web-push and ntfy when threshold exceeded - Station data stored as per-day JSONL files; backfill imports up to 1yr from Ambient Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Weather App
Self-hosted weather app with animated radar. No API keys required.
Data Sources
- Weather: Open-Meteo — free, no key
- Radar: RainViewer — free, no key
- Map tiles: CartoDB Dark Matter (free, no key)
Features
- Current conditions (temp, feels-like, wind, humidity, pressure, visibility, UV, clouds)
- 24-hour hourly forecast
- 7-day daily forecast
- Embedded radar panel on the conditions page
- Full-page radar tab with animated past frames + nowcast
- Animated radar timeline with play/pause controls
- City search with autocomplete + GPS geolocation
- Auto-pans radar to searched city
- Dark mode (follows system preference)
- Responsive / mobile-friendly
Quick Start
docker compose up -d
App runs at http://localhost:3000
Pull prebuilt image
docker pull ghcr.io/nmemmert/weather:latest
docker run -d --name weather-app -p 3000:3000 ghcr.io/nmemmert/weather:latest
If the package is private, log in first:
echo "<GITHUB_PAT>" | docker login ghcr.io -u nmemmert --password-stdin
Change the port
Edit docker-compose.yml:
ports:
- "8080:3000"
Run without Docker
cd app
npm install
node server.js
Project structure
weather-app/
├── docker-compose.yml
└── app/
├── Dockerfile
├── package.json
├── server.js # Express — proxies Open-Meteo, RainViewer
└── public/
├── index.html
├── style.css
└── app.js # Weather render + dual Leaflet radar
Nginx reverse proxy
server {
listen 80;
server_name weather.yourdomain.com;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Languages
JavaScript
55.3%
HTML
26.4%
CSS
18.3%