Przejdź do treści

Rozszerzenie do porównywania kursów sportowych

Rozszerzenie przeglądarki (Chrome, Firefox, Safari) porównujące kursy bukmacherskie bezpośrednio na stronach bukmacherów. Rozwijałem adaptery dla ponad 40 bukmacherów i nanosiłem poprawki w pozostałych aplikacjach produktu.

Szczegóły projektu

#Kontekst

W OddsGuard rozwijałem rozszerzenie przeglądarki do porównywania kursów bukmacherskich. Głównym obszarem była warstwa adapterów - modułów, które rozpoznawały kursy w kodzie HTML konkretnych bukmacherów i doklejały obok nich nakładkę z lepszą ofertą z innego bukmachera. Nanosiłem też poprawki w pozostałych aplikacjach produktu: w backendowym API, w serwisie zbierającym kursy od dostawców i na stronie marketingowej.

Do OddsGuard trafiłem po pracy nad regulowaną platformą gier hazardowych online dla wielu marek - kontekst rynku bukmacherskiego (regulatorzy, marki, gracze, sposób pracy z kursami i zakładami) był mi już znany, a projekt wokół porównywarki kursów okazał się naturalnym kolejnym krokiem.

Poza pracą z bieżącymi zgłoszeniami samodzielnie prowadziłem większe inicjatywy - od pomysłu, przez prototyp, po produkcyjne wdrożenie. Szczegóły w sekcji „Co dostarczyłem” niżej.

Rozszerzenie porównywało kursy bukmacherskie w czasie rzeczywistym. Kiedy użytkownik przeglądał ofertę u bukmachera, rozszerzenie wykrywało kurs bezpośrednio na stronie i pokazywało obok nakładkę z ofertą u innego bukmachera. Wspierane przeglądarki: Chrome, Firefox, Safari (w tym Safari na iPhonie) - wszystkie na standardzie Manifest V3. Sama warstwa rozszerzenia obsługiwała ponad 40 bukmacherów z rynków brytyjskiego, amerykańskiego, europejskiego i offshore.

Rozszerzenie było jedną z aplikacji większego produktu żyjącego w jednym repozytorium kodu (monorepo oparte o pnpm i Turborepo), obok backendu, serwisów danych i pozostałych aplikacji klienckich.

Statystyki

Moja aktywność w pierwszych 3 miesiącach

Zamkniętych zadań
82
Zamkniętych zadań przypisanych do mnie i ukończonych, kwiecień - lipiec 2026
Nowych funkcji wprowadzonych do produkcji
40
Nowych funkcji wprowadzonych do produkcji poza samymi poprawkami błędów i porządkami
Adaptery napisane od zera
2
Adaptery napisane od zera Oddsshark, VegasInsider - porównywarki konkurencji
Wspierane przeglądarki
3
Wspierane przeglądarki Chrome, Firefox, Safari (standard Manifest V3)

#Co dostarczyłem

  • Adaptery napisane od zera: Oddsshark i VegasInsider - dwa adaptery pod strony, które same nie są bukmacherami, tylko porównywarkami konkurencji. Wyzwanie: strony pokazywały po kilka propozycji kursów w jednym wierszu, więc jeden adapter musiał umieć powielać nakładkę tyle razy, ile było opcji w wierszu.
  • Wspólna warstwa pod tymi adapterami: wydzieliłem wspólny mixin (fragment kodu wielokrotnego użycia) dla adapterów porównywarek konkurencji - jedna zmiana szła jednocześnie na wszystkie adaptery tego typu. Analogicznie dla bukmacherów dzielących ten sam bazowy silnik do wyświetlania kursów wydzielałem wspólne pliki wspierające całą grupę.
  • Pokrycie Mistrzostw Świata 2026: uruchomiłem nakładki porównawcze na stronach WC u kilku bukmacherów - theScore Bet, DraftKings, Oddschecker, William Hill - plus jedna zmiana we współdzielonym kodzie, która uruchomiła nakładki dla zakładu „kto wygra turniej” u całej grupy bukmacherów naraz. Każdy operator miał inną strukturę stron turniejowych (osobno lista meczów, osobno drabinka, osobno zakładka „zakłady długoterminowe”), więc pod każdą trzeba było przygotować osobne rozpoznanie w adapterze.
  • Utrzymanie rozszerzenia w trzech przeglądarkach jednocześnie: ten sam kod źródłowy budował się do trzech różnych paczek. Każda przeglądarka miała własny proces wydawania i własne testy przed wypuszczeniem nowej wersji.
  • Safari na iOS i macOS przez Xcode: rozszerzenie działało też jako natywna aplikacja Apple w projekcie Xcode ze Swift-ową powłoką. Dodałem Apple Privacy Manifests (pliki opisujące, jakich danych używa aplikacja) dla wszystkich czterech aplikacji budowanych z projektu - wymaganych przez App Store.
  • Praca w pozostałych aplikacjach produktu (około 40 osobnych zmian poza samym rozszerzeniem): sekcja porównująca konkurencyjne rozszerzenia na stronie marketingowej (adresy w formie /vs/nazwa-konkurenta), integracja chatbota AI w backendowym API, praca w serwisie zbierającym kursy.
  • Testy i monitoring: testy jednostkowe pilnujące, że fragmenty kodu identyfikujące elementy na stronie bukmachera (tzw. selektory) ciągle działają - żeby cicha zmiana u bukmachera była wychwytywana w automatycznych testach przed wypuszczeniem, a nie u użytkownika końcowego.
  • Rygorystyczne typowanie kodu (TypeScript w trybie strict): standard projektu obowiązujący w całej bazie kodu, pilnowany w CI.

#Wyzwania

Adaptery musiały wytrzymać ciche zmiany kodu HTML u bukmachera

