Preskočiť na obsah
Jozef Čabala
Späť na projekty

Full-stack webová aplikácia

FlatWatch

Self-hosted sledovač bytov v Bratislave: číta upozornenia na nové ponuky, odstraňuje duplikáty, hodnotí každý byt podľa mojich filtrov a skutočného času pešo a MHD a dobré ponuky mi pošle e-mailom.

  • Next.js
  • React
  • TypeScript
  • Node.js
  • PostgreSQL
  • Drizzle
  • MapLibre
  • OSRM
  • OpenTripPlanner
  • Docker
Rola
Návrh a full-stack vývoj
Typ projektu
Osobný projekt
Rok
2026

Problém

Hľadanie bytu v Bratislave znamená každý deň prechádzať tie isté portály, vidieť ten istý byt viackrát od rôznych realitiek a len hádať, ako dlho bude trvať cesta do práce — inzeráty zvyčajne nepovedia viac než „blízko centra“.

Navyše dva najväčšie slovenské portály v obchodných podmienkach výslovne zakazujú automatické získavanie dát, takže zrejmé riešenie — scraper — neprichádzalo do úvahy.

Riešenie

FlatWatch využíva prístup, ktorý portály samy ponúkajú: e-mailové upozornenia na uložené vyhľadávanie. Worker na pozadí tieto upozornenia číta, stiahne každú novú ponuku, vyčistí ju, odhalí duplikáty, vypočíta skutočný čas pešo a MHD ku kotviacemu bodu, ohodnotí byt podľa mojich filtrov a pošle mi e-mail, keď sa objaví niečo dobré.

Všetko beží self-hosted — geokódovanie, trasy, MHD aj mapové dlaždice — takže netreba spravovať žiadne účty u externých API ani limity.

Ako to funguje

  1. Príjem — worker číta upozornenia cez IMAP, vytiahne z nich odkazy na ponuky a stiahne detail každej novej alebo zmenenej ponuky.
  2. Normalizácia a duplikáty — ponuky sa prevedú na jeden dátový model a porovnajú podľa šiestich signálov: súradnice, počet izieb, plocha, cena, podobnosť textu (pg_trgm) a perceptuálny hash fotiek.
  3. Skutočný čas cesty — adresy geokóduje Nominatim, pešie trasy počíta OSRM a MHD OpenTripPlanner 2 z oficiálnych cestovných poriadkov DPB (GTFS).
  4. Skóre a upozornenia — každá ponuka dostane skóre zhody podľa nastaviteľných váh; zhoda spustí okamžitý e-mail a denný prehľad.
  5. Dashboard — mapa s ponukami a trasami, filtre aj vybraná ponuka uložené v URL, galéria fotiek a nastavenia kotviaceho bodu, zdrojov, upozornení a váh skóre.

Screenshoty aplikácie

Filtre a vyhovujúce ponuky
Náhľad trasy pri prechode myšou
História ceny, cesta a dôvody zhody

Technické výzvy

Legálny prístup k dátam

Scraping vylúčili obchodné podmienky portálov. Postaviť príjem dát na e-mailových upozorneniach zachovalo hlavnú myšlienku — automatické zachytenie nových ponúk — a zároveň ostať v rámci toho, čo každý portál dovoľuje. Zdroje sú adaptéry za jedným rozhraním, takže ďalší portál znamená nový súbor, nie prepisovanie.

Ten istý byt, inzerovaný mnohokrát

Realitky ten istý byt opakovane pridávajú s trochu iným nadpisom, cenou a fotkami. Detekcia duplikátov kombinuje štrukturálne signály s trigramovou podobnosťou textu v PostgreSQL a perceptuálnym hashom fotiek, takže opakované inzeráty skončia v jednej skupine a nezahltia zoznam.

Deadlock odhalený pri ostrom behu

Prvý beh proti skutočnej schránke sa navždy zasekol. Označenie správy ako prečítanej zvnútra streamovaného sťahovania viacerých správ sa nikdy nedokončí: spojenie čaká, kým stream skončí, a stream čaká na zaseknutý príkaz. Potvrdil som to postupným zužovaním (bisecting) a opravil sťahovaním po jednej správe, pričom stream sa vždy úplne vyprázdni pred ďalším príkazom. Ten istý beh odhalil aj chybu plánovača — zaseknutý beh nechal zdroj navždy „na rade“, takže sa spúšťali prekrývajúce sa behy — teraz plánovač preskočí zdroje, ktoré ešte bežia.

Technológie a architektúra

pnpm monorepo s Next.js dashboardom a samostatným dlhodobo bežiacim Node.js workerom, ktoré zdieľajú jednu databázu PostgreSQL spravovanú cez Drizzle. Čistá doménová logika (normalizácia, skóre, duplikáty) je v samostatnom balíku bez I/O, takže sa ľahko testuje.

  • Frontend — Next.js, React, TypeScript, MapLibre so self-hosted vektorovými dlaždicami (svetlý aj tmavý štýl mapy)
  • Backend — Node.js worker (príjem cez IMAP, plánovanie, upozornenia), Server Actions
  • Dáta — PostgreSQL, Drizzle ORM, geo dotazy cez earthdistance/cube, pg_trgm
  • Trasy a geo — OSRM, OpenTripPlanner 2 (GTFS DPB), Nominatim
  • Infraštruktúra — Docker Compose na jednom serveri, prístup cez spoločné heslo

Výsledok

FlatWatch funguje od začiatku do konca na skutočných dátach: skutočné upozornenia sa spracujú, nové ponuky sa stiahnu, zbavia duplikátov, geokódujú a naplánujú trasy podľa skutočnej bratislavskej MHD a e-maily s upozorneniami — vrátane denného prehľadu — prichádzajú samy. Používam ho pri vlastnom hľadaní bytu; ďalším krokom je pridanie druhého zdroja ponúk.

Obrázok 1 z 4

Dashboard FlatWatch: vybraný byt s pešou trasou ku kotviacemu bodu na mape Bratislavy a jeho detail

Potrebujete niečo podobné?

Napíšte mi pár viet o projekte a ozvem sa s ďalším postupom.

Napíšte mi