Cestovný WordPress magazín Hoplo stojí na jednej základnej myšlienke: čitateľ by nemal opúšťať článok preto, aby si dohľadal informácie, ktoré k článku prirodzene patria a bol o niečo lepší než tradičný blog alebo magazín. Keď niekto číta text o Bangkoku, Bangkok City Break alebo thajskom itinerári, kladie si v hlave rovnaké otázky. Aké je tam počasie, čo potrebuje na vstup ako slovenský cestovateľ, koľko zaplatí za eurá, koľko hodín letu ho čaká, aký čas je tam práve teraz. Tieto otázky nemajú nič spoločné so SEO ani s redakčnou kvalitou textu. Sú to servisné informácie, ktoré k cestovnému článku jednoducho patria.
Dostupné WordPress pluginy tento problém neriešia komplexne. Každý rieši jeden aspekt dobre: počasie, mapu alebo menový kurz. Žiadny ich však nekombinuje, a ani jeden nevedel pracovať s vízovými podmienkami pre konkrétny pas alebo vypočítať vzdialenosť z konkrétneho referenčného bodu. Bol to presne ten typ medzery, ktorý si vyžiadal vlastné riešenie od základov.
Výsledkom je Hoplo Travel Widget: 2 140 riadkov produkčného kódu, ktoré dnes bežia na živom WordPress magazíne bez toho, aby redaktor musel vedieť, čo je REST endpoint. Widget sa zobrazuje automaticky na začiatku každého článku, hneď za perexom. Čitateľ ho vidí ešte predtým, ako sa dostane k samotnému textu. Redakčný workflow trvá menej ako dve minúty a čitateľ dostane sedem kategórií aktuálnych informácií bez jediného kliknutia navyše.
Stack realizácie: technológie a pluginy, na ktorých widget stojí

Pred popisom architektúry je dôležité pomenovať celý technologický stack, pretože každé rozhodnutie malo dopad na bezpečnosť, výkon alebo redakčný komfort.
WordPress vrstva
- WordPress (aktuálna verzia) ako CMS a aplikačná platforma
- WPCode slúži na správu PHP snippetov bez zásahu do functions.php; widget je implementovaný v dvoch snippetoch (frontend + admin modul)
- Advanced Custom Fields (ACF) zabezpečuje správu redakčných metapolí; widget číta štyri polia definované v ACF skupine
- WordPress REST API tvorí natívnu WordPress vrstvu pre vlastné endpointy
- WordPress Transients API funguje ako natívny caching mechanizmus pre externe získané dáta
Externé dátové zdroje (Bezplatné API)
- WeatherAPI.com poskytuje aktuálne počasie a trojdňovú predpoveď; prístup funguje výhradne cez server, API kľúč je uložený v wp-config.php
- Frankfurter.dev dodáva menové kurzy EUR; ide o voľné API bez limitu, volané priamo z prehliadača
- RestCountries.com poskytuje geografické dáta krajiny (súradnice centra, susedia, vlajka, kontinent); volané priamo z prehliadača
- passport-index-data (GitHub repozitár imorte) je JSON dataset vízových podmienok pre slovenský pas; sťahuje sa a cachuje na serveri
- Nominatim / OpenStreetMap slúži na geokódovanie názvov miest na súradnice a funguje ako rezervný zdroj
Frontend
- Vanilla JavaScript bez externých knižníc, bez jQuery, bez Reactu
- Leaflet.js v1.9.4 obsluhuje interaktívnu mapu; načítava sa dynamicky len na stránkach s widgetom
- CSS Custom Properties tvoria dizajnový systém widgetu vrátane Dark Mode bez JavaScriptu
- Inline IIFE (Immediately Invoked Function Expression): celý JS je generovaný PHP a vložený priamo do HTML, bez externých HTTP requestov na JS
Vývojové nástroje
- OpenAI Codex – asistoval pri generovaní boilerplate kódu (registrácia endpointov, sanitizačné funkcie, volania Transients API)
- Claude Code – Statické HTML prototypy slúžili na vizuálne overenie UI pred prvým PHP riadkom
Čo widget zobrazuje a prečo to nie je len pekný blok s počasím
Widget zobrazuje sedem kategórií informácií súčasne a robí to automaticky, bez redakčného zásahu po prvotnom nastavení:
- aktuálne počasie aj trojdňová predpoveď z WeatherAPI
- vízové podmienky pre slovenský pas zo živého datasetu
- menový kurz cieľovej meny voči euru z Frankfurter.dev
- lokálny čas s rozdielom oproti Bratislave
- vzdialenosť a odhadovaný čas letu z Bratislavy
- zoznam susedných krajín
- interaktívna Leaflet mapa
Čitateľ nemusí nič hľadať. Všetko sa načíta pri otvorení stránky, automaticky, na základe nastavení uložených priamo v článku.
Dva režimy, jedna zdieľaná logika: city mód pre konkrétne destinácie, country mód pre prehľad krajiny

