Nate EmmertandClaude Sonnet 5.5 0cbebfef2a
Publish Container / publish (push) Successful in 2m42s
Cache-proof asset URLs and inline iOS touch icon
A reverse proxy in front of the app serves stale copies of static files for hours (live app.js and
sw.js were old next to new HTML). iOS also showed a letter tile (N / S) because its separate
icon download failed.

- HTML pages are served through a versioner: every local script/stylesheet/icon/manifest gets a
  content-hash query (app.js?v=…), so any change is a URL no proxy or phone has cached
- Service worker URL versioned too; SW offline lookups tolerate the query string; cache v15
- The 180px apple-touch-icon is embedded in each page as a data: URI, so the Home Screen icon
  no longer depends on a second network request

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-15 14:33:40 -04:00

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;
    }
}
S
Description
No description provided
Readme
3.2 MiB
0 Stars 1 Watchers 0 Forks
Languages
JavaScript 55.3%
HTML 26.4%
CSS 18.3%