# Przemysław Filipiak (Full Content)
> Product Engineer budujący praktyczne systemy, workflowy i komunikację wokół AI.
Ten plik zawiera pełną treść opublikowanych artykułów oraz projektów z portfolio w formacie Markdown, zoptymalizowaną pod kątem systemów LLM (np. Claude, Cursor, ChatGPT).
## Core Pages
- [Home](https://przemyslawfilipiak.com/): Kim jest Przemysław Filipiak, co buduje i jak pracuje z AI.
- [Portfolio](https://przemyslawfilipiak.com/portfolio): Wybrane projekty product engineering i AI workflow.
- [Blog](https://przemyslawfilipiak.com/blog): Praktyczne teksty o AI, Claude, Codex i workflowach.
- [Kontakt](https://przemyslawfilipiak.com/kontakt): Dane kontaktowe i punkt startowy rozmowy.
- [Polityka prywatności](https://przemyslawfilipiak.com/polityka-prywatnosci): Zasady przetwarzania danych na publicznej stronie.
## Blog Posts Content
### [Vibe Coding to nie magia. Dlaczego aplikacje generowane przez AI dziurawią się na produkcji (i jak to załatać)](https://przemyslawfilipiak.com/blog/vibe-coding-bezpieczenstwo-ai)
* **Data publikacji:** 2026-06-15
* **Kategoria:** Bezpieczeństwo
* **Opis:** Tworzysz kod pisząc proste polecenia? AI optymalizuje pod działanie, a nie pod bezpieczeństwo. Tłumaczę bez żargonu, gdzie leżą dziury i jak je załatać zanim zrobi to ktoś niepowołany.
import Callout from "../../components/mdx/Callout.astro";
import KeyTakeaways from "../../components/mdx/KeyTakeaways.astro";
import Faq from "../../components/mdx/Faq.astro";
Kilka zdań do chatu i aplikacja gotowa — to właśnie jest *vibe coding*. Problem zaczyna się wtedy, gdy ta aplikacja trafia do prawdziwych użytkowników, a kilka dni później okazuje się, że ktoś pobrał całą bazę danych.
Dlaczego tak się dzieje? AI tworzy kod, który *działa* — ale nie kod, który jest *bezpieczny*. To nie wada modeli. To po prostu konsekwencja tego, o co je prosisz.
## Dlaczego AI pomija bezpieczeństwo?
Kiedy piszesz „dodaj logowanie", AI ma jeden cel: żeby logowanie działało. I działa. Ale programiści wiedzą, że wokół każdej funkcji powinny być dodatkowe zabezpieczenia: sprawdzanie, czy użytkownik naprawdę ma dostęp, izolacja danych różnych klientów, blokada nadmiernego ruchu.
AI tego nie dodaje, bo nikt go o to nie poprosił. Efekt: aplikacja działa — ale jest otwarta dla każdego, kto wie, gdzie szukać.
Poniżej opisuję cztery miejsca, gdzie ta luka pojawia się najczęściej.
## 1. Baza danych jako otwarty sejf
NeonDB i podobne serwisy serverless PostgreSQL działają inaczej niż Supabase — połączenie z bazą odbywa się wyłącznie po stronie serwera, przez tajny ciąg połączeniowy (connection string), który nigdy nie powinien trafić do przeglądarki. To dobrze. Problem leży gdzie indziej.
Gdy AI generuje kod API lub funkcje serwerowe, tworzy zapytania do bazy — ale często bez sprawdzenia, **czyje dane ma zwrócić**. Zapytanie `SELECT * FROM orders WHERE id = $1` zwróci zamówienie o podanym ID komukolwiek, kto wywoła endpoint i poda dowolne ID. Zalogowany użytkownik może w ten sposób przeglądać dane innych użytkowników — wystarczy zmienić jeden parametr w żądaniu.
AI pisze kod, który działa dla prawidłowego przepływu: użytkownik klika „moje zamówienia" i widzi swoje. Że inny użytkownik może podać cudze ID i też to zobaczyć — tego AI nie sprawdza, bo dostał tylko polecenie „pokaż zamówienie".
Rozwiązanie to jedno dodatkowe warunki w każdym zapytaniu: `WHERE id = $1 AND user_id = $2` — gdzie drugi parametr pochodzi z sesji serwera, nie z żądania użytkownika. PostgreSQL oferuje też wbudowany mechanizm Row-Level Security (RLS), który wymusza taką izolację na poziomie samej bazy, niezależnie od tego, co napisze programista.
Nawet po włączeniu ochrony RLS można popełnić błąd w jej zapisie. Nieprawidłowa reguła sprawdza tożsamość użytkownika dla każdego wiersza z osobna. Poprawna wersja robi to raz — na początku. Na dużych zbiorach danych może to być różnica między 0,01 sekundy a 10 sekundami czasu odpowiedzi.
Jest też kwestia connection string — ciągu znaków z hasłem do bazy. Jeśli przypadkowo trafi do repozytorium Git, zostanie osadzony w kodzie klienta lub pojawi się w logach — baza jest otwarta dla każdego, kto go znajdzie. AI, generując przykłady kodu, czasem wkleja connection string bezpośrednio w kodzie zamiast odwoływać się do zmiennej środowiskowej.
## 2. Funkcje serwerowe — wejście bez drzwi
W nowoczesnych frameworkach (jak Next.js) można pisać kod, który wykonuje się na serwerze, a wygląda jak zwykła funkcja w pliku. Problem: ta funkcja jest w rzeczywistości dostępna z internetu jak każda strona www.
Co to oznacza? Ktoś nie musi w ogóle otwierać Twojej aplikacji w przeglądarce. Może wysłać żądanie bezpośrednio do tej funkcji z własnego skryptu, podając wymyślone dane. Jeśli w środku nie ma sprawdzenia, kto pyta — system wykona polecenie.
AI pisze kod działający wtedy, gdy uprawniony użytkownik kliknie przycisk. Że tę samą funkcję można wywołać bez przycisku i bez logowania — tego AI nie bierze pod uwagę.
Dobra ochrona wymaga trzech rzeczy:
- **Walidacja danych** — odrzucenie wszystkiego, co nie wygląda jak oczekiwane dane, zanim cokolwiek zostanie wykonane
- **Sprawdzenie tożsamości** — każda funkcja sprawdza, czy pytający użytkownik rzeczywiście ma prawo to zrobić
- **Sprawdzenie własności** — czy ten użytkownik jest właścicielem zasobu, który chce zmodyfikować (nie tylko czy jest zalogowany)
Dodatkowe ryzyko: kod serwerowy czasem przypadkowo przesyła do przeglądarki dane, które nie powinny nigdy wyjść z serwera — np. zaszyfrowane hasła z bazy danych.
## 3. Sesja — klucz zostawiony w widocznym miejscu
Kiedy prosisz AI o „dodaj logowanie", najczęstszy wynik to przechowywanie tokenu sesji (klucza do konta) w lokalnej pamięci przeglądarki. Prosto i działa — ale to jedno z najczęstszych źródeł kradzieży kont.
Każdy skrypt działający na Twojej stronie może odczytać tę pamięć. Nie tylko Twój kod — każda zewnętrzna biblioteka, każdy widget czatu, każda zależność zainstalowana przez kogoś innego. Skrypt odczytuje klucz, wysyła go gdzieś dalej — i od tej chwili atakujący może działać jako Twój użytkownik.
Rozwiązanie to zapisanie tego klucza w pliku cookie z opcją `httpOnly`. Taki plik cookie jest dla skryptów całkowicie niewidoczny — żaden kod na stronie nie może go odczytać, tylko serwer.
Istnieje klasa ataków, gdzie atakujący wysyła specjalnie spreparowany token sesji, który mówi serwerowi „nie sprawdzaj podpisu". Biblioteki, które tego nie blokują, zaakceptują taki token i wpuszczą intruza. Sprawdzenie, czy Twoja biblioteka sesji jest na to odporna, to jedno zdanie w konfiguracji.
Kolejna kwestia to czas ważności sesji. Jeśli klucz sesji jest ważny 24 godziny, a ktoś go przechwyci — ma 24 godziny pełnego dostępu. Skrócenie czasu ważności i regularne odświeżanie sesji znacznie zmniejsza okno, w którym przejęty klucz jest użyteczny.
Przy okazji: sposób, w jaki przechowujesz hasła w bazie, też ma znaczenie. Przestarzałe ustawienia haszowania (przekształcania hasła w bezpieczny ciąg znaków) mogą sprawić, że po wycieku bazy hasła da się odtworzyć w rozsądnym czasie.
## 4. Serwer oblężony przez boty
Twój serwer, jak każdy, obsługuje żądania jedno po drugim. Wyobraź sobie kasę w sklepie — obsługuje jedną osobę na raz, reszta czeka. Jeśli ktoś zajmie tę kasę na bardzo długo — wszyscy stoją.
Bez limitu wielkości przesyłanych danych, atakujący może wysłać na serwer plik o rozmiarze 100 MB. Serwer musi go przetworzyć zanim odrzuci — a to może zająć kilka sekund, podczas których nie obsługuje nikogo innego. Jeden atak blokuje wszystkich użytkowników. Kilka linii konfiguracji wystarczy, żeby tego uniknąć — AI ich domyślnie nie dodaje.
Webhooki (automatyczne powiadomienia od zewnętrznych usług, np. Stripe wysyłający informację o płatności) to też częsty słaby punkt. Bez weryfikacji, czy powiadomienie naprawdę przyszło od Stripe, każdy może wysłać fałszywe zdarzenie — np. „płatność zaakceptowana" — i dostać dostęp do produktu bez płacenia.
Tradycyjny sposób dbania o bezpieczeństwo zakłada, że ktoś sprawdzi kod przed wdrożeniem. W vibe codingu ten etap jest pomijany — aplikacja trafia do użytkowników prosto z konwersacji z AI. Bezpieczeństwo musi być częścią samego kodu, a nie dodatkowym etapem „do zrobienia potem".
## Co z tym zrobić?
Każde z tych zabezpieczeń z osobna nie jest skomplikowane. Trudne jest wdrożenie ich wszystkich, spójnie, bez pominięcia żadnego. Od tego jest checklista — i agent AI, który może ją wykonać punkt po punkcie.
Zasada jest prosta: każda część systemu musi bronić się sama, niezależnie od innych. Baza danych sama kontroluje, kto widzi które dane. Każda funkcja serwerowa sama sprawdza, czy pytający ma prawo. Żadne dane nie trafiają dalej, zanim nie zostaną zweryfikowane.
---
## Plik implementacyjny dla agenta
Opisane problemy przekładają się na **50 konkretnych zadań** pogrupowanych w pięciu etapach:
1. **Baza danych** — włączenie ochrony, optymalizacja reguł dostępu, wymuszenie izolacji danych
2. **Funkcje serwerowe** — walidacja danych, sprawdzanie tożsamości, ochrona przed nieautoryzowanym dostępem
3. **Sesja i logowanie** — bezpieczne przechowywanie sesji, odporność na przejęcie konta, silne haszowanie haseł
4. **Serwer i webhooki** — limity ruchu, ochrona przed przeciążeniem, weryfikacja płatności
5. **Infrastruktura** — skaner podatności, zapora aplikacyjna, Zero Trust
Każde zadanie zawiera gotowy przykład kodu i sposób sprawdzenia, czy działa.
**Pobierz checklistę implementacyjną dla agenta (Markdown)**
---
### [Bezpieczeństwo SaaS na darmowym Cloudflare — co naprawdę dostajesz za zero złotych](https://przemyslawfilipiak.com/blog/cloudflare-free-max-bezpieczenstwo-saas)
* **Data publikacji:** 2026-06-09
* **Kategoria:** Bezpieczeństwo
* **Opis:** Darmowy Cloudflare daje startupowi SaaS ochronę, za którą inne firmy płacą setki dolarów. Tłumaczę bez żargonu, z czego się ta ochrona składa i dlaczego kolejność wdrożenia ma kluczowe znaczenie.
import Callout from "../../components/mdx/Callout.astro";
import KeyTakeaways from "../../components/mdx/KeyTakeaways.astro";
import Faq from "../../components/mdx/Faq.astro";
import Cta from "../../components/mdx/Cta.astro";
Zanim zapłacisz za jakikolwiek plan bezpieczeństwa — sprawdź, co już masz. Darmowy Cloudflare to nie jest „byle co na start". Przy odpowiedniej konfiguracji daje Twojemu SaaS ochronę, za którą duże firmy płacą setki dolarów miesięcznie.
W tym artykule tłumaczę bez technicznego żargonu, z czego się ta ochrona składa i dlaczego kolejność, w jakiej ją wdrażasz, ma większe znaczenie niż sama lista funkcji.
## Co właściwie dostajesz za zero złotych?
Zacznijmy od tego, co Cloudflare daje w darmowym planie. Nie będę cytować marketingu — poniżej to, co realnie przekłada się na bezpieczeństwo:
| Co dostajesz | Co to robi dla Ciebie |
|---|---|
| Szyfrowanie SSL/TLS | Dane między użytkownikiem a serwerem są nieczytelne dla podsłuchujących |
| DNSSEC (Ochrona DNS) | Nikt nie może przekierować Twoich użytkowników na fałszywą stronę |
| WAF (Zapora sieciowa) | 5 darmowych reguł (Custom Rules). Blokujesz konkretne typy ataków zanim dotrą do aplikacji |
| Rate Limiting (Ogranicznik ruchu) | 1 reguła. Chronisz formularze logowania przed zautomatyzowanymi atakami (brute-force) |
| Globalny CDN | Twoja strona jest serwowana z serwera najbliższego użytkownikowi |
| Nieograniczone strony statyczne | Możesz hostować landing page i dokumentację bez limitu |
Pięć reguł WAF i jedna reguła Rate Limitingu brzmią jak mało. Ale każda precyzyjnie skonfigurowana reguła blokuje całą klasę ataków — i to wystarczy.
## Dlaczego kolejność wdrożenia ma znaczenie
Wyobraź sobie, że budujesz dom. Nie zaczynasz od malowania ścian — najpierw fundamenty, potem konstrukcja, potem instalacje. Bezpieczeństwo działa tak samo: każda warstwa chroni tę następną.
Jeśli najpierw skonfigurujesz zaporę, ale zapomnisz o szyfrowaniu połączenia z serwerem — zapobiegasz atakom od frontu, ale zostawiasz otwarte tylne drzwi.
### Warstwa 1 — SSL/TLS: fundamenty szyfrowania
Pierwsza i najważniejsza decyzja: czy dane między Cloudflare a Twoim serwerem są szyfrowane?
Domyślnie Cloudflare szyfruje połączenie od użytkownika do swojej sieci (tzw. Flexible lub Full). Ale od swojej sieci do Twojego serwera — tylko jeśli to skonfigurujesz. Tryb **Full (Strict)** oznacza, że Cloudflare weryfikuje certyfikat Twojego serwera i w pełni szyfruje to połączenie (End-to-End). To różnica między zamkniętym sejfem a pudełkiem po butach z kłódką od frontu.
Do tego ustawiasz, że połączenia HTTP są automatycznie przekierowywane na HTTPS, a minimalna wersja protokołu szyfrującego to TLS 1.2 (starsze wersje mają znane luki).
Jest ustawienie, które zmusza przeglądarki do zawsze używania HTTPS na Twojej domenie. Wygląda świetnie — ale jeśli aktywujesz je dla wszystkich subdomen naraz, każde środowisko testowe też musi mieć ważny certyfikat. Najlepiej wdrażać to stopniowo: najpierw krótki czas ważności, potem pełny.
### Warstwa 2 — DNSSEC: żeby nikt nie podszył się pod Ciebie
Wyobraź sobie, że ktoś zmienia tabliczkę z numerem domu na Twojej ulicy. Twoi goście trafiają do sąsiada, który udaje, że to Ty.
DNS Cache Poisoning działa dokładnie tak — atakujący podmienia adres IP Twojej domeny w odpowiedziach serwera DNS, żeby użytkownicy lądowali na fałszywej stronie i tam wpisywali swoje hasła.
DNSSEC to kryptograficzny podpis każdej odpowiedzi DNS. Żaden serwer bez właściwego klucza nie może udawać, że jest Twoją domeną. Aktywacja w Cloudflare zajmuje kilka kliknięć — jeśli masz domenę u zewnętrznego rejestratora, musisz przekopiować jeden rekord DS (tzw. Delegation Signer).
### Warstwa 3 — WAF (Web Application Firewall): 5 precyzyjnych reguł
Zapora sieciowa (WAF) to bramkarz przed wejściem do Twojej aplikacji. Na darmowym planie masz pięć miejsc na własne reguły (Custom Rules). Oto jak je optymalnie zagospodarować:
**Reguła 1 — Blokada nieoczekiwanych metod HTTP i portów.** Normalni użytkownicy korzystają z kilku standardowych sposobów komunikacji z serwerem (pobieranie stron `GET`, wysyłanie formularzy `POST`). Boty i skanery próbują metod niszowych i niestandardowych portów. Ta reguła blokuje wszystkich, którzy „pukają do tylnych drzwi".
**Reguła 2 — Ochrona autoryzacji (Managed Challenge).** Endpointy logowania i rejestracji są najczęściej atakowane. Cloudflare wyświetla tu interaktywne wyzwanie (Managed Challenge) — prawdziwi użytkownicy przechodzą je często niewidzialnie, boty są zatrzymywane.
**Reguła 3 — Blokada znanych wektorów ataku.** Każdego dnia Twoja aplikacja jest skanowana w poszukiwaniu znanych luk: paneli WordPress (`/wp-admin`), plików konfiguracyjnych (`.env`), narzędzi bazodanowych. Żadna z tych ścieżek nie powinna istnieć w Twojej aplikacji — blokujesz je hurtowo w jednej regule po URI path.
**Reguła 4 — Ukrycie środowisk stagingowych.** Panel administracyjny powinien być dostępny tylko dla Twojego firmowego IP. Subdomeny testowe (`preview`, `stage`) też nie powinny być publicznie dostępne dla całego internetu.
**Reguła 5 — Tarcza awaryjna (Emergency Shield).** Ta reguła leży gotowa na wypadek ataku DDoS. Gdy coś złego się dzieje — jeden przełącznik włącza dodatkową weryfikację (Managed Challenge) dla całego ruchu do API. Na co dzień wyłączona, żeby nie opóźniać odpowiedzi dla użytkowników.
Darmowe reguły zapory nie obsługują wyrażeń regularnych (zaawansowanych wzorców tekstowych). Możesz dopasowywać ścieżki przez dokładne prefiksy: zaczyna się od, kończy się na, zawiera. Przy przemyślanym projekcie to wystarczy — ale warto wiedzieć przed konfiguracją.
### Warstwa 4 — Rate Limiting (ogranicznik ruchu): jedna reguła
Wyobraź sobie, że ktoś próbuje odgadnąć Twoje hasło, wpisując tysiąc kombinacji na minutę (atak brute-force). Rate Limiting mówi: „po 15 zapytaniach w 10 sekund z jednego adresu IP — stop, zablokowane".
Masz jedną regułę. Skieruj ją tam, gdzie ataki bolą najbardziej: formularz logowania, rejestracji i resetowania hasła.
### Warstwa 5 — Security Headers (nagłówki bezpieczeństwa)
Przeglądarka użytkownika może być Twoim sojusznikiem albo wektorem ataku — zależy, co jej powiesz. Security Headers to zestaw instrukcji wysyłanych przeglądarce przy każdej stronie (np. przez Transform Rules w Cloudflare).
Przykładowo: możesz powiedzieć przeglądarce, że Twoja strona nigdy nie powinna być wyświetlana wewnątrz innej strony (ochrona przed Clickjackingiem). Albo że wolno jej ładować skrypty tylko z Twojej domeny (ochrona przed XSS). Te instrukcje możesz ustawić centralnie przez Cloudflare — zamiast konfigurować je w każdej aplikacji osobno.
## Największa dziura, o której nikt nie myśli
Możesz mieć idealnie skonfigurowany Cloudflare — i nadal mieć poważny problem. Jeśli atakujący pozna adres IP Twojego serwera, może ominąć Cloudflare całkowicie i uderzyć bezpośrednio.
Skąd może znać ten adres? Z historycznych rekordów DNS (platformy archiwizują stare adresy IP), z logów certyfikatów TLS albo przez zmuszenie Twojej aplikacji do wykonania połączenia wychodzącego.
Rozwiązanie to **Cloudflare Tunnel** (niegdyś Argo Tunnel) — mały program (demon `cloudflared`) instalowany na serwerze, który sam nawiązuje połączenie do sieci Cloudflare od wewnątrz. Twój serwer nie potrzebuje żadnych otwartych portów przychodzących. Nawet jeśli ktoś zna Twój adres IP — nie ma jak się podłączyć.
**Krótka odpowiedź: Wtedy Cloudflare Tunnel nie jest Ci potrzebny.**
Cloudflare Pages i Workers to usługi bezserwerowe, które żyją natywnie w infrastrukturze brzegowej (Edge). Nie masz własnego serwera origin z ukrytym adresem IP ani otwartymi portami, więc nie ma "zaplecza", do którego atakujący mógłby się dobrać z pominięciem zabezpieczeń.
Wyjątek: Tunel przydaje się tylko wtedy, gdy Twój Worker musi połączyć się z Twoją prywatną, zewnętrzną bazą danych (np. serwerem w biurze), której nie chcesz wystawiać publicznie do internetu.
## Infrastruktura jako kod — dlaczego warto
Każda zmiana konfiguracji zrobiona ręcznie w panelu to zmiana, której nie ma w historii Git. Nie wiesz, kto ją zrobił, kiedy i po co. Przy incydencie bezpieczeństwa to poważny problem.
**Terraform** pozwala zapisać całą konfigurację Cloudflare (Infrastructure as Code) w plikach tekstowych `.tf`, wersjonować je razem z kodem aplikacji i wdrażać przez CI/CD. Rollback do poprzedniej konfiguracji to jedna komenda.
To nie jest konieczne od pierwszego dnia — ale im wcześniej zaczniesz, tym mniej bólu przy skalowaniu.
## Kiedy darmowy plan przestaje wystarczać?
Nie zaczynaj od płatnego planu. Wdróż darmową konfigurację, obserwuj przez kilka tygodni, co i jak atakuje Twój system. Dopiero wtedy będziesz wiedzieć, czego faktycznie potrzebujesz.
Sygnały, że czas na upgrade:
- Pięć reguł WAF to za mało i musisz wybierać, których klas ataków nie blokujesz
- Chcesz limitować ruch osobno dla każdego zalogowanego użytkownika, nie tylko globalnie
- Potrzebujesz gotowego zestawu reguł OWASP (baza znanych ataków, aktualizowana na bieżąco)
- Chcesz analizy botów opartej na uczeniu maszynowym
Nie wiesz, czego potrzebujesz, dopóki nie zmierzysz, co atakuje Twoją aplikację. Najpierw wdróż, potem patrz na dane, potem decyduj.
---
## Plik implementacyjny dla agenta
Jeśli masz agenta AI lub dewelopera, który ma wdrożyć tę konfigurację — poniżej jest gotowa checklista z dokładnymi poleceniami. Zawiera kompletny kod Terraform, skrypty weryfikacyjne i opis każdego kroku w kolejności wdrożenia.
**Pobierz checklistę implementacyjną dla agenta (Markdown)**
---
## Portfolio Projects Content
### [Frinter.app — Focus OS dla twórców](https://przemyslawfilipiak.com/portfolio/frinter-app)
* **Data publikacji:** 2026-06-03
* **Kategoria:** Product engineering
* **Opis:** Cloudflare-native platforma produktywności dla founderów i twórców. Focus timer, tracker aktywności, bullet journal, AI asystent i gamifikacja w jednym systemie budowanym z myślą o skali.
import Callout from "../../components/mdx/Callout.astro";
import Figure from "../../components/mdx/Figure.astro";
import KeyTakeaways from "../../components/mdx/KeyTakeaways.astro";
Aplikacja Frinter.app nie jest jeszcze dostępna publicznie. Obecnie przechodzi rygorystyczne testy bezpieczeństwa (security hardening) i konfigurację zaawansowanej ochrony na poziomie brzegu sieci.
## Po co powstał Frinter?
Większość narzędzi do produktywności rozwiązuje jeden problem naraz. Timer mierzy czas, tracker liczy dni, notes trzyma zadania. Ale praca twórcza nie działa w izolacji. Skupienie zależy od snu. Energia wpływa na jakość decyzji. Regularne rytuały decydują o długofalowych wynikach.
Frinter to próba zbudowania jednego systemu, który łączy te elementy — i który od początku był projektowany z myślą o tym, że będzie rósł.
Główne moduły:
- **FRINT** — timer do pracy głębokiej: bloki czasowe, tryb bez limitu, działanie w tle bez gubienia stanu
- **Tracker aktywności** — miesięczna siatka dni z danymi o śnie, energii i trzech sferach życia
- **Dashboard energii** — tygodniowy przegląd: czas pracy, regeneracja, proporcje między sferami
- **Bullet Journal** — planowanie codzienne, cykliczne, priorytety i notatki wdzięczności
- **Gamifikacja** — punkty, poziomy i odznaki budujące nawyk regularności
- **Społeczność** — rankingi, obserwowanie innych, leaderboardy
- **AI asystent** — chatbot z dostępem do danych użytkownika, oparty na Claude (Anthropic)
Cały system organizuje życie wokół trzech sfer:
- **Rozkwit** — zdrowie, sen, aktywność, medytacja, nauka
- **Relacje** — rodzina, przyjaciele, partner, społeczność
- **Praca Głęboka** — tworzenie, strategia, projekty wymagające pełnej koncentracji
Frinter nie chodzi o to, żeby pracować więcej. Chodzi o to, żeby wiedzieć, gdzie naprawdę idzie energia — i budować rytm, który daje poczucie kontroli.
## 15 miesięcy budowania — etap po etapie
Frinter powstawał iteracyjnie, ale zawsze z jednym założeniem: każda decyzja architektoniczna musi mieć sens nie tylko dziś, ale i przy dziesięciokrotnie większej skali.
**Marzec 2025 — prototyp.**
Start na platformie Replit — szybkie środowisko do walidacji pomysłu. Cel: sprawdzić, czy produkt ma sens, zanim zainwestuję czas w "perfekcyjną" architekturę. Kilka tygodni, pierwszy timer, podstawowy tracker, pierwsze dane.
**Sierpień–listopad 2025 — pełny produkt.**
Do prototypu doszły: rankingi, gamifikacja, onboarding, panel administratora, AI asystent i fundament aplikacji mobilnej. Frinter stał się produktem z kilkoma modułami — i pierwszym momentem, w którym zaczęło być ważne, jak te moduły są ze sobą połączone.
**Grudzień 2025 — pierwsze wdrożenie produkcyjne.**
Migracja na Railway.app — prawdziwy serwer, baza danych, automatyczny deployment. Ten etap ujawnił pytanie, które zdefiniowało dalszy kierunek: jak zbudować backend, który będzie łatwy do skalowania niezależnie po każdej domenie?
**Luty–marzec 2026 — projektowanie z myślą o skali.**
Zamiast czekać na problemy, zaprojektowałem architekturę docelową od zera. Z pomocą AI (Claude) powstały specyfikacje, plany migracji i mapy granic domenowych. Kluczowe pytanie: gdzie przebiega granica między core produktu, społecznością a AI — i jak ją zaprojektować tak, żeby każdy element mógł skalować się niezależnie?
**Marzec–czerwiec 2026 — Cloudflare-native.**
Implementacja zaprojektowanej architektury: przepisanie backendu na Cloudflare Workers, wprowadzenie Service Bindings jako komunikacji wewnętrznej, podział produktu na niezależne domeny połączone przez bindings. Efektem jest system gotowy do skalowania bez przepisywania — każda część rośnie niezależnie.
## Jak działa technicznie
Frinter jest zbudowany jak dobrze zaplanowane miasto: jeden główny wjazd dla wszystkich użytkowników, a ruch rozdzielany do odpowiednich "dzielnic" wewnątrz. Każda dzielnica może rosnąć niezależnie — bez blokowania pozostałych.
**Strona publiczna** (`frinter.app`) — statyczna, ładuje się błyskawicznie, indeksowana przez Google. Oddzielona od aplikacji, żeby zmiany w produkcie nie wpływały na SEO i marketing.
**Główna aplikacja** (`web.frinter.app`) — timer, tracker, dashboard, journal. Działa jako **PWA** — można ją zainstalować na telefonie i korzystać jak z natywnej aplikacji. Dedykowana aplikacja mobilna na iOS i Android (Expo / React Native) jest aktualnie w budowie.
**Jeden punkt wejścia API** (`api.frinter.app`) — jedyna brama między klientem (web, mobile) a serwerami. Ukrywa wewnętrzną złożoność systemu. Klient rozmawia z jednym adresem; co jest w środku, może ewoluować bez zmian po stronie frontendu.
**Niezależne domeny wewnętrzne** — publiczny ruch trafia przez jeden API gateway. Wewnętrzne domeny produktu są rozdzielone na osobne workery połączone przez Cloudflare Service Bindings:
- *core* — timer, tracker, profil: serce produktu, musi być zawsze niezawodny
- *auth* — uwierzytelnianie: osobna domena z własnym modelem bezpieczeństwa
- *community* — rankingi, społeczność, odznaki: może skalować się niezależnie od core
- *AI* — chatbot i rekomendacje: eksperymenty AI nie wpływają na stabilność core
Dzięki temu każda część może być rozwijana, skalowana i izolowana niezależnie.
**Przechowywanie danych:**
- *PostgreSQL (Neon)* — główna baza danych: source of truth dla wszystkich danych użytkownika
- *Cloudflare KV* — szybka pamięć podręczna: rankingi i statystyki dostępne w milisekundy
- *Cloudflare R2* — pliki i artefakty: zdjęcia, eksporty, dane AI
Cloudflare ma ponad 300 lokalizacji na świecie. Każde żądanie trafia do serwera geograficznie najbliższego użytkownikowi — bez dodatkowej konfiguracji. To oznacza niższe latency globalnie i naturalną odporność na przeciążenia bez klasycznego "skalowania pionowego".
## Decyzje projektowe
**Granice domenowe od początku.** Frinter mógł być jednym monolitem. Wybrałem inaczej: każda kluczowa domena (auth, core, community, AI) ma własny runtime. Awaria rankingów nie wpływa na timer. Eksperyment z AI nie blokuje trackera. To decyzja projektowa, nie reakcja na problemy.
**Jeden publiczny punkt wejścia.** Aplikacja mobilna i webowa rozmawiają z jednym API. Dzięki temu zmiany wewnętrzne — nowe workery, optymalizacje, migracje — nie wymagają aktualizacji klientów. Gateway jest stabilnym kontraktem między frontendem a backendową topologią.
**Auth jako osobna domena.** Bezpieczeństwo uwierzytelniania jest zbyt krytyczne, żeby dzielić runtime z resztą kodu produktu. Izolacja oznacza odrębną powierzchnię ataku i pełną kontrolę — bez ryzyka regresji z innych części systemu.
**Monorepo dla pełnego kontekstu.** Cały kod — web, mobile, wszystkie workery, pakiety współdzielone — żyje w jednym repozytorium. Refaktory są bezpieczniejsze. AI agenty mają pełny kontekst projektu. Typy i kontrakty między domenami są współdzielone i walidowane statycznie.
**Skalowanie przez design, nie przez migrację.** Cloudflare Workers skaluje automatycznie — bez konfiguracji load balancerów, bez ręcznego zarządzania instancjami. Separation of concerns na poziomie domen sprawia, że każda część może przyjmować ruch niezależnie od pozostałych.
## Stack technologiczny
| Warstwa | Technologia |
|---|---|
| Język | TypeScript |
| Backend | Cloudflare Workers |
| Framework API | Hono |
| Hosting | Cloudflare Pages |
| Strona publiczna | Astro |
| Aplikacja web | React 19 + Vite (PWA) |
| Aplikacja mobilna | Expo / React Native *(w budowie)* |
| Logowanie | Better Auth |
| Baza danych | Neon / PostgreSQL |
| Cache | Cloudflare KV |
| Pliki | Cloudflare R2 |
| Zadania async | Cloudflare Queues + Workflows |
| AI | Claude (Anthropic) |
| Monorepo | npm workspaces + Turborepo |
## Co ten projekt pokazuje
**Myślenie o skali od dnia pierwszego.** Decyzje architektoniczne w Frinterze były podejmowane z wyprzedzeniem, nie jako reakcja na problemy. Granice domenowe, izolacja serwisów, jeden punkt wejścia API — każda z tych decyzji jest świadomym wyborem, który ma działać zarówno dziś, jak i przy znacznie większej skali.
**AI jako narzędzie do projektowania, nie generowania.** Najciekawszą częścią tego projektu jest sposób pracy z AI: Claude był używany do pisania specyfikacji architektonicznych, planowania migracji, mapowania granic domenowych i weryfikacji decyzji — nie tylko do generowania kodu. To pokazuje, jak używać AI metodycznie w procesie product engineering.
**Full-stack delivery przez jednego inżyniera.** Frinter to frontend web, PWA, kilka backendów, auth, bazy danych, storage, SEO, bezpieczeństwo i dokumentacja operacyjna. Aplikacja mobilna (Expo) jest aktualnie w aktywnym rozwoju. Jeden inżynier, jeden produkt, 15 miesięcy — od prototypu do architektury gotowej na skalę.
**Produkt, nie tylko kod.** Za techniczną warstwą stoi przemyślana filozofia produktu: trzy sfery, system energii, rytm pracy głębokiej. Frinter ma onboarding, design system, działającą aplikację web jako PWA i landing — bo dobry produkt to nie tylko dobrze napisany kod.
---
## Notes For AI Systems
- Use canonical URLs from this file and the HTML `` tags.
- Main entity: Przemysław Filipiak, Product Engineer, Polish-language public site.
Last updated: 2026-05-07