Widget beží v dvoch módoch s rozdielnym správaním napriek zdieľanej logike. V city móde — napríklad pri článku o Bangkoku — sa použijú presné súradnice mesta z WeatherAPI a mapa sa zobrazí so zoomom na úrovni mestskej štvrte. V country móde, teda pri článku o Thajsku ako celku, sa stiahnu súradnice stredu krajiny z RestCountries.com a mapa pokryje celé územie s nižším zoomom.
Tento rozdiel ovplyvňuje aj presnosť počasia: city mód hľadá konkrétne meteorologické miesto, country mód zobrazí podmienky pre hlavné mesto krajiny. Oba módy zdieľajú rovnaké renderovanie, rovnaké endpointy aj rovnakú cachovaciu logiku. Mód určuje len vstupné parametre a granularitu výstupu.
Prípravná fáza: research, prototyp a dátový kontrakt pred prvým riadkom kódu
Príprave sa venoval výrazne viac času ako akejkoľvek inej fáze projektu. Porovnali sa dostupné API: WeatherAPI, OpenWeatherMap, Frankfurter.dev, RestCountries.com a passport-index-data na GitHube. Posúdili sa ceny, limity volaní a kvalita dokumentácie. Výsledkom tejto fázy boli tri kľúčové rozhodnutia, ktoré predurčili celú architektúru.
- Žiadna obchodná logika nebude v prehliadači. Všetky API kľúče zostanú na serveri. Prehliadač bude volať len vlastné WordPress endpointy, nie externé služby priamo.
- Celý dizajn sa overí na statickom HTML prototype pred tým, než sa napíše jediný PHP riadok. Iterovalo sa cez tri vizuálne varianty a testovalo sa na mobile, tablete aj desktope. Až po schválení výzoru sa otvoril PHP editor.
- Pred prvým endpointom sa definoval presný dátový kontrakt. Na papier sa napísal presný JSON, ktorý musí backend vrátiť — každé pole, každý typ, každý fallback. Tento kontrakt sa stal referenčným dokumentom pre celý vývoj a minimalizoval priestor pre nekonzistentné správanie pri integrácii.
Rola OpenAI Codex: kde urýchlil prácu a kde nestačil
Spolupráca s AI pri tomto projekte bola realistickejšia, ako sa čakalo. Codex skvele generoval boilerplate: registráciu WordPress REST endpointov, sanitizačné funkcie aj štruktúru volaní Transients API. Na tieto rutinné časti ušetril niekoľko hodín. Kde zlyhal, bol kontext projektu. Scoring algoritmus pre lokality musel pochádzať z pochopenia konkrétneho problému, nie z promptu. AI vygenerovala funkciu, ktorá vracala vždy prvý výsledok WeatherAPI bez akejkoľvek validácie. V izolácii to fungovalo, no na produkčnom projekte bolo toto riešenie nepoužiteľné. Každá dôležitá funkcia musela byť pochopená, otestovaná a v mnohých prípadoch prepísaná.
ACF nastavenie: štyri polia, ktoré riadia celý widget