Strony bukmacherów zmieniały swój kod HTML bez zapowiedzi - inny identyfikator elementu, przemianowana klasa CSS, przebudowana struktura kolumn, nowy układ tabeli z kursami. Adapter, który dziś rozpoznawał notowania poprawnie, jutro pokazywał zero nakładek. Sztuka polegała na tym, żeby selektory (fragmenty kodu wskazujące, gdzie w stronie szukać kursu) były na tyle konkretne, żeby nie łapać fałszywych trafień, ale na tyle luźne, żeby przetrwać małe przebudowy. Do tego dochodziły testy sprawdzające, czy selektory ciągle działają - żeby cicha zmiana identyfikatora u operatora była wychwytywana w automatycznych testach, nie u użytkownika końcowego. Ważny był też jasny podział na „to jest błąd adaptera” versus „to jest brak danych z serwisu zbierającego kursy” - dwa różne rodzaje zgłoszeń, dwa różne obszary kodu.

Manifest V3 w trzech przeglądarkach oznaczał w praktyce trzy różne implementacje

Chrome, Firefox i Safari deklarowały wsparcie dla Manifest V3 (standardu opisującego, jak rozszerzenia mają działać w przeglądarce), ale każda przeglądarka różniła się w szczegółach: inaczej obsługiwały procesy działające w tle, inaczej rozstrzygały uprawnienia do wysyłania zapytań na obce domeny, inaczej trzymały sesję między przejściem z jednej strony na drugą, inaczej przekazywały komunikaty między częściami rozszerzenia. Safari na iOS to była osobna historia - własny sposób pakowania rozszerzenia, symulator iPhone’a trzeba było czyścić przed testem instalacji (bo zapamiętane ustawienia użytkownika maskowały scenariusz pierwszego uruchomienia), a kopiowanie paczki do projektu Xcode po każdej zmianie w głównej gałęzi kodu było codzienną higieną wydawania nowych wersji. Traktowałem każdą przeglądarkę jak osobny cel, a różnice ujmowałem w jednej wspólnej warstwie - zamiast pisać jedną wersję i liczyć, że wszędzie zadziała identycznie.

Zakłady na żywo: kod strony zmienia się bez przerwy, nie tylko przy załadowaniu

W widokach zakładów na żywo notowania aktualizowały się w czasie rzeczywistym

  • kursy skakały, uczestnicy (zawodnicy lub drużyny) znikali, wydarzenie kończyło się w środku sesji użytkownika. Adaptery napisane pod widoki przed meczem (jednorazowe skanowanie strony po jej załadowaniu) nie wystarczały. Pracowałem nad rozwiązaniami, które obserwowały zmiany kodu strony na bieżąco
  • uruchamiane tylko po wejściu użytkownika na konkretny adres URL z widokiem na żywo u wybranych bukmacherów. Kluczowa idea: nakładka znikała razem z uczestnikiem, a nie zostawała zawieszona na starym kursie.
Odróżnianie problemów w adapterze od braków w danych i ograniczeń regionalnych

Kiedy użytkownik zgłaszał „nie widzę porównania kursów na tym meczu”, mogło to znaczyć trzy zupełnie różne rzeczy: (a) adapter źle rozpoznawał ten konkretny widok bukmachera, (b) serwis zbierający kursy nie dostał tych notowań od dostawcy, (c) użytkownik był w regionie, w którym operator w ogóle nie oferował danego rynku. Wypracowałem procedurę diagnostyczną - najpierw sprawdzałem wymiar ograniczeń regionalnych na tle produkcyjnego kanału danych, potem wymiar serwisu zbierającego kursy pod kątem brakujących notowań, dopiero wtedy zaglądałem do adaptera w narzędziach programisty w przeglądarce. Wniosek „tu nie ma błędu w adapterze” też był pełnoprawną odpowiedzią - pod warunkiem, że stał za nim konkretny dowód.

#Wnioski

  • Manifest V3 w trzech przeglądarkach to były w praktyce trzy różne implementacje pod jedną nazwą - najbezpieczniej było traktować każdą przeglądarkę jak osobny cel i uzgadniać różnice jedną wspólną warstwą, zamiast pisać jedną wersję i liczyć, że wszędzie zadziała identycznie.
  • Adaptery działające na kodzie stron bukmacherów wymagały monitoringu na produkcji - bez wysyłania danych z produkcji i bez testów pilnujących, że rozpoznawanie ciągle działa, nie było wiadomo, kiedy strona bukmachera zmieniła kod. Poprawki po zgłoszeniu użytkownika były zawsze spóźnione.
  • Wspólne rozwiązania (mixiny wielokrotnego użycia, pliki dla bukmacherów dzielących ten sam silnik) opłacały się najbardziej - kiedy dwudziesty adapter zaczynał wyglądać jak dwudziesty pierwszy, wydzielenie wspólnego mixina pozwalało odzyskać tempo. Wspólny mixin pod adapterami porównywarek konkurencji powstał właśnie z tej obserwacji, po dwóch pierwszych takich adapterach.
  • Odróżnianie przyczyn awarii ma znaczenie w każdym produkcie, który wyświetla cudze dane: zgłoszenie „tu nic się nie pokazuje” może wskazywać na adapter, na warstwę danych albo na ograniczenie regionalne. Bez ustalonej procedury diagnostycznej łatwo naprawiać nie ten problem, co trzeba - i wypuścić „poprawkę”, która nic nie zmienia.

Pracujmy razem

Jestem senior frontend developerem. Buduję szybkie, dostępne aplikacje webowe w React i Next.js, z TypeScriptem. Zależy mi na Core Web Vitals, SSR/SSG i skalowalnej, łatwej w utrzymaniu architekturze. Jeśli szukasz kogoś takiego - daj znać.

Napisz do mnie →