iTwin Engineering
← All work

Case study · 2026

Balkan Borders

Live border waits and cameras for the Balkans, built from official sources and refreshed every hour.

Role
Product, design, data and engineering
Team
Andrej Janev, Filip Janev
Stack
Astro, Python, GitHub Actions, Cloudflare, Expo
Timeline
Started July 27, 2026
balkanborders.com
Balkan Borders homepage: live waits for the main crossings, a HAK camera frame from Bajakovo and fuel prices

Screenshots of the live site, October 22, 2026.

0
border crossings
0
live cameras
0
languages
0
pages
0+
automated tests
0h
refresh cycle

01The problem

The wait is public. It just isn't findable.

On a Balkan road trip, the border is the one part nobody can plan. Queues run from minutes to hours, and they change by direction, by day and by hour, most of all in summer.

The official figures exist, but they are scattered: auto-club cameras in Croatia, border police readings in Serbia, video feeds in North Macedonia, each on its own site, in its own language and format. Bosnia and Herzegovina and Montenegro publish no wait figure at all.

02The approach

One polite bot, every hour

Each official source gets its own small Python scraper that reads at the source's own pace, under a named user agent that says who we are. Everything is normalised into one schema, checked by a freshness gate, and rebuilt into a static Astro site that Cloudflare serves from the edge. GitHub Actions runs the whole loop every hour.

> refresh --hourly

  1. 01
    fetch
    official sources
  2. 02
    normalise
    one schema
  3. 03
    check
    freshness gate
  4. 04
    build
    1,332 pages × 6 languages
  5. 05
    deploy
    Cloudflare edge

repeats every hour · deploy refused if data is corrupt▋

03The product

What a driver sees

One page per crossing: the wait in each direction, the live cameras, who published the figure and when. Where a driver at the border reports something different from the official reading, the report leads, because the person in the queue knows more than a number posted once a day.

  • Wait by direction, for cars and trucks
  • 112 live cameras across 48 crossings
  • Driver reports that lead when they disagree with the official figure
  • Fuel prices, tolls and EU Entry/Exit System guidance
  • Six languages: English, Croatian, Serbian, Macedonian, German, Albanian
balkanborders.com/borders/bajakovo-batrovci/
The Bajakovo–Batrovci crossing page: wait per direction, its sources, a driver report and the live HAK camera
The Bajakovo–Batrovci crossing page on a phone
balkanborders.com/cameras/
The cameras page: 112 cameras across 48 crossings, grouped by border

04The hard parts

01

Sourcing honestly

Every scraper identifies itself with a named bot, reads no faster than the source publishes, and never solves a CAPTCHA or pretends to be a browser. Where a CDN blocks us, we ask the source before working around it. Where a source publishes nothing, the page says so instead of guessing.

02

Deploys that stall

The hosted build queue stalled four times in the first season. Rather than babysit it, the hourly job now checks how far production is behind and, past two hours, ships the site through a guarded break-glass path.

03

Saying no to the wrong demand

A third of search impressions were for camera queries owned by an auto-club brand. We measured it: ranking first there earned no more clicks than ranking fifteenth. So we stopped chasing it and put the effort into wait-time searches, which do convert.

05The result

July 28

first day with Google impressions, one day after the first commit

748,748

Google impressions in the first twelve weeks, with 14,099 clicks

29,619

impressions on the peak day, August 7, from searchers in 178 countries overall

8.3

average Google position across every query, July 28 to October 20

06What we'd do differently

Over 99% of search demand landed on individual crossing pages; route and corridor pages drew a few hundred impressions between them. We would have put every early hour into the crossing pages and built the rest only once a reader asked for it.

07What's next

A native app built with Expo, sharing its core with the site, is in progress. Partner sites can already embed a live crossing widget, and the season ahead is about getting those embeds onto the travel sites drivers already use.

> next --project

Have something that should run by itself?