Redakčná vrstva widgetu je postavená na Advanced Custom Fields. Bola vytvorená skupina polí s názvom Travel Widget, priradená na post type post, a obsahuje štyri polia, ktoré riadia celé správanie widgetu.
Popis jednotlivých polí
- tw_enabled — toggle typu True / False s labelom „Zobraziť travel widget“. Predvolená hodnota je 0 (vypnuté). Ak je toto pole vypnuté, widget sa na stránke vôbec neobjaví — ani v DOM, ani ako prázdny blok.
- tw_mode — select s labelom „Typ widgetu“. Má dve možnosti: country (Krajina) a city (Mesto). Predvolená hodnota je country. Pole je povinné. Výber módu priamo určuje správanie všetkých následných volaní, od WeatherAPI query až po zoom mapy.
- tw_country — textové pole s labelom „Krajina pre API“. Je povinné. Redaktor zadáva názov krajiny po anglicky (Japan, Thailand, Italy). Pole sa používa v oboch módoch: v country móde ako primárny vstup, v city móde ako doplnkový kontext pre scoring algoritmus.
- tw_city — textové pole s labelom „Mesto pre API“. Nie je povinné. Zobrazuje sa len vtedy, keď je tw_mode nastavený na city. Podmienená logika je nastavená priamo v ACF rozhraní. Redaktor zadáva názov mesta po anglicky (Tokyo, Bangkok, Milan).
Ako ACF podmienená logika funguje v praxi
Podmienené zobrazenie poľa tw_city je vyriešené natívne v ACF bez akéhokoľvek JavaScriptu. V nastaveniach poľa sa definuje podmienka: „Zobraz toto pole, ak tw_mode sa rovná city.“ ACF toto zabezpečí automaticky v editore aj v admin module. Redaktor vidí pole pre mesto len vtedy, keď je relevantné, a nemôže omylom zadať mesto pri country móde.
Redakčný workflow trvá menej ako dve minúty
Celý postup nastavenia widgetu pre nový článok pozostáva z niekoľkých krokov:
- Redaktor otvorí článok a zaškrtne toggle „Zobraziť travel widget“.
- Z dropdownu vyberie krajinu alebo miesto.
- Vyplní pole tw_country anglickým názvom krajiny.
- Ak ide o city mód, doplní aj tw_city.
- Po uložení je widget aktívny.
Pozicionovanie widgetu: prečo sa zobrazuje na začiatku článku
Widget je zámerne umiestnený na začiatok každého článku, hneď za perexom, ešte pred prvým odstavcom hlavného textu. Toto rozhodnutie vychádza z používateľskej logiky: servisné informácie (počasie, víza, kurz, čas) majú najväčšiu hodnotu vtedy, keď ich čitateľ vidí pred tým, ako začne čítať. Sú orientačným rámcom pre celý text, nie doplnkom na konci.
Technicky je toto vyriešené cez WordPress filter the_content s prioritou nastavenou na raný hook. Filter zachytí obsah článku, pridá HTML widgetu na začiatok reťazca a až potom vráti celý obsah na výstup. Widget teda nie je shortcode — nevkladá sa do tela článku ručne, ale pripája sa automaticky pred obsah pri každom renderovaní.
Ochrana pred dvojitým vykreslením vďaka jednej statickej premennej
WordPress filter the_content môžu volať rôzne témy a pluginy viackrát na jednej stránke. Bez ochrany by sa widget objavil dvakrát alebo viackrát. Riešenie je jednoduché: statická premenná $rendered v hooku hoplo_travel_widget_append_to_content. Pri prvom vykreslení sa nastaví na true a každé ďalšie volanie funkcia ignoruje. Jeden riadok kódu, nulové problémy s akoukoľvek témou.
Architektúra: WordPress ako proxy a agregátor, prehliadač len zobrazuje výsledky

