Poznań - Skórzewo ul. Działkowa 32

Nowoczesna aplikacja do organizacji wyzwania rowerowego Komornicka 100

W dzisiejszym artykule chciałbym podzielić się doświadczeniami z tworzenia nowoczesnej aplikacji internetowej dla lokalnego wyzwania rowerowego Komornicka 100. Aplikacja ta łączy w sobie najnowsze technologie webowe, integrację z popularnymi serwisami sportowymi oraz zaawansowane mechanizmy weryfikacji tras. Jeśli zastanawiasz się, jak wykorzystać nowoczesne narzędzia programistyczne do stworzenia aplikacji sportowej, ten artykuł jest właśnie dla Ciebie.

Czym jest Komornicka 100?

Komornicka 100 to lokalne wyzwanie rowerowe organizowane przez klub sportowy Komorniki MTB Team. Uczestnicy mają za zadanie pokonać specjalnie wytyczone trasy rowerowe. Założeniem projektu było stworzenie aplikacji, która:

  • Umożliwi łatwą rejestrację uczestników
  • Zintegruje się z platformą Strava do automatycznego pobierania aktywności rowerowych
  • Automatycznie zweryfikuje, czy uczestnik faktycznie przejechał wyznaczoną trasę
  • Zaprezentuje wyniki w formie rankingu

Przykład interfejsu aplikacji mobilnej z widokiem podstrony trasy

Architektura systemu - nowoczesne podejście

Przy projektowaniu aplikacji postawiliśmy na nowoczesne podejście wykorzystujące mikrousługi oraz techniki wdrażania CI/CD. Cała aplikacja została podzielona na kilka kluczowych komponentów:

Frontend - Next.js

Do stworzenia interfejsu użytkownika wykorzystaliśmy framework Next.js, który jest obecnie jednym z najpopularniejszych narzędzi do tworzenia aplikacji React. Next.js oferuje:

  • Renderowanie po stronie serwera (SSR) oraz statyczną generację stron (SSG), co znacząco poprawia wydajność ładowania stron
  • Automatyczną optymalizację obrazów
  • Wsparcie dla PWA (Progressive Web App), co pozwala na “instalację” aplikacji na urządzeniach mobilnych
  • Wbudowany routing i obsługę API
  • Zaawansowane mechanizmy optymalizacji ładowania danych

W aplikacji Komornicka 100 szczególnie cenne okazało się wsparcie dla PWA. Dzięki temu użytkownicy mogą “zainstalować” aplikację na swoich telefonach i korzystać z niej nawet przy ograniczonym dostępie do internetu - co jest szczególnie ważne podczas jazdy rowerem w terenie.

Zrzut ekranu pokazujący stronę główną aplikacji Komornicka 100 z listą tras i przyciskiem rejestracji

Backend - FastAPI

Sercem naszej aplikacji jest API zbudowane przy użyciu frameworka FastAPI. To stosunkowo nowe narzędzie do tworzenia API w Pythonie, które zdobyło ogromną popularność dzięki:

  • Imponującej wydajności - FastAPI jest jednym z najszybszych frameworków Pythonowych
  • Automatycznej walidacji danych wejściowych
  • Automatycznej generacji dokumentacji API (Swagger UI i ReDoc)
  • Wsparciu dla asynchronicznych operacji
  • Intuicyjnej składni

FastAPI świetnie sprawdza się w aplikacjach, które wymagają przetwarzania dużej ilości danych. W naszym przypadku, musieliśmy analizować dane GPS z aktywności uczestników i porównywać je z wzorcowymi trasami, co wymagało wydajnego przetwarzania.

@router.get("/activities/leaderboard")
async def get_leaderboard(db: Session = Depends(get_db)):
    """Pobierz ranking uczestników według liczby zaliczonych aktywności"""
    return get_leaderboard_data(db)

Proxy i bezpieczeństwo - Nginx

Całość aplikacji zabezpieczona jest przez serwer Nginx, który działa jako:

  • Proxy dla usług backendu i frontendu
  • Warstwa zabezpieczająca (API Gateway)
  • Serwer obsługujący certyfikaty SSL
  • Mechanizm limitujący liczbę zapytań (rate limiting)

