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.
4. Search
PostgreSQL ILIKE na start:
- Wyszukiwanie planet po nazwie
- Wyszukiwanie zadan w content manager
- Wystarczajace dla skali MVP
- Przyszlosc:
pg_trgmextension 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
timezonew 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
i18nz 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 → zwracaavatar_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 zadania | XP |
|---|---|
| Quiz (krotki, do 5 pytan) | 10-20 |
| Quiz (dlugi, 6+ pytan) | 30-50 |
| Video (obejrzenie) | 15 |
| Video + quiz po | 25 |
| Podcast | 15 |
| Creative (rysunek, tekst) | 30-50 |
| Mini-gra | 20-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.