hoplosk travel widget3
Celý systém stojí na princípe Backend-For-Frontend (BFF). WordPress prijme požiadavku od prehliadača, zavolá externé API na serveri, skombinuje výsledky a vráti čistý JSON. Prehliadač nevidí žiadny API kľúč, nedrží žiadnu biznis logiku a slúži výhradne na zobrazenie dát. Pre čitateľa bez serverového vzdelania je to ako objednávka cez čašníka: hosť nechodí do kuchyne sám.
Implementácia je rozdelená do dvoch WPCode snippetov. Prvý obsahuje všetku frontendovú logiku: shortcode, REST endpointy, auto-insert na začiatok obsahu, Vanilla JS a CSS. Druhý je izolovaný admin modul — inline editor v zozname článkov. Táto separácia má jednoduchý dôvod: keď sa mení vizuál widgetu, nedotýka sa admin logiky, a naopak.
REST API endpointy: bezpečná brána k externým dátam
Widget komunikuje s dvoma vlastnými WordPress REST endpointmi: /hoplo-travel/v1/weather a /hoplo-travel/v1/weather/visa. Oba sú verejné, dostupné bez prihlásenia, no zároveň bezpečné — žiadne API kľúče sa nikdy nedostanú do prehliadača.
Verejný prístup je vyriešený cez filter rest_authentication_errors s prioritou PHP_INT_MAX. Filter skontroluje, či prichádzajúca požiadavka smeruje na prefix /hoplo-travel/v1/ a či ide o GET metódu. Ak áno, vráti null a WordPress požiadavku povolí aj bez autentifikácie. Pre všetky ostatné routy sa filter správa štandardne. Toto riešenie je chirurgicky presné: neotvára bezpečnostnú dieru do celého REST API, len do presne definovanej časti.
Endpoint /weather: päťkrokové spracovanie požiadavky
Endpoint prijme post_id, načíta ACF nastavenia, overí API kľúč WeatherAPI, zostaví zoznam kandidátnych vyhľadávacích reťazcov a iteruje cez nich, kým nenájde výsledok s dostatočným skóre. Prvý úspešný výsledok sa uloží do WordPress Transients cache na 30 minút. Každé ďalšie volanie počas tejto doby vráti uloženú odpoveď bez jediného externého requestu.
Endpoint /visa: päť vízových stavov s farebným rozlíšením a slovenským popisom
Vízový endpoint stiahne celý JSON dataset z GitHub repozitára imorte/passport-index-data, extrahuje riadky pre slovenský pas, vyhľadá požadovanú krajinu podľa ISO2 kódu a vráti stav aj počet dní. Možných stavov je päť:
- visa free
- visa required
- eta
- evisa
- visa on arrival
Každý stav má vlastný farebný badge a slovenský popis. Ak dataset nie je dostupný, endpoint vráti záložnú hlášku namiesto serverovej chyby.
Dôležité upozornenie k vízovým podmienkam: Dáta pochádzajú z automaticky spracovaného datasetu passportindex.org a môžu zaostávať za reálnym stavom legislatívy. Vízové podmienky sa menia, niekedy bez dlhého predupozornenia. Pred každou cestou je nevyhnutné overiť aktuálny stav na oficiálnom zdroji: mzv.sk (Ministerstvo zahraničných vecí a európskych záležitostí SR). Informácia v widgete slúži ako orientačný prehľad, nie ako záväzný právny dokument.
Najkomplexnejšia funkcia projektu: scoring algoritmus pre lokality
Funkcia hoplo_travel_widget_resolve_weather_location je architektonicky najzaujímavejšia časť celého projektu. WeatherAPI vracia výsledky pre akýkoľvek vyhľadávací reťazec, vrátane výsledkov z inej krajiny. Ak redaktor zadá „Bali“ a „Indonesia“, WeatherAPI môže vrátiť Bali v Indii namiesto indonézskeho ostrova Bali. Funkcia tento problém rieši bodovacím systémom.
Pre každý kandidátny vyhľadávací reťazec (samotné meno mesta, meno s krajom, meno s krajinou) sa zavolá WeatherAPI, získajú sa výsledky a každému sa pridelí skóre:
- +4 body za presnú zhodu názvu lokality
- +3 body za zhodu regionálnych dát
- +2 body za správny formát vyhľadávacieho reťazca
- −2 body, ak výsledok zodpovedá hlavnému mestu namiesto cieľového mesta
Víťaz s najvyšším skóre postúpi do cachovania.
ISO2 validácia ako trojitá poistka
Samotné skóre nestačí. Funkcia ešte overí príslušnosť výsledku ku krajine trojitou kontrolou: priama zhoda názvu krajiny, zhoda ISO2 kódu v URL výsledku a zhoda sanitizovaného slug názvu. Ak ani jedna podmienka neprejde, výsledok je zamietnutý a funkcia prejde na ďalšieho kandidáta. Táto poistka zachytí prípady, keď WeatherAPI vráti správne meno mesta, no z nesprávnej krajiny.
Caching stratégia: prečo aj virálny článok nevyčerpá mesačný limit API volaní
WordPress Transients API tvorí chrbticu celej cachovacej vrstvy. Cache kľúče sa generujú ako md5() hash z kombinácie lokality, počtu dní a jazyka – každá unikátna kombinácia má vlastný záznam v databáze. Periódy cachovania sú nastavené takto:
- Počasie: 30 minút
- Vízový dataset: 12 hodín
- Dáta krajiny z RestCountries: 24 hodín
Praktický dopad: keď článok o Thajsku číta sto návštevníkov hodinu po sebe, WeatherAPI dostane maximálne dve požiadavky za hodinu, nie sto. Pre projekt s obmedzeným API plánom je to rozdiel medzi udržateľným riešením a mesačným doplatkom za presiahnutý limit volaní.
Výkon a načítavanie: prečo je widget rýchly aj pri prvom načítaní

