Skip to content

Decyzje Techniczne

Kluczowe decyzje techniczne podjete w projekcie Lumos Islands, wraz z uzasadnieniem.


1. Globus — uproszczona mapa 2D

Na start uproszczona mapa 2D (ilustrowana, z pinami krajow). Globus 3D jako przyszla iteracja.

Uzasadnienie: Prostsze do implementacji, mniejsze wymagania wydajnosciowe. Mapa 2D pozwala szybciej dostarczyc dzialajacy produkt bez koniecznosci integracji bibliotek 3D (np. Flutter Globe), ktore sa ciezkie i slabo przetestowane na roznych urzadzeniach.


2. Push Notifications

FCM (Firebase Cloud Messaging) + APNs. Typy powiadomien:

  • Streak reminder — jesli dziecko nie wykonalo zadania danego dnia, wieczorem
  • Nowe zadanie dostepne — w lokacji
  • Parent approve — rodzic zatwierdzil todo
  • Level up / badge earned

Implementacja: Go server wysyla przez FCM API. Flutter: firebase_messaging package.

Uzasadnienie: FCM jest standardem branzy, darmowy, dobrze wspierany przez Flutter. Pozwala utrzymac zaangazowanie dzieci (streak reminders) i informowac rodzicow o postepach.


3. Offline Support

Na start minimalne wsparcie offline:

  • Profil i postep cachowany lokalnie (Hive lub SharedPreferences)
  • Media (video, audio) wymagaja polaczenia — brak offline cache
  • Zadania tekstowe (quiz) moga byc cachowane do wykonania offline, sync przy reconnect
  • Przyszlosc: pelny offline mode z Isar/Drift

Uzasadnienie: Pelny offline mode to duzy naklad pracy (synchronizacja konfliktow, queue). Na MVP wystarczy podstawowy cache profilu i quizow. Media offline to zbyt duzy koszt storage na urzadzeniu.


PostgreSQL ILIKE na start:

  • Wyszukiwanie planet po nazwie
  • Wyszukiwanie zadan w content manager
  • Wystarczajace dla skali MVP
  • Przyszlosc: pg_trgm extension dla fuzzy search

Uzasadnienie: ILIKE jest proste, nie wymaga dodatkowej konfiguracji i przy malej skali danych (dziesiatki/setki rekordow) jest wystarczajaco szybkie. Unikamy przedwczesnej optymalizacji.


5. Strefy Czasowe

Streak dzienny liczony wg lokalnej strefy czasowej dziecka:

  • Flutter wysyla timezone w naglowku lub body (np. Europe/Warsaw)
  • Serwer przelicza midnight wg timezone dziecka
  • Streak resetuje sie o polnocy lokalnej

Uzasadnienie: Dziecko w Warszawie i dziecko w Nowym Jorku powinny miec streak liczony wg swojego lokalnego dnia. Unikamy sytuacji, w ktorej streak resetuje sie o dziwnej godzinie z perspektywy uzytkownika.


6. Internacjonalizacja (i18n)

Jezyki na start: polski + angielski.

Flutter App:

  • flutter_localizations + pliki ARB
  • Zmiana jezyka na statku (ekran ustawien)
  • Jezyk zapisywany w profilu uzytkownika

Manager-Content:

  • Go i18n z plikami tlumaczen (JSON/YAML)
  • Flagi do przelaczania jezyka w top bar
  • Jezyk zapisywany w session/cookie

Uzasadnienie: Dwa jezyki na start pokrywaja glowny rynek (Polska) i otwieraja drzwi miedzynarodowo. ARB to standardowy format dla Flutter. Przyszlosc: dodawanie kolejnych jezykow (niemiecki, hiszpanski) przez pliki tlumaczen.


7. Avatar Rendering

Preset avatary jako gotowe obrazki PNG:

  • 8 presetow przy rejestracji (4 meskie + 4 zenskie) — pojedyncze pliki PNG
  • Przechowywane w Supabase Storage (bucket avatars/presets/)
  • Garderoba (edycja na statku): warstwy PNG skladane w Stack (Flutter) — face, hair, top, bottom, shoes, hat, accessories
  • Elementy garderoby w Supabase Storage (bucket avatars/items/)
  • Po zapisie: serwer generuje composite PNG jako avatar_url

Rendering server-side:

  • Po zapisie w garderobie: PATCH /app/avatar → serwer składa warstwy PNG → generuje composite → zapisuje w Supabase Storage → zwraca avatar_url
  • Avatar URL jest cache'owany, regenerowany tylko po zmianie wyglądu
  • Presety rejestracyjne: gotowe PNG, bez składania warstw

Uzasadnienie: Warstwy PNG sa proste do implementacji w Flutter (Stack widget). Unikamy skomplikowanych rozwiazan jak SVG compositing czy rendering po stronie serwera w czasie rzeczywistym. Composite generowany server-side zapewnia spojny wyglad avatara wszedzie.


8. XP Formuly

Typ zadaniaXP
Quiz (krotki, do 5 pytan)10-20
Quiz (dlugi, 6+ pytan)30-50
Video (obejrzenie)15
Video + quiz po25
Podcast15
Creative (rysunek, tekst)30-50
Mini-gra20-40

Streak bonus: +10% XP za kazdy kolejny dzien serii (max +50% przy 5+ dni).

XP przypisywane do konkretnego zadania w content manager (pole xp_reward).

