Mateo.

Kreni — live Zagreb transit map

Kreni started as a personal tool for checking when the next tram was coming. It ended up with 4,435 active users in its first month, a write-up in Večernji list, and a peak of 660 people on it in a single day — none of which I expected.

The core idea: preprocess Zagreb’s entire GTFS dataset (114 MB) into small JSON shards at deploy time, serve them from a CDN, and decode live vehicle positions from the GTFS-Realtime protobuf feed through a Cloudflare Worker. No backend server, no database — the browser does the heavy lifting.

Numbers

Active users (first month)4,435
Total interactions73,700+
Page views35,495
Peak day660 users (Mar 29, 2026)
Routes selected1,096
Onboarding completions2,072

Traffic came from Večernji list (~615 referrals), Facebook (~880), and 2,200+ direct visits.

What it does

  • Live bus and tram positions with interpolation between GTFS-RT updates
  • HŽPP train tracking as a separate map mode
  • City layers: parking zones, Nextbike stations, road closures, water fountains, EV charging, cycling paths, student cafeterias
  • Delay information from trip update feeds
  • PWA — installable, schedule data works offline
  • Croatian, English and German

How it works

At build time, a Python + shell pipeline downloads the GTFS zip from ZET (and HŽPP for trains), slices it into shards, and writes them to public/data/. Vite builds the SPA; GitHub Actions deploys to Cloudflare Pages.

At runtime, a Cloudflare Worker handles everything the browser can’t fetch directly: proxies the GTFS-RT protobuf with edge caching (~7s), serves road closure data from Zagreb open data (~1h cache), Nextbike JSON (~15s cache), and parsed service alerts stored in KV. A cron job runs every 10 minutes to aggregate congestion stats.

Initial load is ~450 KB. Each map interaction fetches 3–70 KB of shard data on demand from the CDN.

Stack

  • React 19 + Vite 7, TypeScript throughout
  • Leaflet for the map
  • Tailwind CSS v4 + DaisyUI 5
  • Cloudflare Pages + Worker + KV + R2
  • GitHub Actions for build, deploy, GTFS processing and service alert parsing

Visuals

Wide screen

Mobile