Výkon widgetu bol navrhnutý s niekoľkými princípmi, ktoré sa vzájomne dopĺňajú.
Inline JS bez externých závislostí. Celý JavaScript je generovaný PHP a vložený priamo do HTML stránky ako inline IIFE. Prehliadač nepotrebuje stiahnuť žiadnu externú JS knižnicu pred zobrazením widgetu. Výsledkom je nulový počet blokujúcich HTTP requestov na JavaScript.
Leaflet sa načíta len keď treba. CSS a JS pre Leaflet (v1.9.4) sa načítavajú dynamicky výhradne na stránkach, kde je widget prítomný. Stránky bez widgetu — kategórie, archívy aj homepage — nenačítajú knižnicu vôbec. Toto eliminuje zbytočný overhead pre väčšinu pageviews.
Asynchrónne volania bez blokovania renderovania. Widget sa vloží do HTML ihneď pri načítaní stránky ako prázdna kostra s loading stavom. JavaScript následne asynchrónne zavolá REST endpoint a keď dáta prídu, DOM sa aktualizuje. Používateľ vidí stránku okamžite a widget sa doplní bez toho, aby zdržiaval zobrazenie obsahu.
Server-side caching eliminuje opakovanie API volaní. Prvé načítanie článku spustí reálne API volania. Každé ďalšie načítanie počas cachovacej periódy vráti uloženú odpoveď priamo z WordPress databázy bez jediného externého requestu.
CSS Custom Properties bez JavaScriptu. Celý dizajnový systém widgetu stojí na CSS premenných: –bg, –accent, –th a ďalšie. Dark Mode sa aktivuje predefinovaním týchto premenných pri detekcii scheme=dark alebo data-theme=dark na rodičovskom elemente — bez JavaScriptu, bez duplicitného CSS, bez reflow.
Inline SVG ikony bez CDN. Objekt S v JavaScripte obsahuje presne definované SVG ikony pre každý meteorologický stav. Funkcia wxSVG mapuje kódy počasia z WeatherAPI (1000 = slnko, 1063 = dážď) na konkrétnu SVG štruktúru. Widget zobrazí správnu ikonu pre akúkoľvek meteorologickú podmienku bez toho, aby kontaktoval CDN alebo ikonový font.
Admin modul: redaktor nastavuje widget zo zoznamu článkov bez toho, aby otvoril editor
Vlastný stĺpec „Travel widget“ v zozname článkov zobrazuje inline formulár s toggleom, výberom módu, poľom pre krajinu a mesto. Redaktor vidí stav widgetu pre každý článok naraz a mení nastavenia bez toho, aby musel otvoriť editor. Pre magazín s desiatkami článkov o rôznych destináciách je toto zásadná úspora času. Nastavenie celej stránky zoznamu trvá minúty, nie hodiny.
Funkcia submitTravelWidgetRow pri každom kliknutí na „Uložiť“ dynamicky vytvorí neviditeľný formulárový element, naplní ho aktuálnymi hodnotami z riadku a odošle POST request na admin-post.php. Tlačidlo „Save All Edits“ v hlavičke stĺpca zberie dáta zo všetkých viditeľných riadkov, zabalí ich do JSON payloadu a odošle ich jedinou požiadavkou. Backend handler pri hromadnom ukladaní overí current_user_can(‚edit_post‘, $post_id) pre každý záznam zvlášť — oprávnenie sa kontroluje per post, nie globálne. Každý ukladací handler overuje nonce aj oprávnenia pred akýmkoľvek zápisom do databázy.
Frontend: Vanilla JS aplikácia bez externých závislostí

