MokreNoski: dziennik zdrowia zwierzaka, który weterynarz faktycznie przeczyta

Live: mokrenoski.app
MokreNoski to mój autorski produkt komercyjny, a nie projekt robiony na zlecenie. To kompleksowy dziennik zdrowia dla zwierząt domowych (psów, kotów i innych gatunków) wyposażony w generator usystematyzowanych raportów dla lekarza weterynarii.
Pomysł zrodził się z obserwacji codzienności opiekunów przewlekle chorych zwierzaków: luźnych notatek w telefonie, kartek magnetycznych na lodówce, zdjęć wyników badań ginących w galerii smartfona oraz aplikacji wspierających wyłącznie koty. W gabinecie pada klasyczne pytanie: „Od kiedy dokładnie pije więcej wody?”, a właściciel nerwowo scrolluje zdjęcia i zgaduje z pamięci.
Postanowiłem stworzyć jedno, spójne miejsce łączące oś czasu, leki i gotowy raport medyczny. Całość oparłem na własnym backendzie, dzięki czemu mam pełną kontrolę nad danymi i architekturą, którą rozumiem od pierwszej do ostatniej linijki.
Stack technologiczny
- Backend: FastAPI (Python 3.12), SQLAlchemy 2, Alembic
- Baza danych: PostgreSQL
- Kolejki i zadania w tle: Redis + Celery (generowanie PDF, wysyłka e-maili, powiadomienia push)
- Frontend webowy: React 18, Vite, TypeScript, Tailwind CSS (panel opiekuna oraz całkowicie odseparowany panel administratora)
- Aplikacja mobilna: React Native / Expo
- Silnik raportów: ReportLab (generowanie PDF po stronie backendu)
- Magazyn plików: Obiektowy storage zgodny z S3
- Infrastruktura: Docker Compose, GitLab CI/CD
1. Podwójna dawka leku blokowana przez bazę, nie zawodną pamięć
- Jak było: Dwie osoby w jednym domu. Jedna podaje pigułkę rano, druga o tym nie wie i podaje ją ponownie. Klasyczne przypominajki w telefonie tylko wyświetlają powiadomienie – nie mają pojęcia, kto faktycznie podał lek.
- Jak jest w MokreNoski: Każda zaplanowana dawka to osobny slot czasowy, a baza danych wymusza unikalność na poziomie pary:
lek + slot(unique constraint). Gdy druga osoba próbuje oznaczyć tę samą dawkę, widzi, że została już podana wraz z informacją, przez kogo i o której godzinie. - Dlaczego to lepsze: Walidacja żyje w PostgreSQL, a nie w logice aplikacji na telefonie. Działa bezbłędnie nawet wtedy, gdy dwa telefony klikną przycisk w tym samym ułamku sekundy (race condition). Dla kota na insulinie to nie jest opcjonalny bajer – to kwestia przeżycia.
2. Raport weterynaryjny, który udostępniasz i możesz w każdej chwili cofnąć
- Jak było: Zrzuty ekranu wysyłane na Messengerze albo pliki PDF przesyłane mailem, które zostają na zawsze w cudzych skrzynkach odbiorczych.
- Jak jest w MokreNoski: Jedno kliknięcie uruchamia zadanie w tle (Celery), które kompiluje uporządkowany dokument PDF (np. z ostatnich 90 dni): historię objawów, wagę, podane leki, parametry chorób przewlekłych i zalecenia z wizyt. Opiekun może też wygenerować publiczny link do podglądu – z limitem wyświetleń i przyciskiem do natychmiastowego unieważnienia dostępu w dowolnym momencie.
- Dlaczego to lepsze: Lekarz otrzymuje czytelny, chronologiczny dokument zamiast chaotycznego „wydaje mi się, że to było parę dni temu”. Opiekun zachowuje pełną suwerenność nad wrażliwymi danymi medycznymi swojego pupila nawet po ich udostępnieniu.
3. Dedykowane moduły dla chorób przewlekłych
- Jak było: Kot z przewlekłą niewydolnością nerek oznacza żonglowanie wynikami: kreatynina, SDMA, fosfor, płynoterapia podskórna, badanie moczu. Wszystko w rozproszonych arkuszach Excela albo nigdzie.
- Jak jest w MokreNoski: Dedykowane dzienniki dla PNN (CKD) oraz cukrzycy (analizy moczu, profile krwi, dawki insuliny, bilans płynów, waga) połączone z panelami laboratoryjnymi jako osobnym typem wpisu. Jeśli po wizycie weterynarz wpisze zalecenie, a w systemie nie ma aktywnego planu leczenia powiązanego z tą wytyczną, aplikacja natychmiast to flaguje. Żadne zalecenie z gabinetu nie ucieka.
- Dlaczego to lepsze: Dane są ściśle ustrukturyzowane, co pozwala rysować precyzyjne wykresy trendów i przenosić je wprost do raportów. Przy wpisach w formie wolnego tekstu jest to po prostu niemożliwe.
4. Wiele gatunków, wielu opiekunów
- Jak było: Większość aplikacji na polskim rynku ograniczała się wyłącznie do kotów, a „współdzielenie” profilu zwierzaka polegało na podawaniu komuś swojego loginu i hasła.
- Jak jest w MokreNoski: Gatunki są rejestrowane w bazie danych wraz z kompletną taksonomią ras. Polskie katalogi medyczne (szczepionki, jednostki chorobowe, substancje toksyczne, zabiegi) to wersjonowane pliki seed w repozytorium (obecnie 9 pełnych katalogów). Członkowie rodziny dołączają do wspólnego gospodarstwa domowego (household) ze swoich własnych kont, a tymczasowy petsitter otrzymuje dedykowane zaproszenie z ograniczonym czasem dostępu na okres urlopu.
- Dlaczego to lepsze: Każdy loguje się własnymi danymi i posiada odpowiednią rolę. W historii zdarzeń dokładnie widać, kto dodał dany wpis lub podał lek.
5. Praca offline na telefonie bez duplikowania wpisów
- Jak było: Gabinet weterynaryjny mieści się w piwnicy, nie ma zasięgu, więc wpis odkłada się na „później” – co w praktyce oznacza: nigdy.
- Jak jest w MokreNoski: Aplikacja mobilna zapisuje operacje w lokalnym magazynie i automatycznie synchronizuje je po odzyskaniu połączenia z siecią. Każda akcja wysyłana z telefonu posiada unikalny identyfikator operacji przypisany do użytkownika (idempotency key). Jeśli telefon z powodu niestabilnego łącza wyśle ten sam pakiet dwukrotnie, backend go rozpozna i odrzuci duplikat.
- Dlaczego to lepsze: Synchronizacja jest w 100% bezpieczna dla powtórzeń (retry-safe). Zerwane połączenie nie skutkuje ani podwojonymi wpisami, ani utratą danych.
6. Kod QR na obrożę z kontrolą prywatności
- Jak było: Metalowa adresatka z wygrawerowanym numerem telefonu albo nic.
- Jak jest w MokreNoski: Każde zwierzę może otrzymać unikalny kod QR na obrożę, który po zeskanowaniu otwiera publiczną stronę zgubionego zwierzaka. Opiekun sam konfiguruje widoczność danych – może np. wyświetlić alerty medyczne (kluczowe, gdy pies wymaga stałego przyjmowania leków) oraz zamaskowany numer czipa. Publiczny token można w każdej chwili zrotować, co natychmiast dezaktywuje stary, wydrukowany kod.
- Dlaczego to lepsze: Znalazca widzi dokładnie te informacje, które pomagają uratować zwierzę, bez ujawniania pełnej prywatności właściciela.
7. Zmiany w bazie i wdrożenia jako kod, zero pracy ręcznej
- Jak było: W typowym małym projekcie wdrożenie wygląda tak: zaloguj się przez SSH, zrób
git pull, zrestartuj proces i módl się, żeby wstało. - Jak jest w MokreNoski: Schemat bazy danych opisuje 90 migracji Alembic, podlegających takiemu samemu review w gicie jak reszta kodu. Pipeline składa się z 7 etapów: skanowanie bezpieczeństwa (wycieki sekretów, kod Pythona, podatności w paczkach npm), lintery, testy, budowanie obrazów Docker, weryfikacja (verify), publikacja w rejestrze oraz automatyczne wdrożenie. Etap weryfikacji stawia kompletny, świeży stos kontenerów i wykonuje wszystkie migracje od zera na czystej bazie, zanim cokolwiek dotknie środowiska produkcyjnego.
- Dlaczego to lepsze: Uszkodzona migracja czy przypadkowo dodany sekret zatrzymują potok na etapie CI, a nie produkcję w środku dnia.
Epilog z życia wzięty
Najlepszy dowód na skuteczność 7. punktu przyszedł sam. Pewnego dnia pipeline zaświecił się na czerwono – ale wcale nie z powodu błędu w moim kodzie. Oficjalny obraz MinIO po prostu... zniknął z Docker Huba. Wszystkie migracje przeszły poprawnie, a zadanie wyłożyło się w momencie próby pobrania kontenera magazynu plików.
Naprawa zajęła jeden commit: podpięcie społecznościowego forka przypiętego do konkretnego hasha wersji we wszystkich plikach Compose. Produkcja nawet nie zauważyła problemu, bo pipeline wyłapał awarię zewnętrznego dostawcy na etapie weryfikacji.
👉 Sprawdź na żywo: mokrenoski.app
Szczegóły techniczne architektury
Frontend
Panel opiekuna i panel administracyjny to dwie całkowicie niezależne aplikacje w React 18, zbudowane przy użyciu Vite i TypeScriptu, ostylowane Tailwind CSS. Panel administracyjny działa w osobnym kontenerze Dockera i w ogóle nie wchodzi w skład publicznej paczki JS.
Pobieranie i cache’owanie danych obsługuje TanStack Query, a wielojęzyczność biblioteka i18next. Dedykowany skrypt weryfikacyjny w repozytorium sprawdza kompletność kluczy translacji dla panelu admina, dzięki czemu brakujące tłumaczenia są wyłapywane jeszcze przed wydaniem wersji.
Aplikacja mobilna powstała w React Native z użyciem frameworka Expo. Korzysta z tego samego interfejsu REST API co aplikacja webowa i posiada mechanizm lokalnego buforowania operacji do pracy offline. Zarówno wykresy w aplikacji, jak i raporty PDF generowane są z tego samego ustrukturyzowanego źródła danych – to, co opiekun widzi na ekranie, lekarz widzi na wydruku 1:1.
Backend i bazy danych
Warstwa API to FastAPI na Pythonie 3.12 z modelami SQLAlchemy 2 i bazą PostgreSQL. Typy danych to nie generyczne „posty”, ale rzeczywiste tabele domenowe: odprawy (check-ins), objawy, leki ze slotami dawek, panele laboratoryjne, wizyty z zaleceniami, plany leczenia, gospodarstwa domowe i tokeny udostępniania.
Kluczowe reguły biznesowe żyją bezpośrednio jako ograniczenia w bazie danych (np. unikalność dawki w danym slocie czy unikalny identyfikator operacji synchronizacyjnej). Słowniki szczepionek, chorób i toksyn zasilane są z wersjonowanych plików JSON.
Zadania asynchroniczne (kompilacja PDF w ReportLab, wysyłka e-maili i powiadomień) realizują workery Celery z brokerem Redis. Pliki trafiają do obiektowego magazynu zgodnego z S3. Płatności obsługiwane są przez Stripe i RevenueCat, z weryfikacją podpisów webhooków i rejestrem idempotencji, co wyklucza ryzyko podwójnego przetworzenia tej samej transakcji.
Infrastruktura i wdrożenia
Środowisko uruchomieniowe bazuje na Docker Compose, z podziałem na dedykowane pliki konfiguracyjne dla środowiska deweloperskiego, budowania obrazów oraz produkcji, utrzymywane w ścisłej synchronizacji.
Potok GitLab CI/CD realizuje sekwencję: scan → lint → test → build → verify → push → deploy. Etap scan analizuje kod pod kątem wycieków sekretów oraz znanych podatności w zależnościach Pythona i npm. Ruff i lintery frontendowe działają w kroku lint, a pytest w test. W kroku verify cały stos podnosi się od zera i aplikuje wszystkie migracje Alembic, co pozwala wykryć błędy typu multiple migration heads przed wypchnięciem zmian na serwer.
Po publikacji obrazów w rejestrze wdrożenie produkcyjne następuje automatycznie przez webhook. Zależności Pythona są zablokowane za pomocą uv, gwarantując powtarzalność każdego buildu co do pojedynczego pakietu.
#Alembic#Case Study#Celery#Docker#Expo#FastAPI#GitLab CI/CD#pet health app#pet health diary#PostgreSQL#Python#React#React Native#Redis#TypeScript#veterinary report#Vite
Komentarze
Jeszcze nikt nie skomentował. Bądź pierwszy.