Implementacja Nginx jako API Gateway zapewnia dodatkową warstwę bezpieczeństwa, umożliwiając:

  • Filtrowanie podejrzanych zapytań
  • Blokowanie ataków typu SQL Injection i XSS
  • Implementację nagłówków bezpieczeństwa
  • Ograniczenie liczby zapytań dla poszczególnych klientów

Kompleksowe podejście do bezpieczeństwa aplikacji

Bezpieczeństwo było jednym z priorytetów podczas tworzenia aplikacji. Poza standardowym zabezpieczeniem przez Nginx, wdrożyliśmy dodatkowe mechanizmy ochrony:

API Gateway z zaawansowanymi regułami bezpieczeństwa

Nasza bramka API (API Gateway) została wyposażona w zaawansowane mechanizmy ochrony, takie jak:

  • Inteligentne blokowanie podejrzanych zapytań, które mogłyby wskazywać na próby ataków
  • Geograficzne filtrowanie ruchu, umożliwiające blokowanie podejrzanych lokalizacji
  • Automatyczne odrzucanie zapytań ze znanymi złośliwymi sygnaturami
  • Zróżnicowane limity zapytań dla różnych typów endpointów (wyższe limity dla statycznych zasobów, niższe dla operacji modyfikujących dane)

Ochrona formularzy przed botami

Aby chronić system przed automatycznymi botami, wdrożyliśmy niewidoczne dla użytkownika mechanizmy ochrony formularzy:

  • Ukryte pola-pułapki (honeypot), które są niewidoczne dla prawdziwych użytkowników, ale wypełniane przez boty
  • Weryfikacja czasu wypełniania formularza - zbyt szybkie wypełnienie wskazuje na automatyzację
  • Proste wyzwania matematyczne jako alternatywa dla CAPTCHA, poprawiające doświadczenie użytkownika przy zachowaniu bezpieczeństwa

Dzięki tym mechanizmom możemy identyfikować i blokować automatyczne próby rejestracji bez wprowadzania irytujących dla użytkowników zabezpieczeń typu CAPTCHA.

Bezpieczne nagłówki HTTP

Wdrożyliśmy komplet nowoczesnych nagłówków bezpieczeństwa HTTP:

  • Content-Security-Policy - ograniczający źródła ładowania zasobów
  • Strict-Transport-Security - wymuszający komunikację przez HTTPS
  • X-Content-Type-Options - zapobiegający atakom poprzez manipulację typami MIME
  • X-Frame-Options - chroniący przed atakami typu clickjacking
  • Referrer-Policy - kontrolujący informacje wysyłane w nagłówku Referer

Dzięki tym zabezpieczeniom aplikacja uzyskała najwyższe oceny w testach bezpieczeństwa.

System dostarczania treści statycznych (CDN)

Dla poprawy wydajności i odciążenia głównego serwera, zaimplementowaliśmy własny system CDN (Content Delivery Network) oparty na lekkim serwerze HTTP:

Dedykowany serwer dla treści statycznych

Wszystkie statyczne zasoby aplikacji, takie jak:

  • Pliki tras GPX do pobrania
  • Obrazy i grafiki
  • Dokumenty do pobrania (regulaminy, instrukcje, itp.)

zostały wydzielone na osobny serwer zoptymalizowany pod kątem szybkiego serwowania plików statycznych.

Inteligentne zarządzanie pamięcią podręczną

W zależności od typu pliku, system automatycznie stosuje różne zasady cachowania:

  • Pliki tras GPX - cache 7 dni (mogą się okazjonalnie zmieniać)
  • Obrazy - cache 30 dni (rzadko się zmieniają)
  • Pliki JavaScript i CSS - cache 7 dni (aktualizowane przy nowych wersjach)
  • Dokumenty do pobrania - cache 7 dni

Takie podejście znacząco przyspiesza ładowanie aplikacji dla powracających użytkowników i zmniejsza obciążenie głównego serwera.

Wsparcie dla różnych formatów plików

