Wyzwanie
Podróżnik wpisuje w Google "szczepienia Kenia" i trafia na stronę CDC. Czyta listę 12 szczepień, z czego 3 są obowiązkowe, 4 zalecane, a reszta "w zależności od regionu". Nie wie, które dotyczą jego trasy. Nie wie, gdzie się zaszczepić. Nie wie, ile to kosztuje. Zamyka kartę.
Po drugiej stronie jest klinika travel medicine w Warszawie, która ma wolne terminy, wszystkie szczepionki na stanie i lekarza, który odpowiedziałby na każde z tych pytań w 5 minut. Ale ta klinika nie istnieje w Google dla hasła "szczepienia Kenia". Jej strona to wizytówka z numerem telefonu i mapką dojazdu.
To jest Care Gap — przepaść między wiarygodną informacją medyczną a umówieniem wizyty. Dane WHO i CDC są publiczne, kliniki istnieją, pacjenci ich szukają. Ale nic tego nie łączy.
Medova miała zamknąć tę lukę: jedno miejsce, w którym podróżnik dowiaduje się co potrzebuje, dlaczego tego potrzebuje i gdzie to dostanie — a klinika zyskuje kanał dotarcia do pacjenta, który już podjął decyzję.
Co to oznaczało technicznie
Proste na papierze. W praktyce — lista wymagań, przy której większość zespołów poprosiłaby o 12 miesięcy i 6 osób:
- 15 języków od dnia pierwszego, w tym arabski (RTL) i japoński — bo rynek travel health jest globalny, a SEO w jednym języku to rezygnacja z 90% ruchu organicznego. Nie "dodamy później". Od pierwszego commita.
- Dane medyczne z WHO i CDC aktualizowane codziennie — nie statyczna tabela, tylko pipeline, który codziennie odpytuje 6 zewnętrznych źródeł, normalizuje dane i aktualizuje rekomendacje per kraj × choroba × szczepionka. Stare dane w travel medicine to nie bug — to ryzyko zdrowotne.
- Marketplace z bookingiem, płatnościami i weryfikacją klinik — nie katalog z linkami. Pełny flow: profil kliniki → kalendarz lekarza → slot → płatność → potwierdzenie. Z weryfikacją tożsamości kliniki, zanim pojawi się w wynikach.
- Compliance od pierwszego dnia — RODO, ISMS (ISO 27001), dane medyczne. Nie "dopiszemy privacy policy przed launczem". Row-Level Security na każdej tabeli, audit trail, szyfrowanie, retencja danych, zgody — zaprojektowane w architekturze, nie doklejone post factum.
- Zero budżetu na infrastrukturę enterprise — startup, nie korporacja. Rozwiązanie musiało kosztować tyle, ile kosztuje Supabase + serwer dedykowany, nie tyle, ile kosztuje AWS z konsultantem.
A to wszystko miał dowieźć jeden developer.
Rozwiązanie
Zamiast planować architekturę przez kwartał, postawiliśmy działający prototyp w 6 tygodni. Kluczowa decyzja na starcie: nie budujemy "platformy, która kiedyś obsłuży 15 języków". Budujemy platformę, która obsługuje 15 języków teraz — bo każdy dzień bez tureckiej, indonezyjskiej czy hiszpańskiej wersji to ruch organiczny, którego nie odzyskamy.
Stack: świadome kompromisy, nie hype
Next.js 16 z App Routerem — bo potrzebowaliśmy SSR dla SEO (Google musi zobaczyć przetłumaczoną treść, nie spinner), a jednocześnie dynamicznych dashboardów dla klinik i adminów. Jeden framework na oba przypadki.
Supabase zamiast custom backendu — PostgreSQL 15 z Auth, Storage, Edge Functions i Row-Level Security w jednym pakiecie. Alternatywa to 3 miesiące pisania boilerplate'u autentykacji i autoryzacji. Supabase dał nam to w tydzień. Trade-off: mniejsza elastyczność w edge case'ach. Akceptowalny na tym etapie.
Sanity v5 jako CMS dla blogu — document-level i18n, Portable Text, embedded Studio pod /studio. Redaktorzy piszą treść w jednym miejscu, a artykuł pojawia się w 15 wersjach językowych bez udziału developera.
Coolify na Hetzner zamiast Vercel/AWS — serwer dedykowany, Docker standalone, zero vendor lock-in. Koszt: ułamek tego, co Vercel przy porównywalnym ruchu. Cloudflare (free plan) przed serwerem — CDN, DDoS, SSL. Całość infrastruktury za cenę jednego lunchu biznesowego miesięcznie.
Routing: jeden z trudniejszych problemów
URL /pl/wiedza/choroby musi prowadzić do tego samego komponentu co /en/knowledge/diseases i /de/wissen/krankheiten. Ale pliki na dysku leżą pod angielskimi ścieżkami.
Rozwiązaliśmy to proxy w warstwie routingu — nie middleware Next.js, nie redirecty, nie 15 kopii tych samych plików. Proxy przechwytuje request, rozpoznaje locale z URL-a, tłumaczy ścieżkę na angielski odpowiednik i przekazuje do właściwego komponentu. Tłumaczenia URL-i trzymamy w bazie — moderator dodaje nowy język bez redeployu.
Bezpieczeństwo: 935 polityk RLS
Każda z 160 tabel w bazie ma polityki Row-Level Security — kto może czytać, pisać, modyfikować, usuwać, na poziomie pojedynczego wiersza. Pacjent widzi swoje dane. Klinika widzi swoich pacjentów. Moderator widzi zgłoszenia. Admin widzi wszystko. Nawet gdyby ktoś ominął frontend i strzelił bezpośrednio do API — baza odmówi.
935 polityk to nie przypadek. To wynik systematycznego podejścia: każda nowa tabela = natychmiastowe pytanie "kto ma dostęp i dlaczego". Napisaliśmy tooling do audytu, który wykrywa tabele bez RLS, zanim kod trafi do repozytorium.
Pipeline danych medycznych
6 Edge Functions (Deno runtime) odpytuje codziennie zewnętrzne źródła:
- WHO — Global Health Observatory, Disease Outbreak News
- CDC — travel notices, vaccination requirements
- Dane klimatyczne, koszty podróży, travel advisories
Dane trafiają do PostgreSQL, gdzie 16 zaplanowanych zadań (pg_cron) normalizuje je, przelicza health score'y i aktualizuje rekomendacje. Na wierzchu — pipeline ML w Pythonie: XGBoost jako predyktor ryzyka per kraj × choroba, Isolation Forest do wykrywania anomalii (nagły wzrost zachorowań → alert dla użytkowników).
Nie budowaliśmy AI dla AI. Budowaliśmy system wczesnego ostrzegania, bo stare dane w travel medicine to nie niedogodność — to realne ryzyko zdrowotne.
CI/CD: trzy bramy, zero kosztów
Największy lęk przy solo development: "a co jeśli zepsuję produkcję o 2 w nocy?". Odpowiedź — trójbramkowy pipeline, w którym ciężkie sprawdzenia odbywają się lokalnie, za darmo:
Brama 1 — lokalna (koszt: $0): pre-commit sprawdza sekrety, formatowanie i lint. Pre-push odpala pełny zestaw: lint strict, typecheck, 7 929 testów, build produkcyjny i kontrola rozmiaru bundle'a. Jeśli cokolwiek padnie — push nie przejdzie.
Brama 2 — GitHub Actions: safety net. Lint + typecheck na każdym PR (łapie sytuacje, gdyby ktoś obszedł lokalne hooki). Na merge do main — automatyczny push migracji do produkcyjnej bazy.
Brama 3 — Coolify: wykrywa nowy commit na main, buduje obraz Dockera, deployuje kontener z zero-downtime. Rollback = jedno kliknięcie w dashboardzie.
AI-augmented development
Nie "AI napisał aplikację". Developer podjął każdą decyzję architektoniczną, zaprojektował schemat bazy, ustalił konwencje i nadzorował każdą linię kodu. Claude Code działał jako pair programmer — przyspieszał implementację powtarzalnych wzorców, generował testy, pomagał w refaktoryzacji.
Efekt: wydajność porównywalna z 3-4 osobowym zespołem. Ale odpowiedzialność za architekturę, jakość i trade-offy — zawsze po stronie człowieka. AI nie zastępuje seniora. AI sprawia, że senior dostarcza szybciej.
Rezultaty
Platforma w produkcji po 4 miesiącach. Nie prototyp, nie demo — działający marketplace z bookingiem, płatnościami, panelem kliniki i panelem admina, obsługujący ruch organiczny w 15 językach.
Ale liczby mówią więcej niż opis.
Skala kodu
1 778 plików TypeScript w strict mode oznacza, że każdy typ jest jawny, każdy null sprawdzony, każdy nieużywany import to błąd kompilacji. 904 migracje oznaczają, że każda zmiana w bazie jest wersjonowana, odtwarzalna i audytowalna — zero ręcznych zmian na produkcji.
- 541 komponentów React
- 105 endpointów API, 13 Edge Functions (Deno)
- 665+ commitów
- 15 języków z pełnym routingiem i przetłumaczonymi URL-ami
Jakość i bezpieczeństwo
7 929 testów to nie efekt pisania testów dla testów. Każdy test istnieje, bo chroni konkretny scenariusz — od kalkulacji health score'u przez flow rejestracji kliniki po edge case'y w tłumaczeniach RTL. Do tego mutation testing (Stryker), który weryfikuje, że testy naprawdę łapią błędy, a nie tylko podnoszą coverage.
935 polityk RLS na 160 tabelach — to poziom bezpieczeństwa, który w tradycyjnym podejściu wymagałby dedykowanego security engineera na pół etatu. U nas jest wbudowany w architekturę bazy.
- 6 ról w systemie: patient, clinic, moderator, admin, analytics_viewer, sales
- ISMS (ISO 27001) fazy 1-4 ukończone, gotowość do certyfikacji ~90%
- 93 kontrole bezpieczeństwa, 10 udokumentowanych ryzyk, 4 playbooki incydentów
- Pełna dokumentacja RODO z 72h procedurą zgłaszania naruszeń
Infrastruktura
Całość infrastruktury kosztuje mniej miesięcznie niż jedna godzina pracy senior developera. Przy porównywalnym ruchu na Vercel Pro — rachunek byłby 10-20x wyższy.
- Hosting: Coolify + Hetzner dedicated — koszt rzędu dziesiątek euro/mies.
- CDN: Cloudflare free plan — DDoS protection, edge caching, SSL za $0
- CI/CD: lokalne hooki + GitHub Actions — ciężkie testy lokalnie = ~$0 za CI
- Monitoring: SigNoz (OpenTelemetry) — pełna obserwowalność bez licencji Datadog
Co to oznacza dla biznesu
- Marketplace w produkcji — pełny flow od wyszukania kliniki przez booking po płatność Stripe
- B2B API w beta — dokumentacja, klucze, rate limiting, gotowe dla partnerów integracyjnych
- Founder's Program uruchomiony — pierwsze 50 klinik z zerową prowizją
- 4 tiery cenowe — od darmowego profilu po Enterprise z API i dedykowanym opiekunem
Czas dostarczenia
4 miesiące od pierwszego commita do produkcji. Jeden developer z AI-augmented workflow.
Dla porównania — projekt o tej skali (marketplace, 15 języków, compliance, ML pipeline, 6 integracji zewnętrznych) w tradycyjnym software house'ie to typowo 6-9 miesięcy z zespołem 4-6 osób.
Nie twierdzimy, że AI zastępuje zespół. Twierdzimy, że zmienia ekonomię dostarczania oprogramowania — i mamy na to 665 commitów dowodu.
Czego się nauczyliśmy
Ta sekcja jest dla nas tak samo ważna jak metryki. Klient, który szuka partnera technologicznego, chce wiedzieć, że potrafimy mówić o trade-offach, nie tylko o sukcesach.
AI-augmented development działa, ale inaczej niż marketing obiecuje. Claude Code jako pair programmer nie zastępuje doświadczenia. Pozwala jednemu developerowi dostarczyć output porównywalny z 3-4 osobowym zespołem — ale kluczowe decyzje architektoniczne, trade-offy i code review to zawsze człowiek.
Supabase: świetny do MVP i szybkiego startu. Ale 935 polityk RLS to dług techniczny, który trzeba świadomie zarządzać. Dałoby się uprościć, ale kosztem bezpieczeństwa. Zostawiliśmy.
15 języków od dnia 1 to trudniejsza decyzja niż "dodamy potem". Routing, testy, treści, SEO — wszystko jest 15x bardziej złożone. Ale dała nam przewagę w wyszukiwarkach, której nie da się nadrobić retroaktywnie.
Mutation testing (Stryker) obok unit testów. Wyłapuje false-positive coverage, gdzie testy przechodzą, ale nie testują tego, co powinny. Dodatkowy koszt w CI, ale wart zachodu.