Uzasadnienie: Wartosci XP zroznicowane wg wysilku — dlugie quizy i zadania kreatywne nagradzane wyzej niz bierne ogladanie. Streak bonus motywuje do codziennej aktywnosci, ale cap na +50% zapobiega zbyt duzej przewadze stalych graczy.


9. Content Moderation

Brak auto-moderacji na start:

  • Creative submissions (rysunki, teksty, zdjecia) widoczne tylko dla rodzica/nauczyciela w Manager
  • Rodzic/nauczyciel przeglada i opcjonalnie komentuje
  • Brak AI moderacji, brak filtrow
  • Przyszlosc: opcjonalna moderacja AI (content safety API)

Uzasadnienie: Na MVP skala tresci jest mala (dziesiatki submissions), wiec reczna moderacja przez rodzica/nauczyciela jest wystarczajaca. AI moderacja to dodatkowy koszt i zlozonosc, ktora nie jest uzasadniona na tym etapie.


10. Analytics / COPPA

Tylko wewnetrzne statystyki:

  • Dane w Supabase (tabele stats) — XP, level, task completions, streak
  • Brak third-party analytics (Google Analytics, Mixpanel, etc.)
  • Brak tracking SDK w aplikacji dziecka
  • COPPA compliant: nie zbieramy danych osobowych poza minimum (birth_year, pin)
  • Rodzic ma wglad w statystyki dziecka przez Manager

Uzasadnienie: Aplikacja dla dzieci musi byc COPPA compliant. Brak third-party trackerow eliminuje ryzyko prawne i upraszcza privacy policy. Wewnetrzne statystyki w Supabase daja nam pelny obraz bez narazania prywatnosci dzieci.


11. Kody zamiast QR

Rezygnujemy z QR code. Wszystkie kody sa alfanumeryczne 8-12 znakow z cyframi:

  • Linking code (laczenie rodzic-dziecko): 8 znakow, wielkie litery + cyfry, wazny 15 minut
  • Manager login code: 8 znakow, wielkie litery + cyfry, wazny 10 minut
  • Generowane server-side, latwe do wpisania recznie
  • Format: np. A3K9M2P8, BX47YN2R
  • Bez QR scanner w Flutter — mniej zaleznosci, prostsze UX

UWAGA

To zmienia flow logowania w Manager-Content — usuwamy tab "QR code", zostaje tab "Kod z aplikacji" i "Email".

Uzasadnienie: QR scanner wymaga uprawnien do kamery, dodatkowej biblioteki i jest problematyczny na niektorych urzadzeniach. Krotki kod alfanumeryczny jest rownie szybki do wpisania, a eliminuje caly layer zlozonosci.


12. Testing Strategy

Go (manager-content):

  • Unit tests na service layer (go test ./internal/service/...)
  • Handler tests z httptest
  • Repository tests z test database (Supabase local via Docker)

Flutter (app):

  • Widget tests na kluczowe ekrany (auth, globe, location, task)
  • Unit tests na providers/repositories
  • Integration tests: kluczowe flowy (rejestracja, wykonanie zadania)

Pokrycie docelowe: 60%+ na service layer, 40%+ na UI.

Uzasadnienie: Skupiamy testy na logice biznesowej (service layer), gdzie bugi sa najkosztowniejsze. UI testy na kluczowych flowach zapewniaja, ze glowne sciezki dzialaja. Nie celujemy w 100% coverage — to nieefektywne na etapie MVP.


13. Data Retention

Soft delete z 90-dniowym retention:

  • Usuniete konto — dane oznaczone jako deleted_at
  • Po 90 dniach — hard delete (cron job / Supabase Edge Function)
  • GDPR: uzytkownik moze zazadac natychmiastowego usuniecia
  • Backup bazy: Supabase automatic backups (daily)

Uzasadnienie: Soft delete daje mozliwosc odzyskania konta w razie pomylki. 90 dni to standard branzy. Hard delete po tym okresie spelnia wymagania GDPR i minimalizuje przechowywanie danych.


14. API Versioning

Brak wersjonowania na start:

  • Endpointy: /app/*, /api/*
  • Gdy potrzebne breaking changes: /app/v2/*
  • Na start nie komplikujemy — jeden klient (Flutter app) kontrolowany przez nas

Uzasadnienie: Przy jednym kliencie mobilnym, ktorego sami wydajemy, mozemy koordynowac zmiany API z aktualizacjami aplikacji. Wersjonowanie staje sie potrzebne dopiero przy wielu klientach lub publicznym API.


15. Logging / Monitoring

Go server:

  • slog (structured logging) w formacie JSON
  • Logi na stdout (Docker — agregacja)
  • Request logging middleware (method, path, status, duration)

Flutter app:

  • Sentry (sentry_flutter) — crash reporting i error tracking
  • Brak verbose logging w produkcji

Serwer:

  • Sentry (sentry-go) — error tracking
  • Health check: GET /health — 200 OK
  • Supabase Dashboard — monitoring bazy danych

Uzasadnienie: slog to standardowa biblioteka Go od wersji 1.21, structured logging ulatwia parsowanie logow. Sentry to sprawdzony standard do crash reportingu — laczy bledy z obu stron (Flutter + Go). Health check endpoint umozliwia monitoring uptime.

Lumos Islands v2 - Dokumentacja Projektowa