System CDN został skonfigurowany z obsługą wszystkich potrzebnych typów plików, w tym:

  • Standardowe formaty web (HTML, CSS, JS, obrazy)
  • Pliki GPX z trasami (z odpowiednim typem MIME: application/gpx+xml)
  • Dokumenty PDF
  • Pliki kompresowane ZIP

To zapewnia prawidłowe wyświetlanie i pobieranie wszystkich typów zasobów przez użytkowników.

System powiadomień - email i webhooks

Aby zapewnić dobrą komunikację z uczestnikami, stworzyliśmy:

  • System powiadomień email informujący o:
    • Weryfikacji konta
    • Połączeniu ze Stravą
    • Zaliczeniu aktywności
    • Usunięciu aktywności
  • System webhooków umożliwiający integrację z zewnętrznymi platformami organizatora, takimi jak:
    • Systemy powiadomień
    • Platformy analityczne
    • Własne aplikacje organizatora

Zaawansowany system webhooków dla integracji zewnętrznych

Szczególnie wartym uwagi elementem jest system webhooków, który umożliwia organizatorom otrzymywanie natychmiastowych powiadomień o kluczowych zdarzeniach w aplikacji. System obsługuje szereg różnych typów zdarzeń:

Zdarzenia związane z użytkownikiem

  • Rejestracja użytkownika: Wysyłane gdy nowy uczestnik rejestruje się lub reaktywuje konto
  • Połączenie ze Stravą: Informuje gdy użytkownik pomyślnie łączy swoje konto ze Stravą
  • Dezaktywacja konta: Powiadamia o dezaktywacji konta użytkownika

Zdarzenia związane z aktywnościami

  • Zatwierdzenie aktywności: Wysyłane gdy aktywność rowerowa użytkownika zostaje pozytywnie zweryfikowana
  • Odwołanie aktywności: Informuje gdy wcześniej zatwierdzona aktywność zostaje usunięta z systemu (np. gdy użytkownik usunie ją ze Stravy)

Wszystkie webhoki wysyłają dane w ustandaryzowanym formacie JSON, zawierającym szczegółowe informacje o zdarzeniu, co pozwala organizatorom na łatwą integrację z własnymi systemami. Dzięki temu organizatorzy mogą na przykład:

  • Automatycznie aktualizować własne statystyki i rankingi
  • Wysyłać dodatkowe powiadomienia do uczestników przez SMS lub inne kanały
  • Prowadzić zaawansowane analizy uczestnictwa w czasie rzeczywistym

Mechanizm webhooków może być również wykorzystany do automatyzacji procesów organizacyjnych lub nawet integracji z fizycznymi systemami (np. wyświetlanie aktualnych liderów na tablicach LED podczas imprez sportowych).

System weryfikacji tras GPS - serce aplikacji

Największym wyzwaniem technicznym było stworzenie systemu, który automatycznie weryfikowałby, czy uczestnik faktycznie przejechał wyznaczoną trasę. W tym celu opracowaliśmy zaawansowany algorytm, który:

  1. Pobiera aktywności uczestnika z platformy Strava poprzez API
  2. Porównuje dane GPS z wzorcowymi trasami zapisanymi w formacie GPX
  3. Analizuje podobieństwo trasy, uwzględniając naturalne odchylenia GPS
  4. Wykrywa potencjalne próby oszustwa (np. ręczne edycje tras)

Wizualizacja trasy użytkownika na mapie po udanej weryfikacji

Anti-fraud - wykrywanie prób oszustwa

Szczególnie ciekawym elementem jest system wykrywania prób oszustwa. W świecie zawodów sportowych zawsze znajdą się osoby próbujące zdobyć przewagę w nieuczciwy sposób. Nasz system analizuje:

  • Statystyczne odchylenia punktów GPS - naturalne aktywności zawsze mają pewne odchylenia wynikające z dokładności GPS
  • Podejrzanie “idealne” dopasowanie do trasy wzorcowej - wskazujące na potencjalne oszustwo
  • Duplikaty aktywności - aby uniknąć wielokrotnego zaliczania tej samej trasy zarejestrowanej na różnych urządzeniach

To zaawansowane podejście analityczne pozwala na utrzymanie uczciwej rywalizacji, jednocześnie dopuszczając naturalne odchylenia podczas normalnej jazdy.

