webcam dashboard showing live snapshot feeds from Madrid and cities around the world https://madridcam.patilla.es
  • CSS 48.3%
  • JavaScript 35.2%
  • HTML 13.3%
  • Dockerfile 3.2%
Find a file
PatillaCode 5f2ff7dd96
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 5s
chore: remove stale volume mount comment from Dockerfile
2026-03-13 18:07:12 +01:00
.forgejo/workflows ci: only push latest tag, drop sha tag 2026-03-13 17:00:02 +01:00
src config: madrid feeds 30s refresh, all others 60s 2026-03-13 17:58:41 +01:00
.gitignore feat: add static site source — HTML, CSS, JS, config 2026-03-12 21:41:27 +01:00
compose.yml feat: add Dockerfile, nginx config, self-hoster compose, README 2026-03-12 21:45:36 +01:00
Dockerfile chore: remove stale volume mount comment from Dockerfile 2026-03-13 18:07:12 +01:00
nginx.conf fix: use ^~ on proxy location to prevent jpg regex from intercepting it 2026-03-13 17:18:46 +01:00
README.md docs: update README — remove volume mount instructions, document proxy URLs and swipe 2026-03-13 18:02:24 +01:00

MadridCam

A minimal, self-hosted webcam dashboard showing live snapshot feeds from Madrid and cities around the world.

  • No backend — pure static site served by nginx
  • No build step — vanilla HTML, CSS, JavaScript
  • Configurable — feeds and refresh rates defined in src/config.json

Quick Start

git clone https://forgejo.patilla.es/patillacode/madridcam.git
cd madridcam
docker build -t madridcam .
docker run --rm -p 8080:80 madridcam

Open http://localhost:8080.

Customising feeds

Edit src/config.json, commit, and push. CI will rebuild and push the image automatically.

config.json schema

{
  "title": "My Dashboard",
  "sections": [
    {
      "id": "unique-id",
      "label": "Section Label",
      "feeds": [
        {
          "id": "feed-id",
          "name": "Camera Name",
          "sublabel": "Location",
          "url": "https://cdn.skylinewebcams.com/liveXXX.jpg",
          "refresh": 30
        }
      ]
    }
  ]
}

refresh is the interval in seconds between image reloads per feed.

Note: Direct browser requests to external webcam URLs are blocked by CORS/ORB. The nginx config includes a /proxy/ location that fetches images server-side. Use /proxy/liveXXX.jpg instead of the full cdn.skylinewebcams.com URL.

Keyboard & touch shortcuts (lightbox)

Input Action
Click card Open lightbox
ESC Close
← → Cycle cameras within section
Swipe left/right Cycle cameras (mobile)
Click outside Close