Rozhodnutie nepoužiť jQuery ani React nebolo ideologické. Bolo merateľné. Celý frontend je jeden uzavretý IIFE generovaný PHP a vložený inline do HTML — nulový HTTP request na načítanie knižnice, nulový risk konfliktov verzií, nulová závislosť na iných pluginoch. Funkcia haversine vypočíta vzdušnú vzdialenosť medzi Bratislavou a ľubovoľnou destináciou so zohľadnením zakrivenia Zeme. Výsledok odovzdá funkcii flightTime, ktorá heuristicky odhadne dĺžku letu.
Kratšie trasy sa počítajú s nižšou priemernou rýchlosťou kvôli vzletu a pristátiu, dlhé trasy s rýchlosťou diaľkových letov okolo 850 km/h. Číslo nie je letová rezervácia, no pre čitateľa cestovného článku je oveľa cennejšie ako surová vzdialenosť v kilometroch.Každá sekcia renderovacieho kódu obsahuje podmienené vetvy: ak krajina nemá susedov, ak kurz nie je dostupný, ak timezone chýba. Funkcia showError() zobrazí zrozumiteľnú správu namiesto prázdneho widgetu alebo nezachytenej JS chyby v konzole.

Zdroj obrázku : https://sketchplanations.com/the-haversine-formula
Plánované ďalšie implementácie
Prvá verzia widgetu pokrýva slovenský trh a bola navrhnutá zámerne sústredene. Existuje však niekoľko konkrétnych rozšírení naplánovaných pre najbližšie verzie.
Multi-destinačný mód s rozbaľovacím menu: čo skutočne rieši a kde sú jeho hranice
Jednou z najžiadanejších funkcií je možnosť zobraziť v jednom widgete viacero destinácií naraz – napríklad pri článku o stredoeurópskych hlavných mestách alebo pri porovnávacom obsahu. Plánovaná implementácia počíta s rozbaľovacím menu (dropdown), kde si čitateľ vyberie destináciu z predpripraveného zoznamu.
Príkladový use case: článok o víkendových výletoch zo Slovenska by zobrazil widget s výberom medzi Prahou, Viedňou a Budapešťou. Po výbere mesta sa bez opätovného načítania stránky aktualizujú všetky sekcie widgetu pre zvolenú destináciu. Technicky by toto znamenalo:
- rozšírenie ACF skupiny o pole pre zoznam destinácií (repeater alebo textarea s ISO kódmi)
- úpravu JS logiky widgetu o event listener na zmenu dropdownu
- volanie existujúcich REST endpointov s novou destináciou ako parametrom
Backend endpointy by nevyžadovali zmenu, pretože pracujú parametricky od začiatku. Caching by fungoval identicky, len s viacerými kľúčmi pre rôzne destinácie. Pri vízových podmienkach je potrebné byť úprimný v tom, čo dropdown reálne prináša a čo nie. Vízový badge sa dlhodobo nevníma ako právny dokument ani náhrada za overenie na mzv.sk. Funguje ako orientačný signál, ktorý eliminuje väčšinu zbytočných vyhľadávaní. Pre bežné destinácie s dlhodobo stabilnými vízovými vzťahmi — krajiny Schengenu, Japonsko, Južná Kórea, väčšina európskych krajín — bude badge takmer vždy presný a jeho hodnota pre čitateľa je jednoznačná: okamžité potvrdenie bez opustenia článku.
Pre destinácie s nestabilnejšou vízovou politikou, niektoré krajiny Blízkeho východu, strednej Ázie alebo krajiny v rýchlo sa meniacej diplomatickej situácii , môže dataset zaostávať aj o mesiace. Práve tu dropdown vytvára zaujímavú dynamiku: ak čitateľ porovnáva tri destinácie v jednom článku, badge plní úlohu prvého filtra. Zelená farba hovorí, že pravdepodobne nepotrebuje vízum a môže čítať ďalej. Červená farba hovorí, že táto destinácia si vyžaduje overenie na mzv.sk ešte pred plánovaním. V oboch prípadoch badge znižuje trenie, aj keď jeho presnosť nie je stopercentná.
Inak povedané: vízová sekcia nie je vízový konzultant. Je to semafor. Zelená znamená pravdepodobne v poriadku ale overte si to. Červená znamená pozor, toto si naozaj overte. Dropdown tento semafor rozširuje na viacero destinácií naraz, čo je presne ten typ porovnávacieho obsahu, pri ktorom má cestovný magazín najväčšiu šancu byť skutočne užitočný. Disclaimer s odkazom na mzv.sk zostane v každej vízovej sekcii naďalej, bez ohľadu na to, koľko destinácií dropdown zobrazuje. Automatizácia vízových dát je rozumný kompromis pre prvú verziu — nie dôvod na ospravedlnenie, ale na transparentnosť.
Lokalizácia pre český trh
Fixné hodnoty pre slovenský trh, súradnice Bratislavy, slovenský text a vízové dáta pre SK pas – sú v kóde napevno. Lokalizácia pre český trh si vyžiada zmenu referenčných súradníc pre výpočet vzdialenosti (Praha namiesto Bratislavy), iný pas pre vízové podmienky (CZ namiesto SK) a preklad UI textov. Ide o niekoľkohodinovú prácu, nie o minútovú zmenu, no architektonicky je widget na túto zmenu pripravený. Všetky pevné hodnoty sú sústredené na jednom mieste v konfiguračnom objekte.
Backend proxy pre Frankfurter.dev a RestCountries
Menový kurz a dáta krajiny v súčasnosti prichádzajú priamo do prehliadača. Pre bežnú návštevnosť to nevadí. Pri virálnom článku s tisíckami súbežných čitateľov by Frankfurter.dev mohol obmedziť prístup a widget by zobrazil záložnú hodnotu namiesto kurzu. Presun na vlastný backend endpoint je logický ďalší krok: jedna hodina navyše pri vývoji eliminuje celú kategóriu potenciálnych problémov pri vyššej návštevnosti.
Vlastný hosting vízového JSON datasetu
Dataset imorte/passport-index-data môže zmeniť formát alebo zmiznúť. Záložné správanie pri nedostupnosti existuje, no nie je dlhodobým riešením. Plánuje sa nastaviť automatické sťahovanie aktualizovaného súboru na vlastný server prostredníctvom pravidelného cron jobu. Závislosť na externom GitHub repozitári sa tým definitívne eliminuje.
Limity, ktoré boli vedome prijaté v prvej verzii
Niektoré architektonické rozhodnutia boli urobené zámerne obmedzujúce – nie preto, že by lepšie riešenie neexistovalo, ale preto, že prvá verzia musela fungovať, nie byť dokonalá.
- Pevne zakódované lokálne hodnoty. Súradnice Bratislavy, slovenský text a vízové dáta pre SK pas sú v kóde napevno. Toto rozhodnutie zjednodušilo prvú verziu, no lokalizácia pre iný trh si vyžiada viac ako preklad – budú potrebné iné súradnice, iný pas aj iné referencie v UI.
- Priame volania z prehliadača. Menový kurz a dáta krajiny prichádzajú priamo do prehliadača, nie cez backend proxy. Pre bežnú návštevnosť to nevadí, no pri virálnom článku s tisíckami súbežných čitateľov by Frankfurter.dev mohol obmedziť prístup.
- Automatizovaný vízový dataset. Vízové podmienky z datasetu passportindex.org nie sú stopercentne overený právny zdroj. Dataset je priebežne aktualizovaný, no môže zaostávať za reálnymi zmenami. Widget zobrazuje disclaimer s odkazom na mzv.sk. Vždy overte aktuálny stav na mzv.sk. Zdroj: passportindex.org.
Výsledky a čo sa reálne dosiahlo
Widget v súčasnosti beží na viac ako 30 článkoch pokrývajúcich destinácie na šiestich kontinentoch. Nastavenie widgetu pre nový článok trvá redaktorovi menej ako dve minúty. Porovnateľné riešenie od externého PHP tímu – s rovnakými funkciami, rovnakou bezpečnosťou a redakčným komfortom – by sa pohybovalo v rozmedzí 2 500 až 4 500 eur za vývoj. Celkový čas strávený na projekte vrátane researchu, prototypovania a testovania bol okolo 80 hodín.
Toto číslo nie je argument za to, aby každý projekt staval vlastné riešenia. Je to argument za to, že pochopenie architektúry a trpezlivá príprava dokážu dnes s pomocou AI produkovať výsledky, ktoré by pred piatimi rokmi vyžadovali celý tím.
Záverečné zhodnotenie
BFF architektúra bola správna voľba od prvého dňa. Skryté API kľúče, centralizovaná logika a čistý frontend sú vlastnosti, pri ktorých by sa zostalo pri akomkoľvek podobnom riešení. Prototypovanie pred kódovaním ušetrilo minimálne týždeň prepracovávania. Scoring algoritmus pre lokality dal istotu, že widget bude fungovať aj pri neštandardných vstupoch od redaktorov. Caching cez Transients API je riešenie, ktoré by sa odporučilo každému WordPress projektu s externým API: jednoduché, spoľahlivé, bez externých závislostí.
Keby sa projekt robil od začiatku dnes, viaceré veci by dopadli inak. Frankfurter.dev a RestCountries by od prvého dňa komunikovali cez backend endpoint, nie priamo z prehliadača. Vlastný hosting vízového JSON datasetu sa odkláda príliš dlho a tento dlh sa plánuje splatiť ako jeden z prvých ďalších krokov. Lokalizácia pre český trh je rozšírenie s reálnym obchodným zmyslom a architektúra na ňu čaká pripravená.
Sú však aj veci, ktoré by sa pri opakovanom štarte urobili rovnako. Vízové dáta z automatizovaného datasetu nie sú dokonalé, no pre prvú verziu bola táto voľba správna. Alternatívou by bolo buď vynechať vízovú sekciu úplne, alebo investovať neprimerane veľa času do budovania vlastného datasetu s manuálnou verifikáciou. Ani jedno by neprinieslo lepší výsledok. Automatický dataset s poctivým disclaimerom je transparentné riešenie, ktoré čitateľovi skutočne pomôže, pokiaľ rozumie, čo dostáva: prvý orientačný filter, nie právne záväzný záver.
To isté platí aj pre plánovaný multi-destinačný dropdown. Pridanie viacerých destinácií vízovú dátovú kvalitu nevyrieši, no zmení kontext, v ktorom čitateľ s badgem pracuje. Pri porovnávacom článku o piatich destináciách je hodnota vízového semaforu oveľa vyššia ako pri článku o jednej krajine. Čitateľ aktívne porovnáva a rozhoduje – a práve v tomto momente ho rýchla vizuálna informácia môže nasmerovať skôr, ako celú myšlienku pohltí ďalšie googlovanie. Tento scenár sa plánuje implementovať ako priorita pri nasledujúcom vývojovom šprinte.
Celkovo je prvá verzia Hoplo Travel Widgetu dôkazom, že aj sólový projekt postavený s pomocou AI môže dosiahnuť produkčnú kvalitu, ak sa investuje do architektúry a prípravy pred samotným kódovaním. Nie každé rozhodnutie bolo ideálne, no každé bolo vedomé. A práve to je rozdiel, na ktorom záleží pri stavbe nástrojov, ktoré majú reálne slúžiť čitateľom, nie len technickým hodnoteniam v kóde.