Integracja ze Strava - kluczowy element aplikacji

Integracja z platformą Strava była jednym z najważniejszych elementów aplikacji. Strava to popularna platforma dla sportowców, która umożliwia rejestrowanie i analizowanie aktywności fizycznych, szczególnie popularnych wśród rowerzystów.

Integracja obejmowała:

  • Proces autoryzacji OAuth 2.0
  • Automatyczne pobieranie nowych aktywności uczestników
  • Dostosowanie UX dla różnych platform (web, mobile)
  • Obsługę wygasających tokenów dostępu

Szczególnie istotne było zapewnienie płynnego procesu autoryzacji na urządzeniach mobilnych, gdzie zaimplementowaliśmy specjalne mechanizmy obsługi przekierowań.

Progressive Web App - aplikacja dostępna zawsze i wszędzie

Ważnym aspektem projektu było przygotowanie aplikacji jako Progressive Web App (PWA). Ta technologia pozwala na:

  • “Instalację” aplikacji na urządzeniu mobilnym bez konieczności korzystania ze sklepu z aplikacjami
  • Działanie aplikacji offline lub przy słabym połączeniu internetowym
  • Szybsze ładowanie dzięki cachowaniu zasobów
  • Dostęp do funkcji urządzenia takich jak powiadomienia push

Dla uczestników wyzwania rowerowego możliwość korzystania z aplikacji nawet przy słabym zasięgu sieci komórkowej jest nieoceniona, szczególnie na terenach leśnych czy oddalonych od miast.

Wydajność aplikacji - Lighthouse jako narzędzie kontroli jakości

Jednym z kluczowych aspektów rozwoju aplikacji była jej wydajność. Wykorzystaliśmy narzędzie Lighthouse zintegrowane z przeglądarką Chrome, aby stale monitorować i optymalizować wydajność aplikacji.

Nasze wyniki Lighthouse są imponujące:

  • Performance: 91/100
  • Accessibility: 96/100
  • Best Practices: 100/100
  • SEO: 100/100
  • PWA: Wszystkie checklisty zaliczone

Zrzut ekranu z raportu Lighthouse pokazujący wyniki aplikacji

Osiągnięcie tak wysokich wyników wymagało systematycznej pracy nad wieloma aspektami aplikacji:

Optymalizacja wydajności (Performance)

Kluczowe metryki wydajnościowe, które udało nam się zoptymalizować:

  • First Contentful Paint (FCP): 1.6s
  • Largest Contentful Paint (LCP): 2.8s
  • Total Blocking Time (TBT): 180ms
  • Cumulative Layout Shift (CLS): 0.068
  • Speed Index: 1.6s

Lighthouse wskazał kilka potencjalnych obszarów do dalszej optymalizacji:

  • Eliminacja zasobów blokujących renderowanie (potencjalna oszczędność 580ms)
  • Redukcja niewykorzystywanego kodu JavaScript (potencjalna oszczędność 60KB)
  • Lepsze zarządzanie cachingiem statycznych zasobów

Dostępność (Accessibility)

Z wynikiem 96/100 nasza aplikacja spełnia większość wymogów dostępności. Główne obszary, które zapewniliśmy:

  • Odpowiednia struktura nagłówków
  • Teksty alternatywne dla obrazów
  • Wystarczający kontrast kolorów
  • Dostępność z poziomu klawiatury

Najlepsze praktyki (Best Practices) i SEO

Perfekcyjny wynik 100/100 w obu tych kategoriach oznacza, że aplikacja jest zgodna z najlepszymi praktykami programistycznymi i zoptymalizowana pod kątem wyszukiwarek.

Do osiągnięcia tych wyników przyczyniło się:

  • Korzystanie z HTTPS
  • Poprawne nagłówki bezpieczeństwa
  • Unikanie przestarzałych API
  • Prawidłowe metadane i struktura dokumentu
  • Dostępne i opisowe linki
  • Prawidłowy plik robots.txt

Wielojęzyczność - polski i angielski

Aplikacja została zaprojektowana z myślą o użytkownikach polskojęzycznych, ale zaimplementowaliśmy również pełne wsparcie dla języka angielskiego. Wszystkie treści, emaile i powiadomienia są dostępne w obu językach, co czyni aplikację bardziej dostępną dla międzynarodowych uczestników.

Wyzwania i rozwiązania

Podczas tworzenia aplikacji napotkaliśmy kilka istotnych wyzwań:

Problemy z autoryzacją Strava na urządzeniach mobilnych

Jednym z najbardziej frustrujących problemów dla użytkowników było “zamrożenie” procesu autoryzacji Strava na urządzeniach mobilnych. Problem polegał na tym, że po przyznaniu uprawnień w aplikacji Strava, użytkownik nie był prawidłowo przekierowywany z powrotem do naszej aplikacji.

Rozwiązaliśmy ten problem poprzez:

  1. Implementację specyficznych mechanizmów wykrywania platformy
  2. Użycie specjalnych adresów URL dla autoryzacji mobilnej
  3. Dodanie komponentu diagnostycznego, który pomaga użytkownikom w rozwiązywaniu problemów

Obsługa dużych plików GPX

Innym wyzwaniem była wydajna obsługa i porównywanie dużych plików GPX, które mogą zawierać tysiące punktów. Nasze rozwiązanie obejmowało:

  1. Algorytmy upraszczania tras (Douglas-Peucker)
  2. Optymalizację zapytań do bazy danych
  3. Kompresję danych GPS przy przechowywaniu

Wdrożenie i skalowalność

Aplikacja została wdrożona z wykorzystaniem kontenerów Docker, co zapewnia:

  • Łatwość wdrażania na różnych środowiskach
  • Izolację komponentów
  • Możliwość szybkiego skalowania w przypadku wzrostu liczby użytkowników
  • Prostotę w zarządzaniu zależnościami

Cała infrastruktura jest definiowana jako kod (Infrastructure as Code), co umożliwia szybkie odtworzenie środowiska w przypadku awarii lub potrzeby migracji.

Wnioski i przyszły rozwój

Tworzenie aplikacji Komornicka 100 było fascynującym projektem, który pozwolił nam wykorzystać najnowsze technologie webowe w praktycznym zastosowaniu. Najważniejsze wnioski:

  1. Nowoczesny stos technologiczny (Next.js, FastAPI, Nginx) sprawdza się doskonale w aplikacjach sportowych
  2. Projektowanie z myślą o urządzeniach mobilnych jest kluczowe dla aplikacji użytkowanych w terenie
  3. Progressive Web Apps oferują doskonały kompromis między natywną aplikacją a stroną internetową
  4. Automatyzacja procesów weryfikacji znacząco zwiększa atrakcyjność różnych zawodów sportowych

Plany na przyszłość

W kolejnych wersjach aplikacji planujemy:

  • Implementację zaawansowanych statystyk dla uczestników
  • Rozbudowę mechanizmów społecznościowych
  • Integrację z innymi platformami sportowymi
  • Dodanie analizy wysiłku (np. dane o tętnie, mocy)
  • Dalszą optymalizację wydajności dla urządzeń o ograniczonej mocy obliczeniowej

Podsumowanie

Projekt Komornicka 100 pokazuje, jak nowoczesne technologie webowe mogą być wykorzystane do tworzenia funkcjonalnych aplikacji sportowych. Połączenie frontendu opartego na Next.js, backendu w FastAPI oraz zabezpieczeń Nginx pozwoliło na stworzenie wydajnej, bezpiecznej i przyjaznej dla użytkowników aplikacji.

Jeśli jesteś organizatorem zawodów sportowych lub myślisz o stworzeniu podobnej aplikacji, zachęcamy do rozważenia podobnego stosu technologicznego. Nowoczesne frameworki znacząco przyspieszają rozwój i pozwalają skupić się na funkcjonalnościach, a nie na rozwiązywaniu problemów technicznych.

A jeżeli jesteś entuzjastą kolarstwa z okolic Poznania - zapraszamy do udziału w wyzwaniu Komornicka 100!

Oficjalny start wydarzenia: 1 czerwca 2025 r.


Autor: Paweł Rosół

Zapoznaj się z naszą pełną ofertą: