trl.gft.pl · szkolenie zespołu
↑ góra
GFT · materiał szkoleniowy

Fabryka aplikacji TRL

Materiał wyjaśnia od zera, jak w GFT robimy aplikacje na telefon i komputer — od pomysłu zapisanego w jednym pliku tekstowym, aż do działającej apki w sklepie Apple i Google. Bez wystukiwania kodu ręcznie. Pisze go za nas sztuczna inteligencja, a my dyrygujemy.

Czytasz od góry do dołu, albo skaczesz po spisie treści po lewej. W prawym górnym rogu jest przełącznik jasny / ciemny. Strona drukuje się ładnie (Ctrl+P).

Słownik na start. W tekście są angielskie słowa, których nie tłumaczymy bo wszyscy w branży ich używają — ale przy pierwszym pojawieniu się piszemy obok co znaczą. Pełny słownik jest w sekcji 2. Słownik.

1. Wstęp — o czym jest to szkolenie

Wyobraź sobie fabrykę samochodów. Ktoś przychodzi i mówi: „chcę czerwony samochód z 4 drzwiami, dla rodziny z dwójką dzieci". Fabryka go robi — sama. Robotnicy wiedzą jak. Linia produkcyjna jest gotowa. Materiały na półce. Kontrola jakości na końcu. Klient odbiera gotowy produkt.

U nas jest fabryka aplikacji. Zamiast samochodów produkujemy aplikacje — takie co działają jako strona internetowa, jako apka na telefonie z Androidem i jako apka na iPhone'a. Ktoś (np. Tomasz, właściciel firmy) wpisuje w jednym pliku buduj.txt, czego chce — i fabryka robi resztę.

Kto wykonuje robotę

  • Sztuczna inteligencja — konkretnie program „Claude Opus" od firmy Anthropic. To „programista", który nie śpi, nie męczy się i pracuje dwa rzędy szybciej od człowieka.
  • Ty (i zespół) — jak brygadzista. Mówisz co ma być zrobione, sprawdzasz czy dobrze, zatwierdzasz i wysyłasz na produkcję.

Do kogo to szkolenie

  • Nowy członek zespołu — żebyś po przeczytaniu wiedział gdzie kliknąć, co czytać i czego nie ruszać.
  • Każdy w GFT, kto chce zrozumieć cały proces zamiast szukać po komunikatorze.
  • Zewnętrzny człowiek (np. kontraktor) — zanim coś nam zmieni, musi to przeczytać.

Kim jest właściciel

Tomasz (mail: t@gft.pl) — założyciel firmy. Sam nie programuje. Buduje całą fabrykę tak, żeby pisała aplikacje za niego. Każda apka, którą wypuszcza, ma od pierwszego dnia podpięte płatności (Stripe albo Lemon Squeezy — to bramki płatnicze, jak terminal w sklepie). Decyzje techniczne są zapisane w pliku CLAUDE.md i są nienegocjowalne.

2. Słownik — angielskie słowa, które się powtarzają

Te słowa pojawiają się w tekście wielokrotnie. Tu wyjaśniam co znaczą — żeby potem nie tłumaczyć przy każdym wystąpieniu.

SłowoCo znaczy
app / apkaaplikacja — czyli program, np. na telefon albo komputer
kodtekst napisany w języku programowania, który komputer wykonuje
repozytorium (repo)folder z kodem trzymany na GitHubie, z całą historią zmian
GitHubserwis, gdzie zespół trzyma kod aplikacji online — jak Dysk Google, ale dla programistów
commitzapisanie zmiany w kodzie z opisem co się zmieniło — jak „zapisz wersję" w Wordzie
pushwysłanie commitów ze swojego komputera na GitHub, żeby inni zobaczyli
branchboczna gałąź kodu — pracujesz na niej osobno, żeby nie psuć głównej
mergescalenie brancha (gałęzi bocznej) z główną — czyli „zatwierdzam zmiany"
PR / Pull Requestprośba o zatwierdzenie zmian — „spójrzcie na mój kod, zatwierdźcie albo zgłoście uwagi"
backendczęść apki działająca na serwerze — pamięta dane, sprawdza hasła, liczy
frontendczęść apki widoczna dla użytkownika — przyciski, ekrany, kolory
baza danychzorganizowane miejsce, gdzie apka pamięta dane (użytkowników, zamówienia, posty)
APIsposób, w jaki frontend rozmawia z backendem — jak menu w restauracji: zamawiasz „kawa", kelner przynosi
deployment / wdrożeniewystawienie apki na serwerze, żeby świat mógł z niej korzystać przez internet
serwerkomputer w internecie, który non stop działa i obsługuje aplikację
VPSwirtualny prywatny serwer — wynajęty serwer, który należy tylko do nas
kontener / Dockeropakowanie aplikacji ze wszystkimi jej składnikami — jak słoik z gotową zupą, którą postawisz na każdym serwerze i się odpali
Dockerfileprzepis, jak zbudować ten słoik (kontener)
buildbudowa — proces złożenia wszystkich plików w gotowy do wysyłki produkt
releasewydanie nowej wersji apki światu
tokendługi sekretny ciąg znaków — jak hasło, ale automaty go używają zamiast Ciebie
klucz APItoken specjalnie do API zewnętrznej usługi (np. żeby Twoja apka mogła pytać Google Mapy)
frameworkgotowy „szkielet" do robienia aplikacji — żebyś nie pisał wszystkiego od zera
ORMnarzędzie, które gada z bazą danych za Ciebie — piszesz po polsku „daj mi użytkowników", a ono tłumaczy na język bazy
auth (authentication)logowanie i sprawdzanie kto jest kim — login, hasło, sesja
OAuthlogowanie przez Google / Facebook / Apple, bez tworzenia nowego hasła
JWTelektroniczny „bilet" potwierdzający kim jesteś po zalogowaniu
preview envśrodowisko podglądowe — kopia apki z Twojej zmiany, żebyś sprawdził zanim wgrasz na produkcję
CI / CI/CDroboty, które automatycznie testują i wdrażają kod po każdym Twoim push'u
open source / OSSkod publicznie dostępny za darmo — możesz wziąć i wykorzystać
licencja (np. MIT, AGPL)zasady używania cudzego kodu open source — co możesz, czego musisz
forkkopia cudzego repozytorium, na której robisz własne zmiany
SaaSaplikacja, którą wynajmujesz miesięcznie zamiast kupować raz (np. Spotify, Netflix)
subskrypcjaabonament miesięczny lub roczny zamiast płatności jednorazowej
FTPstary protokół do przesyłania plików na serwer — jak Dysk Google ale tylko dla plików strony
DNSksiążka adresowa internetu — tłumaczy adresy typu „gft.pl" na numery serwera
SSL / HTTPSkłódka w przeglądarce — szyfruje rozmowę między Tobą a stroną
terminal / CLIczarne okienko, w którym wpisujesz komendy do komputera

Słów technicznych w tym materiale jest dużo. Jeśli któreś jeszcze nie ma w słowniku — kliknij Ctrl+F (szukaj na stronie) i wpisz słowo, prawdopodobnie jest gdzieś wytłumaczone w kontekście.

3. Po co fabryka — co rozwiązuje

Klasyczne robienie aplikacji na 3 platformy (strona, Android, iPhone) trwa pół roku do roku. Bo:

  • Stronę pisze się w jednym języku (np. JavaScript / React)
  • Apkę na Androida w innym (Kotlin albo Java)
  • Apkę na iPhone'a w trzecim (Swift, dodatkowo wymaga Maca z Apple do testowania)
  • Backend (część serwerowa) osobno
  • Wdrożenie ręcznie — kupujesz serwer, konfigurujesz, ustawiasz HTTPS, walczysz
  • Płatności — podłączasz Stripe, piszesz obsługę faktur, VAT-u, abonamentów

U nas fabryka łamie ten schemat. Jak?

KLASYCZNIE FABRYKA ────────── ─────── pomysł buduj.txt (jeden plik) │ │ ▼ ▼ strona w React „SCOUT" sprawdza: │ czy ktoś już zrobił 60% tego? ▼ │ apka Android w Kotlin ▼ │ piszemy plan (PLAN.md) ▼ │ apka iPhone w Swift ▼ │ piszemy testy (spec/) ▼ │ backend osobno ▼ │ AI pisze kod ▼ │ wdrożenie ręcznie ▼ │ automat wgrywa na serwer (Coolify) ▼ │ płatności ręcznie ▼ │ automat wgrywa do sklepów (EAS) ▼ │ ▼ ~6-12 MIESIĘCY ~DNI / TYGODNIE

Trzy żelazne zasady

  1. Żaden krok nie może być pominięty. Nie ma „szybkiego wdrożenia bez testów" albo „małej poprawki bez planu". Idziesz po kolei albo wcale.
  2. Każdy krok ma bramkę na wyjściu. Bramka = automatyczny test, który mówi „zielono — idź dalej" albo „czerwono — wracaj i napraw". Bez bramki nie idziesz dalej.
  3. Spec (testy akceptacyjne) są jedynym dowodem że coś jest skończone. Nie kod. Bug w produkcji = najpierw piszemy nowy test, potem fix.

Jeden kod = trzy platformy

Expo (jeden program) │ ┌────────────────┼────────────────┐ ▼ ▼ ▼ Strona Android iPhone (przeglądarka) (Google Play) (App Store) Ten sam kod. Tylko trzy razy „skompiluj inaczej". Robi to za nas chmura Expo (EAS) — bez Maca, bez Android Studio.

Expo = framework (gotowy szkielet), w którym piszesz raz a działa na 3 platformach. EAS = Expo Application Services — usługa firmy Expo, która kompiluje Twoją apkę w chmurze i wysyła do Apple oraz Google.

4. System TRL 1–9 — poziomy gotowości

TRL = Technology Readiness Level, czyli „poziom gotowości technologii". Skala od 1 do 9, wymyślona przez NASA w 1968 roku do oceny gotowości technologii kosmicznych: TRL 1 to pomysł na kartce, TRL 9 to coś, co już lata w kosmosie.

U nas w fabryce TRL pasuje idealnie:

  • TRL 1 = pomysł zapisany w pliku buduj.txt
  • TRL 9 = pierwsza prawdziwa zapłata od użytkownika w Stripe

Tabela poziomów

TRLStanBramka — co musi być gotowe, żeby przeskoczyć dalej
1Mam pomysł, napisałem buduj.txtPlik manifest.yaml się generuje i jest poprawny
2Mam planIstnieje PLAN.md + decyzja: piszemy od zera czy bierzemy gotowca
3Mam testy (zanim mam kod)Testy się ładują (mogą padać — kodu jeszcze nie ma) i kontrakt API jest poprawny
4Mam szkielet koduŚrodowisko Docker startuje, sprawdzanie błędów (typecheck) zielone
5Apka działa na moim laptopieWszystkie testy zielone na lokalnym kompie
6Apka działa na podglądzie internetowymAdres podglądowy się otwiera, testy końcowe zielone na podglądzie
7Apka działa na produkcji (klienci ją widzą)Wdrożenie zielone, system ostrzeżeń (Sentry) pokazuje 0 błędów przez 5 minut
8Apka jest w sklepach Apple i GoogleBuild w EAS się udał, w TestFlight (testerzy iPhone) i Internal Testing (testerzy Android) działa
9Apka zarabiaPierwsza prawdziwa transakcja w Stripe albo Lemon Squeezy + dane retention w PostHog (czyli klienci wracają)

Sentry = system, który łapie błędy w apce i wysyła nam alarm. TestFlight = aplikacja Apple, w której testerzy mogą zainstalować nieopublikowaną jeszcze wersję iOS. Internal Testing = to samo dla Androida w Google Play. Retention = ile osób wraca do apki kolejnego dnia / tygodnia.

Foldery na dysku

Każdy poziom TRL ma swój folder. Apka „mieszka" w folderze odpowiadającym jej obecnemu poziomowi i przesuwa się dalej tylko po przejściu bramki.

d:\6 APK APP TRL UP\ ├── TRL 1 - Pomysl ← apka świeży pomysł ├── TRL 2 - UI i funkcje ├── TRL 3 - UI UX ├── TRL 4 - Testujemy w laboratorium ├── TRL 5 - Dziala u mnie ├── TRL 6 - Dziala na stronie ├── TRL 7 - Przygotowanie do sklepow ├── TRL 8 - Dziala w sklepach ├── TRL 9 - Zarabia ← apka odnosi sukces └── TRL 9a - Update i funkcje ← rozwijamy działającą apkę
Promocja apki z poziomu na poziom = przeniesienie folderu. Nie ruszaj tego ręcznie — robi to za nas TRL Store (panel zarządzający fabryką). Ręczne przesuwanie psuje katalog.

5. Gdzie co leży na dysku

Główny folder

Wszystko żyje pod ścieżką d:\6 APK APP TRL UP\. To „korzeń" całej fabryki.

Foldery TRL 1–9

O nich była mowa wyżej — to półki produkcyjne z aplikacjami w różnych stanach gotowości.

Specjalne foldery

📁 Nowa apka\flow

Serce fabryki. Tu są pliki konstytucji, które rządzą całą produkcją:

  • CLAUDE.md — konstytucja, czyta ją AI przed każdym zadaniem
  • AGENTS.md — opisy ról AI-pomocników
  • MEMORY.md — dziennik stanu projektu
  • START.md — instrukcja uruchomienia
  • buduj-template.txt — wzór do kopiowania, jak pisać brief nowej apki
  • Foldery apps/, skills/, tools/

📁 .TRL-up

Pakiet startowy dla nowego AI-pomocnika. Gdy nowy „programista AI" wskakuje do projektu, tu znajduje wszystko, czego potrzebuje:

  • CZYTAJ_NAJPIERW.md — instrukcja na start
  • credentials.md — hasła i klucze (poza GitHubem!)
  • infrastructure.md — opis serwerów
  • deploy-playbook.md — instrukcje wdrażania
  • app-store-playbook.md — wgrywanie do sklepów
  • Folder scripts/ — gotowe komendy

📁 ovh

Pakiet wdrożeniowy. Skoncentrowany na wystawianiu apek w internecie:

  • AGENT_START_HERE.md — od zera do produkcji
  • eas.json — wzór konfiguracji do sklepów
  • scripts/deploy-www-coolify.sh
  • scripts/deploy-www-cyberfolks.sh
  • scripts/deploy-stores-eas.sh

📁 Gotowe aplikacje, all, all_app

Archiwum i skarbiec pomysłów:

  • Gotowe aplikacje/ — apki, które dotarły do TRL 9
  • all/, all_app/ — szuflada na pomysły i nieukończone projekty
  • czaty instrukcje/, pomysły/ — robocze notatki

6. Z czego są zbudowane apki — stack

Stack (po polsku „stos technologiczny") = zestaw narzędzi i bibliotek, których używamy do budowania apek. U nas jest jeden, ustalony — nie wybierasz go od projektu do projektu.

Decyzje są zapisane w konstytucji CLAUDE.md i są nienegocjowalne. Gdybyś chciał coś zmienić — trzeba odpalić testy fabryki (folder eval/) i udowodnić, że nowy wybór jest lepszy.

Cały stack jednym diagramem

┌─── FRONTEND (to, co widzi użytkownik) ─────────────┐ │ Expo (React Native) — jedna baza dla 3 platform │ │ NativeWind — stylowanie (kolory, marginesy) │ │ Expo Router — zarządzanie ekranami │ │ Zustand — pamięć ekranu (np. „kliknięto przycisk") │ │ TanStack Query — pobieranie danych z backendu │ │ zod — sprawdzanie poprawności danych w formularzach│ └────────────────────┬───────────────────────────────┘ │ ┌────────────────────▼───────────────────────────────┐ │ BACKEND (część działająca na serwerze) │ │ Node.js 22 — silnik wykonujący kod JavaScript │ │ Hono — szybki framework do budowy API │ │ zod — walidacja na styku z frontem │ │ Better-Auth — gotowy moduł logowania (login, hasło,│ │ Google, Apple, MFA) │ └────────────────────┬───────────────────────────────┘ │ ┌────────────────────▼───────────────────────────────┐ │ BAZA DANYCH │ │ Drizzle — ORM (rozmówca z bazą) │ │ Postgres — sama baza danych │ │ Neon — Postgres w chmurze (z możliwością „kopii │ │ na próbę" dla każdej zmiany) │ └────────────────────┬───────────────────────────────┘ │ ┌────────────────────▼───────────────────────────────┐ │ INFRASTRUKTURA (gdzie to żyje) │ │ Coolify — panel zarządzający serwerem │ │ OVH VPS — wynajęty serwer (jak komputer w internec.)│ │ EAS — chmura Expo do budowania apek mobilnych │ │ CyberFolks — hosting starego typu (gft.pl) │ │ Doppler — sejf na hasła i klucze │ └────────────────────┬───────────────────────────────┘ │ ┌────────────────────▼───────────────────────────────┐ │ OBSERWOWANIE (alarm gdy coś idzie nie tak) │ │ Sentry — łapie błędy │ │ PostHog — śledzi co robią użytkownicy │ │ Better Stack — gromadzi logi, dzwoni gdy serwer pad│ └────────────────────────────────────────────────────┘

Dlaczego nie piszemy własnego logowania

Zamiast pisać moduł „login + hasło + zapamiętaj sesję + zalogowanie przez Google", używamy gotowego: Better-Auth.

Własne logowanieBetter-Auth (gotowiec)
2 tygodnie pisania10 minut konfiguracji
Argon2id (bezpieczne hashowanie haseł) samZ pudełka
Logowanie przez Google / Apple samWbudowane
Dwuskładnikowe (MFA) — zapomnijWbudowane
Ograniczanie prób hasła — samWbudowane
Dziury w bezpieczeństwieSprawdzone setki razy

Płatności: Stripe czy Lemon Squeezy

Bramka płatności = firma, która obsługuje przyjmowanie pieniędzy z kart, Apple Pay, Google Pay. Sami nie obsługujemy kart — to są surowe dane finansowe, regulacje i certyfikaty PCI. Wynajmujemy bramkę.

SytuacjaBierzemy
Klienci firmowi z NIP, PolskaStripe
Klienci indywidualni w Unii EuropejskiejLemon Squeezy
MVP — testujemy pomysł szybkoLemon Squeezy
Klienci z USA, AzjiStripe

MVP = Minimum Viable Product, czyli „minimalna wersja produktu, którą można pokazać klientowi". Lemon Squeezy jest „Merchant of Record" — to oznacza, że firma sama jest sprzedawcą wobec urzędu skarbowego. Bierze na siebie VAT-MOSS (specjalny VAT na sprzedaż cyfrową w UE), faktury i reklamacje. Dostajesz raz w miesiącu czek netto. Stripe to surowe narzędzie — VAT i faktury robisz sam.

7. Pomocnicy AI — Claude i jego koledzy

W fabryce sztuczna inteligencja pisze kod. Ale jest kilka „smaków" AI, każdy do innego zadania. Trzeba wiedzieć, do czego użyć którego.

Claude Code — główny programista

Claude Code to program firmy Anthropic, działa w terminalu (czarne okienko z komendami). Otwierasz go komendą claude w VS Code (popularny edytor kodu). Pod spodem chodzi model Claude Opus 4.7 — najmocniejszy model AI Anthropic'a, do złożonych zadań.

Tabela modeli — który do czego

Model AIKiedy go używaszKoszt
Opus 4.7 (200K)Architektura, debugowanie trudnych błędów, refaktoryzacja, decyzje strategiczne1× (drogi, ale wart)
Sonnet 4.6Drobne poprawki, dokumentacja, tłumaczenia, formatowanie~0.2× (5 razy taniej)
Haiku 4.5Operacje masowe (np. uporządkuj 100 plików), szybka klasyfikacja~0.05× (20 razy taniej)
Opus 4.7 1MTylko gdy w pamięci ma być pół megabajta kodu na raz~1.5× (drogi)
Gemini 2.5 ProAwaryjnie, gdy Anthropic ma awarię. Free tier — darmowy do pewnego limitu0 (free)

200K, 1M = ile tekstu model utrzymuje w pamięci. 200K = ok. 200 tysięcy tokenów = jakieś 150 stron tekstu. 1M = pół miliona tokenów = przeszło 700 stron. Token = kawałek słowa albo całe słowo, którym AI mierzy długość tekstu.

Reguła: jak chcesz przeformatować 20 plików — nie potrzebujesz Opusa. Włącz Sonnet komendą /model sonnet i jest 5 razy taniej, a wynik praktycznie ten sam.

IDE — gdzie piszemy kod

IDE = Integrated Development Environment, czyli „edytor dla programistów". To jak Word, ale do kodu — z kolorowaniem składni, podpowiadaniem, debugowaniem.

  • VS Code — główny edytor. Darmowy, od Microsoftu. W nim odpalamy Claude Code w terminalu.
  • Cursor — VS Code z wbudowanym AI-pomocnikiem (Composer).
  • Windsurf — alternatywa Cursora od Codeium.
  • Comet — przeglądarka Perplexity z AI, które klika za Ciebie w panelach (np. żeby coś poprawić w panelu CyberFolks bez wchodzenia tam ręcznie).
Ważna zasada: uruchamiasz VS Code zawsze komendą code -n (n = nowe okno). Nigdy code -r (r = reuse, czyli „użyj istniejącego okna") — bo to zabija sesję Claude w już otwartym oknie.

8. Narzędzia codzienne fabryki

Oprócz pomocników AI mamy w fabryce cztery własne narzędzia — to z nimi zespół pracuje na co dzień. Wszystkie są zainstalowane lokalnie w folderze Nowa apka\flow\.

TRL Store — panel zarządzający fabryką

Aplikacja Node.js z panelem w przeglądarce. To „dyspozytornia" całej fabryki — widzisz tu wszystkie apki na wszystkich poziomach TRL, klikasz „awansuj na wyższy poziom", importujesz nowe apki z dysku, GitHuba albo FTP.

  • Gdzie żyje: Nowa apka\flow\apps\01-app-store\
  • Adres: http://localhost:3000 (po uruchomieniu)
  • Jak uruchomić: dwuklik na START-ALL.bat na pulpicie (otwiera od razu wszystko: TRL Store + screenshot-to-code)
  • Co potrafi:
    • Lista wszystkich apek pogrupowana po TRL 1–9
    • Awans apki na wyższy poziom (przesuwa folder na dysku)
    • Importowanie apek z dysku, GitHuba, FTP
    • Podgląd kodu apki w VS Code (przycisk ✏️)
    • Otwarcie apki w screenshot-to-code do poprawiania UI (przycisk 🎨)
    • Chat z szefem kuchni (Brigade de Cuisine — wieloosobowy AI, model Claude Opus 4.6)

Brigade de Cuisine = „brygada kucharska". To architektura, w której kilka modeli AI pracuje razem jak kuchnia w restauracji — szef kuchni (Claude Opus) decyduje, sous chef (Sonnet) wykonuje, commis (Haiku) sprząta. Każdy ma swoje zadanie.

screenshot-to-code — z obrazka na kod

Robisz zrzut ekranu (screenshot) ładnego UI z dowolnej strony albo apki — narzędzie generuje gotowy kod HTML / React / Vue, który ten UI odtwarza. Idealne, jak zobaczysz coś co Ci się podoba i chcesz mieć podobne u siebie.

  • Gdzie żyje: Nowa apka\flow\screenshot-to-code-main\
  • Adres: http://localhost:5173 (frontend) + :7001 (backend Python)
  • Jak uruchomić: START-ALL.bat z pulpitu uruchamia razem z TRL Store
  • Co potrafi:
    • Wgrywasz zrzut ekranu → dostajesz kod HTML/React
    • Wpisujesz adres strony → narzędzie samo robi zrzut i konwertuje
    • Zakładka „My Apps" — pokazuje Twoje apki z TRL Store, klik „Popraw UI" → robi zrzut + generuje ulepszony kod
    • Modele AI: Claude (najlepszy do UI), GPT-4 Vision, Gemini

Vision model = model AI, który widzi obrazki (nie tylko czyta tekst). Może opisać co jest na zdjęciu, czytać zrzuty ekranu, generować kod z mockupu UI.

expo-converter — HTML/React → Expo (bez AI)

Mechaniczny konwerter, który bierze gotową apkę HTML albo React i automatycznie owija ją w projekt Expo (czyli daje Ci od ręki wersję na iPhone'a i Androida). Zero kosztów AI — to czysta mechaniczna konwersja.

  • Gdzie żyje: Nowa apka\flow\expo-converter\
  • Jak uruchomić:
    node converter.js "D:\6 APK APP TRL UP\TRL 5 - Dziala u mnie"
    # Wynik w ./expo-output/
  • Co robi:
    • Skanuje folder ze stronami HTML / React
    • Każdą apkę kategoryzuje: HTML / Express → owija w WebView (zawsze działa)
    • React / Vite → konwertuje na natywne komponenty Expo
    • Generuje gotowy projekt Expo, który możesz wrzucić do EAS i wypuścić w sklepach

WebView = komponent w apce mobilnej, który wewnątrz pokazuje stronę HTML — jak okno przeglądarki w środku apki. Najprostszy sposób, żeby stronę zamienić na apkę.

Praktyka TRL 5 → 6: apkę z TRL 5 (działa lokalnie jako strona) możesz natychmiast wypuścić jako apkę mobilną przez expo-converter — bez przepisywania od zera.

UI inspiracje (kreator-ui) — biblioteka komponentów

Folder pełny gotowych klocków do budowy UI: przyciski, czcionki, kolory, szablony ekranów. Kopiujesz to, czego potrzebujesz do swojej apki.

  • Gdzie żyje: Nowa apka\flow\UI inspiracje\kreator-ui\
  • Co zawiera:
    • buttony/ — gotowe style przycisków (różne wielkości, stany hover, kolory)
    • fonty/ — paczki czcionek z licencjami
    • kolory/ — palety kolorów, gradienty, motywy
    • szablony/ — całe ekrany (logowanie, dashboard, paywall)
    • start.bat — uruchamia mini-serwer z podglądem wszystkich komponentów
  • Workflow:
    1. Otwórz UI inspiracje\kreator-ui
    2. Uruchom start.bat
    3. Przeglądasz komponenty w przeglądarce, znajdujesz ten, który chcesz
    4. Kopiujesz kod do swojej apki

Cały dzień pracy — jak narzędzia łączą się ze sobą

1. Mam pomysł ──► piszę buduj.txt → folder TRL 1 2. Otwieram TRL Store (localhost:3000) ──► widzę apkę na liście TRL 1 ──► chat z Brigade (Claude Opus) o pomyśle 3. Zobaczyłem fajne UI w internecie ──► robię zrzut ekranu ──► screenshot-to-code (localhost:5173) generuje kod 4. Brakuje mi przycisku? ──► UI inspiracje\kreator-ui — kopiuję gotowca 5. Apka działa lokalnie (TRL 5) ──► expo-converter robi z niej wersję mobilną ──► EAS buduje i wysyła do App Store / Google Play (TRL 8) 6. W TRL Store klikam „awansuj" → apka leci na wyższy TRL
Wszystkie cztery narzędzia uruchamiasz jednym dwuklikiem na START-ALL.bat z pulpitu.

10. Serwery i miejsca w internecie — infrastruktura

CoGdzie lądujeJak się tam dostaje
Apka Node.js (zaawansowana, z bazą)OVH VPS / Coolifyskrypt deploy-www-coolify.sh
Strona statyczna (sam HTML)CyberFolks (gft.pl)FTP / GitHub Actions
Apka iPhoneApp StoreEAS submit (chmura Expo)
Apka AndroidGoogle PlayEAS submit
Kod źródłowyGitHub TGFTIDkomenda git push
Baza danychNeon albo Coolifymigracje przez Drizzle
Hasła i kluczeDoppler (sejf w chmurze)doppler run

OVH VPS — silnik produkcji

OVH to francuska firma hostingowa. Wynajmujemy u nich VPS — jeden mały komputer w chmurze, który działa non-stop. Adres IP: 57.131.51.124.

OVH VPS · 57.131.51.124 ┌── Coolify (panel) — :8000 │ ├── TRL Store (apka w Node.js) │ ├── WordPress │ ├── Twoje apki (gdy zrobisz git push) │ └── Środowiska podglądowe (jedno na każdą gałąź) │ ├── Traefik (rozdzielacz ruchu) — :80 / :443 │ └── Let's Encrypt (darmowy certyfikat SSL) │ ├── Docker (tu siedzą wszystkie apki w „słoikach") │ └── Postgres + Redis (bazy)

Coolify = darmowy panel zarządzający (typu „one-click deploy"). Robi za Ciebie wszystko, co kiedyś robiło się ręcznie po SSH: ściąga kod z GitHuba, buduje kontener, uruchamia, podpina HTTPS. Traefik = „odźwierny" — przyjmuje ruch z internetu i kieruje go do właściwej apki. Let's Encrypt = darmowa instytucja wydająca certyfikaty HTTPS (kłódkę w przeglądarce).

CyberFolks — hosting na gft.pl

CyberFolks to polska firma hostingowa starszego typu. Trzymamy tam tylko strony statyczne (sam HTML, bez bazy danych). Adres IP: 195.242.116.113. Logujesz się do panelu DirectAdmin pod panel.cyberfolks.pl. Limity: brak SSH, brak Dockera, brak Node.js — czyli tylko zwykłe pliki strony i WordPress.

CzynnośćCyberFolksCoolify (OVH)
Statyczne pliki HTMLtaktak
WordPresstaktak
Apka Node.jsnietak
Docker (kontenery)nietak
Środowisko podglądowe na każdy PRnietak
Logowanie po SSH (terminal)nietak
API do zarządzanianietak

GitHub TGFTID

Konto Tomasza na GitHubie nazywa się TGFTID. Wszystkie nasze repozytoria są tam. Token (długi sekretny ciąg, daje uprawnienia robotom) i pełne dane są w pliku .TRL-up/credentials.md.

mój komputer │ │ komenda: gh repo create TGFTID/<nazwa> --public --source=. --push ▼ GitHub TGFTID/<nazwa> │ │ webhook (automatyczne powiadomienie do Coolify) ▼ Coolify uruchamia: pobiera kod → buduje kontener → odpala │ ▼ Adres działa: http://<losowy-id>.57.131.51.124.sslip.io

Webhook = automatyczne powiadomienie wysyłane przez serwis (np. GitHub) do innego serwisu (np. Coolify) gdy coś się stanie (np. nowy kod). sslip.io = sprytny darmowy serwis DNS — możesz wpisać dowolny adres IP w nazwę i on go odda jako poddomenę, np. 1-2-3-4.sslip.io = 1.2.3.4.

Hasła — nigdy w kodzie

  • Lokalnie: doppler run -- pnpm dev (Doppler wstrzykuje hasła w czasie uruchomienia, do pliku ich nie zapisuje)
  • Na serwerze produkcyjnym: Coolify łączy się z Doppler i pobiera hasła do uruchomienia kontenera
  • W projekcie jest tylko .env.example (przykład) — z nazwami zmiennych ale BEZ wartości
  • Wrzucenie pliku z hasłami na GitHub = natychmiastowa rotacja wszystkich haseł (zmiana na nowe, bo stare są spalone)

Doppler = sejf na hasła i klucze API w chmurze. .env = stary sposób trzymania haseł — plik tekstowy na komputerze. U nas tego unikamy bo łatwo się go przypadkiem wgra na GitHuba.

10. Nie pisz od zera — fork-first

Zasada: zanim cokolwiek napiszesz od zera, sprawdź czy ktoś już tego nie zrobił. W internecie są setki gotowych aplikacji open source (kod publicznie dostępny, za darmo). Często możesz wziąć gotowca, zmienić logo i kolory, dodać 2 funkcje — i mamy 80% pracy zrobionej w 1 dzień.

Robi to za nas pomocnik AI o nazwie SCOUT.

manifest.yaml (czego chcemy) │ ▼ SCOUT przeszukuje internet: · awesome-selfhosted (lista gotowców do samodzielnego hostowania) · GitHub trending (najpopularniejsze repozytoria) · OSS Insight (statystyki open source) │ ▼ zwraca tabelę kandydatów: nazwa, gwiazdki, licencja, % pokrycia │ ├── ≥60% pokrycia + licencja OK ──► TRYB B (forkujemy + zmieniamy) │ └── <60% albo zła licencja ──► TRYB A (piszemy od zera)

Fork = własna kopia cudzego repozytorium. Możesz ją zmieniać u siebie, oryginał zostaje nienaruszony. Licencja = zasady używania kodu open source. Najpopularniejsze: MIT i Apache 2.0 — można robić cokolwiek (komercyjnie, bez udostępniania zmian); AGPL — można używać, ale jeśli udostępniasz aplikację publicznie, MUSISZ udostępnić swoje zmiany w kodzie.

Złote kopalnie — lista do sprawdzenia

DomenaRepozytoriumLicencja
Logowanie + baza + storage + realtimeSupabaseApache 2.0
Rezerwacje, kalendarzeCal.comAGPL
Zarządzanie projektamiPlaneAGPL
CRM (relacje z klientami)TwentyAGPL
Podpisywanie dokumentówDocumensoAGPL
Newslettery i mailingiListmonkAGPL
Formularze ankietoweFormbricksAGPL
Obsługa klienta (chat)ChatwootMIT
Analityka (klikania, zachowania)PostHogMIT
Baza wiedzy / wikiOutlineBSL
CMS (system zarządzania treścią)Payload / StrapiMIT
Kursy online (jak Udemy)Open edXAGPL
Skracacz linkówDub.coAGPL
Galeria zdjęć (jak iCloud)ImmichAGPL
Zarządzanie finansami (budżet)Maybe FinanceAGPL

Zasady używania gotowca

  1. Trzymaj oryginał jako „upstream" (źródło). Co jakiś czas pobieraj nowości z oryginału do swojej kopii (rebase).
  2. Zmieniaj tylko logo, kolory i 2-3 funkcje. Jak będziesz zmieniał wszystko, nie nadążysz z pobieraniem nowości z oryginału.
  3. Dostosowuj przez konfigurację i wtyczki, nie przez przepisywanie rdzenia.
  4. AGPL — uważaj. Jak hostujesz publicznie, MUSISZ pokazać swój kod. MIT / Apache = robisz co chcesz.
  5. Mobile (iPhone, Android) — backend (serwer) bierzemy z gotowca, ale apkę mobilną piszemy w Expo od zera, łącząc się z forkniętym backendem.

11. Wspólne klocki — skills

Skill (po polsku „umiejętność") = wspólny moduł kodu, który dokleja jakąś gotową funkcjonalność do każdej apki w fabryce. To cienki wrapper (opakowanie) na popularną bibliotekę.

Idea: nie piszesz logowania od zera w każdej apce. Importujesz skills/auth i masz logowanie. Pod spodem to Better-Auth, ale Tobie tego nie pokazuje.

skills/ ├── auth/ ─► opakowanie na Better-Auth │ useAuth · LoginScreen · AuthGuard · signIn · signOut │ ├── payments/ ─► opakowanie na Stripe / Lemon Squeezy │ PaywallScreen · useSubscription · openCheckout │ ├── notifications/ ─► powiadomienia push (Expo) + email (Resend) │ sendEmail · scheduleNotification · useNotifications │ ├── observability/ ─► Sentry + PostHog + Better Stack │ initObservability · trackEvent · captureError · useFeatureFlag │ └── ui-kit/ ─► komponenty z brandingiem GFT Button · Card · Input · Modal · Toast · Avatar · Layout

Przykład użycia

// gdzieś w ekranie apki:
import { PaywallScreen, useSubscription, openCheckout } from '@skills/payments'

const { isPro } = useSubscription()
if (!isPro) return <PaywallScreen plan="pro" />

return (
  <Button onPress={() => openCheckout({ priceId: 'price_xxx' })}>
    Wykup Pro — 49 PLN miesięcznie
  </Button>
)

Co tu się dzieje? Pytamy „czy ten użytkownik ma Pro?". Jeśli nie — pokazujemy ekran zachęty (PaywallScreen). Jeśli tak — pokazujemy jego funkcje. Przycisk „Wykup Pro" otwiera Stripe Checkout, ale my nic o tym nie wiemy — robi to za nas wrapper.

Reguła: nigdy nie importuj stripe, better-auth ani @sentry/react-native bezpośrednio. Zawsze przez nasz skill. Wyjątek: kod samego skilla (tam musi).

12. Cały proces od pomysłu do produkcji

Tu jest cały pipeline (po polsku „taśma produkcyjna") fabryki — kroki, przez które przechodzi każda nowa apka. Każdy krok ma swojego AI-pomocnika i bramkę kontroli na końcu.

KROK 0 ──► buduj.txt [WEJŚCIE] │ KROK 0.5 ──► SCOUT (szukamy gotowca) │ KROK 1 ──► PLANNER → PLAN.md │ KROK 1.5 ──► SPECCER → spec/ (testy) │ KROK 2 ──► BOOTSTRAPPER → środowisko Docker │ KROK 3 ──► DB → schemat bazy + migracje │ KROK 4 ──► BACKEND → endpointy API │ KROK 5 ──► FRONTEND → ekrany apki │ KROK 6 ──► VERIFIER → testy na podglądzie │ KROK 7 ──► HUMAN GATE [tu pytamy człowieka] │ KROK 8 ──► DEVOPS → wdrożenie + sklepy │ ▼ PRODUKCJA [WYJŚCIE] KROK 9 (ciągły) ── obserwowanie: Sentry błąd → GitHub issue → naprawa → podgląd → wdrożenie

Każdy krok ma deterministyczną bramkę — automat, który mówi „zielono, idź dalej" albo „czerwono, wracaj". Bez zielonej bramki nie idziesz dalej. Bramki są opisane w sekcji 26. Bramki TRL.

13. Krok 0 — buduj.txt (jedyne co piszesz ręcznie)

To jedyny plik, który piszesz ludzką ręką. Resztę generuje fabryka.

=== PODSTAWY === Nazwa [wymagane] FocusFlow Co robi (1 zdanie) [wymagane] Timer Pomodoro z analizą AI produktywności Dla kogo [wymagane] Freelancerzy 25-40 lat Główny problem [wymagane] Nie wiedzą, ile pracują skupieni === FUNKCJE === Główna (killer feature) Timer z analizą, kiedy jesteś najproduktywniejszy Dodatkowe (3-7) 1. Statystyki tygodniowe 2. Cele dzienne 3. Streaki za regularność 4. Kategorie sesji 5. Eksport danych do Excela === MONETYZACJA === Model [ ] Free [ ] Freemium [ ] Subskrypcja Plany Free: 3 kategorie, 7 dni historii Pro 49 PLN/mies: nieograniczone === PLATFORMY === Cel [ ] Strona [ ] Android [ ] iPhone === WYGLĄD === Styl [ ] Jasny [ ] Ciemny [ ] Auto Kolor główny np. #FF6600 (pomarańczowy) Charakter [ ] Minimalistyczny [ ] Kolorowy [ ] Korporacyjny === BACKEND === Panel admina [ ] Tak [ ] Nie Publiczne API [ ] Tak [ ] Nie AI w apce [ ] Nie [ ] Tak — do czego? === RODO / PRAWO === Standardowe (rejestracja + zgody) Rozszerzone (faktury, prawo do usunięcia danych)

Zasady pisania

  • Konkretnie. „Pomaga śledzić sesje skupionej pracy metodą Pomodoro" jest lepsze niż „apka do produktywności".
  • Persona — wiek + branża. To wpływa na wygląd, ton komunikatów, sposób onboardingu.
  • Monetyzacja od początku. Free / freemium / subskrypcja — nie odkładaj „na potem".
  • Kolor i charakter — wpływają na wybór biblioteki UI i ikon.

Killer feature = funkcja, dla której ktoś instaluje apkę. Onboarding = pierwsze chwile użytkownika w apce. Streaki = serie nieprzerwanej aktywności (jak w Duolingo). Persona = profil typowego użytkownika.

14. Krok 0.5 — SCOUT, szukamy gotowca

SCOUT bierze manifest i szuka w internecie projektów open source, które już robią to, co planujesz.

NazwaLicencjaOstatni commit% pokrycia
Cal.com32kAGPL2 dni temu75%
Plane28kAGPL1 dzień temu40%
Twenty15kAGPL5 dni temu60%

Gwiazdki na GitHubie = oznaczenie „lubię to" od programistów. Im więcej, tym popularniejsze. Last commit = data ostatniej zmiany w kodzie. Świeży = aktywny projekt, stary = porzucony.

Decyzja

  • ≥60% + licencja OK → TRYB B. Forkujemy, dokładamy upstream remote (źródło), zmieniamy markę i 2-3 funkcje. Mobile piszemy w Expo jako klient SDK forkniętego backendu.
  • <60% albo licencja blokuje → TRYB A (greenfield, czyli „od zera"). Stack z konstytucji.
Bramka kroku 0.5: PLAN.md zawiera decyzję A/B z uzasadnieniem. Jeśli B — link do forkniętego repozytorium i lista zmian.

15. Krok 1 — PLANNER pisze plan

PLANNER to AI-pomocnik, który czyta manifest i wynik SCOUT-a. Generuje plik PLAN.md — listę „co trzeba zrobić".

PLAN.md zawiera: • Lista ekranów (z opisem, co każdy robi i jakie dane pokazuje) • Lista endpointów API (jaką metodą, co zwraca, co przyjmuje) • Schemat tabel bazy danych (jak będzie wyglądała baza) • Lista skills do podpięcia (auth, payments, ...) • Lista bibliotek do zainstalowania • Kolejność prac

Endpoint = pojedynczy adres w API, np. POST /users = „dodaj użytkownika". Schemat tabeli = projekt tabeli — jakie kolumny, jakie relacje.

Bramka: PLAN.md istnieje, ma wszystkie sekcje, jest zgodny z manifestem.

16. Krok 1.5 — SPECCER, najważniejszy krok

To jest absolutnie najważniejszy moment. Zanim ktokolwiek napisze choć linię kodu — SPECCER pisze testy.

Spec (z angielskiego „specification") = specyfikacja, czyli dokładny opis, co apka MA robić. U nas spec = zestaw testów akceptacyjnych. Testy akceptacyjne = automatyczne klikanie w apce, sprawdzające czy to, co użytkownik chce, faktycznie działa.

spec/ ├── acceptance/ Playwright e2e (testy klikania w apce) │ ├── auth.spec.ts „użytkownik się loguje przez Google" │ ├── payments.spec.ts „użytkownik wykupuje plan Pro" │ └── core-flow.spec.ts „główna ścieżka apki działa" │ ├── api-contracts/ │ └── v1.yaml OpenAPI 3.1 (kontrakt API) │ ├── examples/ przykładowe dane (2 OK + 2 błędne na każdy endpoint) │ └── slo.yaml cele jakości: p95 czas odpowiedzi < 500ms dostępność 99.5% budżet błędów 0.5%

Playwright = popularne narzędzie do automatycznego testowania klikania w apce (jak nagrana makro w Excelu, ale dla stron). e2e = end-to-end, czyli „od początku do końca". OpenAPI = sposób opisywania API w pliku YAML, żeby maszyny mogły go zrozumieć. SLO = Service Level Objectives, czyli „cele jakości usługi".

Bramka kroku 1.5

  • Testy akceptacyjne parsują się przez Playwright (mogą padać — kodu jeszcze nie ma, OK).
  • OpenAPI jest poprawne (sprawdzamy walidatorem).
  • SLO są zdefiniowane (czas odpowiedzi, dostępność, budżet błędów).
Spec-driven. Każdy bug w produkcji = najpierw piszemy nowy test, potem fix. Zawsze w tej kolejności.

17. Krok 2 — BOOTSTRAPPER, środowisko

BOOTSTRAPPER tworzy zamknięte środowisko deweloperskie w Dockerze. „Zamknięte" znaczy: identyczne na Twoim laptopie, na laptopie kolegi, na serwerze produkcyjnym.

.devcontainer/ ├── devcontainer.json ├── Dockerfile node:22 + pnpm + drizzle + playwright + expo └── docker-compose.yml postgres + redis + mailhog (lokalnie) infra/ ├── coolify/coolify.json definicja stosu (jak Coolify ma to zbudować) ├── doppler/doppler.yaml lista haseł (BEZ wartości) └── runbooks/ instrukcje awaryjne (np. odzyskanie bazy) .env.example klucze BEZ wartości (jako wzorzec, w repozytorium)

devcontainer = „kontener deweloperski", środowisko Docker do programowania. pnpm = szybsza wersja narzędzia npm (instalator bibliotek JavaScript). mailhog = fałszywy serwer email do testów (przyjmuje maile, ale nie wysyła nigdzie naprawdę). runbook = instrukcja awaryjna, co robić gdy coś pójdzie źle.

Po co devcontainer

  • Środowisko hermetyczne — wszystko w Dockerze.
  • Nie instalujesz nic na swoim laptopie (czysty komp).
  • Działa identycznie u każdego: Tobie, koledze, na CI, na podglądzie.
  • Eliminuje 80% błędów typu „u mnie działa".
Bramka: docker compose up w devcontainerze startuje pustą, czystą bazę. Lokalnie = CI = produkcja.

18. Krok 3 — DB, schemat bazy danych

DB-pomocnik czyta sekcję „tabele" w PLAN.md i generuje schemat Drizzle + migracje.

// backend/src/db/schema.ts
import { pgTable, uuid, text, timestamp } from 'drizzle-orm/pg-core'

export const users = pgTable('users', {
  id:        uuid('id').defaultRandom().primaryKey(),
  email:     text('email').notNull().unique(),
  name:      text('name'),
  createdAt: timestamp('created_at').defaultNow().notNull(),
  updatedAt: timestamp('updated_at').defaultNow().notNull(),
})

Migracja = zestaw poleceń, które tworzą / zmieniają strukturę bazy. Drizzle = ORM dla TypeScript-a (rozmówca z bazą). UUID = długi unikalny identyfikator (zamiast zwykłej liczby 1, 2, 3).

Zasady

  • Każda tabela ma created_at + updated_at (kiedy stworzono, kiedy ostatnio zmieniono).
  • Hasła w bazie wyłącznie w postaci hash-a Argon2id (Better-Auth robi to za nas).
  • Indeksy na kluczach obcych i polach wyszukiwania (przyspieszenie zapytań).
  • Migracje przez pnpm drizzle-kit generate, potem migrate.
Bramka: pnpm drizzle-kit migrate przechodzi bez błędów na lokalnej bazie z devcontainera.

19. Krok 4 — BACKEND, część serwerowa

BACKEND-pomocnik czyta kontrakt API + schemat bazy i pisze endpointy w Hono (frameworku do API).

// backend/src/routes/projects.ts
import { Hono } from 'hono'
import { z } from 'zod'
import { zValidator } from '@hono/zod-validator'

const app = new Hono()

const createSchema = z.object({
  name:        z.string().min(1).max(100),
  description: z.string().optional(),
})

app.post('/', zValidator('json', createSchema), async (c) => {
  const data   = c.req.valid('json')
  const userId = c.get('userId')               // pobiera z Better-Auth
  const project = await projectService.create(userId, data)
  return c.json(project, 201)
})

export default app

Co tu się dzieje? Mamy endpoint POST (dodanie nowego projektu). Najpierw walidujemy dane (zod sprawdza, czy nazwa ma od 1 do 100 znaków). Potem pobieramy ID użytkownika z tokenu (Better-Auth). Potem wołamy serwis, który zapisze projekt do bazy. Na koniec zwracamy 201 (oznacza „utworzono").

Zasady

  • Jeden plik per moduł (np. projects.ts, users.ts).
  • Logika biznesowa idzie do services/, NIE do routerów.
  • Każdy endpoint: walidacja → autoryzacja → serwis → odpowiedź.
  • Try/catch + globalna obsługa błędów.
  • Ograniczenie liczby prób na /auth/* (Better-Auth ma to wbudowane).
Bramka: pnpm typecheck ✓ · pnpm test:integration ✓ — testy uderzają w PRAWDZIWĄ bazę w devcontainerze, nie w fałszywki.

20. Krok 5 — FRONTEND, ekrany w Expo

FRONTEND-pomocnik generuje ekrany w Expo Router. Pobiera dane przez TanStack Query (typy są automatycznie z OpenAPI), używa skills/.

apps/mobile/ ├── app/ ← routing oparty o pliki (jak Next.js) │ ├── _layout.tsx główny layout (TanStack Query, Auth, Theme) │ ├── index.tsx ekran startowy / │ ├── (auth)/ │ │ ├── login.tsx /login │ │ └── register.tsx │ └── (app)/ │ ├── _layout.tsx zakładki na dole │ ├── home.tsx /home │ └── settings.tsx /settings │ ├── components/ ├── hooks/ ← useProjects, useUser, ... └── app.json ← ikona, splash screen, identyfikator paczki

Splash screen = ekran ładowania z logiem widoczny przy uruchomieniu apki. Hook = funkcja w React, która „zaczepia" coś (np. dane z API). Identyfikator paczki (bundle identifier) = unikalna nazwa apki dla Apple / Google, np. pl.gft.focusflow.

UI / UX — zasady żelazne

  • Kontrast tła i tekstu co najmniej 4.5:1 (sprawdzamy automatem axe-core).
  • Nigdy szare na szarym.
  • Mobile-first (najpierw projektujemy dla telefonu, potem skalujemy do desktopu).
  • Każdy ekran ma trzy stany: ładowanie, błąd, pusty — nie tylko „happy path".
  • Onboarding, formularze, błędy — zawsze czytelne.

Happy path = ścieżka idealna, gdy wszystko działa. UX = User Experience, czyli „doświadczenie użytkownika".

Bramka: pnpm build (turbo, wszystkie apps) ✓ · pnpm typecheck ✓.

21. Krok 6 — VERIFIER, kontrola jakości

VERIFIER puszcza pełną baterię testów na środowisku podglądowym (Coolify wystawił już URL po push'u brancha).

  • spec/acceptance/ — testy Playwright na ŻYWYM URLu, nie tylko lokalnie.
  • Test kontraktu API (Schemathesis albo Dredd) — czy backend zachowuje się zgodnie z kontraktem OpenAPI.
  • Skanowanie bezpieczeństwa: pnpm audit (czy biblioteki nie mają znanych dziur), Trivy (czy obrazy Docker nie mają dziur).
  • Lighthouse na frontendzie — wydajność, dostępność (a11y), SEO.

a11y = accessibility, czyli „dostępność dla osób z niepełnosprawnościami" (kontrast, opisy obrazków, nawigacja klawiaturą). SEO = Search Engine Optimization, czyli „optymalizacja pod wyszukiwarki" (czy Google Cię znajdzie).

Bramka: WSZYSTKIE testy zielone na podglądzie. Jeden czerwony — wracasz do kroku 4 albo 5 z konkretnym błędem. Nie idziesz dalej.

22. Krok 7 — Human Gate, jedyny moment dla człowieka

To jedyny krok w całym pipeline, w którym AI pyta człowieka. Wystawia URL podglądowy, raportuje stan, czeka na decyzję.

┌──────────────────────────────────────────────────────┐ │ ✓ Zielone testy: │ │ auth · 3/3 │ │ payments · 5/5 │ │ core-flow · 7/7 │ │ │ │ 🔗 Podgląd: https://pr-42.example.com │ │ 📊 Sentry preview: [link] │ │ 📈 PostHog preview: [link] │ │ │ │ Decyzja: │ │ [merge] ─► wdrażamy na produkcję │ │ [revise] ─► lista zmian (poprawki) │ └──────────────────────────────────────────────────────┘

Nie pytamy o pierdoły, które AI może rozstrzygnąć sam (nazwa zmiennej, kolor przycisku). Pytamy WYŁĄCZNIE tutaj — czy puszczamy na produkcję?

23. Wystawiamy w internecie — deployment

Wymagania apki, żeby Coolify ją wdrożył

  • Dockerfile w głównym katalogu (przepis na kontener)
  • Serwer nasłuchuje na 0.0.0.0 (nie localhost!) — bo z zewnątrz kontenera localhost jest „w środku"
  • .dockerignore wyklucza node_modules, .env, .git
  • Repozytorium publiczne na TGFTID (GitHub App ma już dostęp)
# Dockerfile dla apki Node.js
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install --omit=dev
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

# .dockerignore
node_modules
.env
.git
*.log

# server.js — uwaga na 0.0.0.0!
const PORT = process.env.PORT || 3000;
app.listen(PORT, '0.0.0.0', () => {
  console.log(`Serwer działa na porcie ${PORT}`);
});

Pełna ścieżka wdrożenia

cd folder-apki │ │ git init · git commit · gh repo create --push ▼ GitHub TGFTID/<nazwa> │ │ bash .TRL-up/scripts/deploy-app.sh <nazwa> TGFTID/<nazwa> 3000 ▼ Coolify API tworzy zasób (apka w panelu) │ ▼ Docker build na VPS → push do registry → uruchomienie kontenera │ ▼ Traefik podpina HTTPS (Let's Encrypt automatycznie) │ ▼ URL: http://<losowy-id>.57.131.51.124.sslip.io ✓ Każdy kolejny push → webhook → automatyczne ponowne wdrożenie.

Dodanie poddomeny .gft.pl

  1. DNS w panelu CyberFolks (ręcznie, jeden raz):
    Panel · Domeny · gft.pl · Zarządzanie DNS
    Dodaj: A · <poddomena> · 57.131.51.124 · TTL 300
  2. FQDN w Coolify (przez API):
    curl -X PATCH "http://57.131.51.124:8000/api/v1/applications/$APP_UUID" \
      -H "Authorization: Bearer $COOLIFY_TOKEN" \
      -d '{"fqdn": "https://<poddomena>.gft.pl"}'
  3. Czekasz 5–10 minut, sprawdzasz: curl -I https://<poddomena>.gft.pl → 200 ✓

FQDN = Fully Qualified Domain Name, czyli pełna nazwa domeny (np. trl.gft.pl). DNS A-record = wpis w DNS, który mówi „nazwa X = adres IP Y".

Strony statyczne — CyberFolks

CyberFolks (gft.pl) nie ma SSH ani Dockera. Można tam wgrać tylko zwykłe pliki HTML/CSS/JS przez FTP. Używamy do landingów (stron promujących produkty), blogów, statycznych SPA.

Landing page = strona docelowa, na którą wpadają nowi użytkownicy. SPA = Single Page Application, czyli „aplikacja jednostronicowa" — wszystko działa w przeglądarce bez przeładowywania strony.

# Build i upload
npm run build   # tworzy folder dist/
bash .TRL-up/scripts/cyberfolks-ftp.sh ./dist/ /public_html/moja-apka/

24. Sklepy mobilne — App Store i Google Play

EAS (Expo Application Services) buduje apkę iOS i Android w chmurze — bez Maca, bez Android Studio. Robi też auto-submit, czyli automatyczne wysłanie do sklepu.

Konfiguracja raz na komputerze

npm install -g eas-cli
eas login   # konto: t@gft.pl albo 5gftid@gmail.com

eas.json — wzór konfiguracji

{
  "build": {
    "production": {
      "ios":     { "buildConfiguration": "Release" },
      "android": { "buildType": "app-bundle" }
    }
  },
  "submit": {
    "production": {
      "ios": {
        "appleTeamId": "3X6USLMFNM",
        "ascAppId": "<10-cyfrowy-App-ID-z-App-Store-Connect>"
      },
      "android": {
        "serviceAccountKeyPath": "./google-play-service-account.json",
        "track": "internal"
      }
    }
  }
}

App Store (iPhone) — pierwsze wdrożenie

  1. Wejdź na appstoreconnect.apple.com → My Apps → + → New App.
  2. Bundle ID: pl.gft.<nazwa> — dokładnie taki sam jak w app.json.
  3. Skopiuj 10-cyfrowy „App Store Connect App ID".
  4. Wklej do eas.json w polu submit.production.ios.ascAppId.
  5. Uruchom: eas build --platform ios --profile production --auto-submit.
  6. EAS Cloud Build (15–30 min) → Apple processing (10–30 min) → TestFlight Internal Testing ✓.
  7. „Submit for Review" w App Store Connect (1–3 dni recenzji Apple). Po akceptacji „Release" ręcznie.

Bundle ID = unikalny identyfikator paczki (Twoja apka różni się od innych w sklepie tylko tym). TestFlight = aplikacja Apple do testów przedpremierowych. App Review = ludzie z Apple ręcznie przeglądają każdą apkę przed publikacją (sprawdzają czy nie łamie zasad).

Google Play (Android) — service account

  1. Play Console → Setup → API access → Create new service account.
  2. Google Cloud Console → IAM → Service Accounts → Create → rola „Release Manager".
  3. Pobierz JSON klucz → zapisz jako google-play-service-account.json (NIE wgrywaj na GitHub!).
  4. Play Console → Users → Invite → email service account → rola Release Manager.
  5. Pierwszy plik .aab wgraj ręcznie w Internal Testing (raz).
  6. Kolejne razy: eas build --platform android --auto-submit działa już sam.

Service account = „konto robota" — automaty go używają zamiast hasła. .aab = format paczki Android (Android App Bundle).

Tracki Google Play

Track (kanał)Kto widziCzas recenzji
internalMaks. 100 testerówNatychmiast
alphaZamknięta lista1–2 dni
betaPubliczna z opt-in (ktoś musi się zapisać)1–2 dni
productionWszyscy w Play Store3–7 dni
Zawsze zacznij od internal. Promocja do production przez Play Console (klik) — gdy testy w internal pójdą OK.

Oba sklepy jedną komendą

bash .TRL-up/scripts/deploy-stores-eas.sh all production
# albo prosto:
eas build --platform all --profile production --auto-submit
# 3-4 godziny później: iPhone w TestFlight + Android w Play Internal

25. Pilnujemy co się dzieje — observability

Bez obserwowania nie ma TRL 7+. Produkcji której nie widzisz, nie kontrolujesz.

NarzędziePo coFree tier
SentryŁapie błędy w backend, frontend, mobile (stack trace, breadcrumbs, source maps)5 tysięcy zdarzeń / mies.
PostHogAnalityka + nagrania sesji + flagi funkcji + lejki konwersji1 milion zdarzeń / mies.
Better StackLogi (Logtail) + monitoring uptime + status page + alerty (Discord, Slack, SMS)1 GB logów / mies.

Stack trace = ślad wykonania programu, gdy się wywrócił — pokazuje gdzie się zepsuło. Breadcrumbs = „okruszki" — historia, co użytkownik klikał przed błędem. Source maps = mapa łącząca skompresowany kod produkcyjny z czytelnym oryginałem. Lejek konwersji = ile osób przechodzi przez kolejne kroki (np. zarejestrowało się, zalogowało, kupiło). Uptime = czas, w którym serwer działa nieprzerwanie. Status page = strona pokazująca, czy serwisy działają (np. status.gft.pl).

Pętla produkcyjna — co się dzieje po wdrożeniu

użytkownik klika w apce │ ▼ coś się psuje → Sentry łapie błąd ze stack trace │ ▼ Sentry → integracja z GitHub → automatycznie tworzy issue w repozytorium │ ▼ AI (Claude) czyta issue → pisze fix + nowy test w spec/ │ ▼ PR → środowisko podglądowe Coolify → VERIFIER sprawdza │ ▼ człowiek zatwierdza merge → automatyczne wdrożenie → Sentry obserwuje │ ▼ 5 min czyste → issue automatycznie zamykane ✓

Issue = zgłoszenie błędu / zadania w GitHubie. Alert fatigue = „zmęczenie alarmami" — gdy alarmów jest za dużo, ludzie przestają je czytać. Ustawiaj alerty TYLKO dla rzeczy krytycznych (P1).

26. Jak zarabiamy — Stripe vs Lemon Squeezy

Każda apka od pierwszego dnia ma podpiętą obsługę płatności. To nie jest „dopiszemy potem" — to skill, który podpina się jak logowanie.

Stripe

  • B2B z VAT-em
  • NIP-y w fakturach
  • Karty + Apple Pay + Google Pay
  • Pełne webhooki
  • Klienci spoza UE (USA, Azja)
  • Faktury i VAT MOSS — robisz sam (albo kupujesz Stripe Tax)

Lemon Squeezy

  • B2C w UE (klienci indywidualni)
  • Merchant of Record — bierze VAT MOSS
  • Faktury sam wystawia
  • Reklamacje sam obsługuje
  • Płaci raz w miesiącu netto
  • Polecane na MVP

B2B = Business to Business, czyli „firma sprzedaje firmie". B2C = Business to Consumer, „firma sprzedaje osobie prywatnej". VAT MOSS = specjalny system VAT dla sprzedaży cyfrowej w UE — naliczasz VAT klienta z jego kraju (a nie swojego). Webhook = automatyczne powiadomienie wysyłane do Twojej apki, gdy coś się stanie u dostawcy płatności (np. „klient zapłacił").

Wrapper w skill

import { PaywallScreen, useSubscription, openCheckout } from '@skills/payments'

const { isPro, isLoading } = useSubscription()
if (!isPro) return <PaywallScreen plan="pro" />
return <ProFeaturesScreen />

Wrapper ukrywa szczegóły Stripe lub LS. Jak zechcesz przesiąść się ze Stripe na LS, podmieniasz wrapper. Reszta kodu nic nie wie.

27. Bramki TRL — czeklisty przeskoków

TRL → TRLMusi być zielone
1 → 2manifest.yaml poprawny względem zod
2 → 3PLAN.md istnieje + wybrany TRYB (A greenfield / B fork)
3 → 4Playwright się parsuje · OpenAPI poprawne · SLO zdefiniowane
4 → 5devcontainer startuje · pnpm typecheck zielony
5 → 6testy unit + integration zielone (na PRAWDZIWEJ bazie!)
6 → 7URL podglądowy działa · e2e zielone na podglądzie
7 → 8wdrożenie zielone · Sentry 0 błędów przez 5 minut
8 → 9EAS build OK · TestFlight + Internal Testing aktywne
Każda bramka to automat. Nie idziesz dalej, dopóki automat nie jest zielony. Bez wyjątków, bez „to tylko ten raz".

28. Co jak się zatnie 3 razy na tym samym

Nie panikuj. Nie pytaj człowieka od razu. Przejdź te kroki po kolei:

  1. Sprawdź bramkę. Czy test/check naprawdę definiuje co jest „skończone"? Jeśli nie — dopisz nowy test do spec/. To pewnie ten brak.
  2. Sprawdź devcontainer. Czy środowisko jest hermetyczne? Czy lokalnie ≠ podgląd ≠ produkcja? Jeśli tak — napraw devcontainer, nie omijaj problemu.
  3. Sprawdź sekrety. Czy Doppler ma wszystkie klucze? Czy Coolify czyta z Doppler poprawnie? doppler secrets.
  4. Sprawdź runbook. Czy ten problem jest w infra/runbooks/? Jeśli tak — wykonaj. Jeśli nie — dopisz po naprawie.
  5. Dopisz test w eval. Jeśli problem powtarza się w różnych projektach → dodaj do eval/tasks/, żeby fabryka się tego nauczyła.
  6. Dopiero teraz idź do człowieka. I to konkretem: „utknąłem na X, próbowałem A/B/C, oto logi".

29. Sprawdź siebie — 10 pytań

Po przeczytaniu materiału powinieneś umieć odpowiedzieć:

  1. Czym różni się Coolify od CyberFolks i kiedy używasz którego?
  2. Gdzie trzymasz hasła i klucze (lokalnie, w CI, w produkcji)?
  3. Co znaczy TRL 6? Jaka jest bramka wyjścia z TRL 6?
  4. Kiedy używasz modelu Opus, kiedy Sonnet, kiedy Haiku?
  5. Fork-first — kiedy TRYB B (fork) zamiast TRYB A (od zera)?
  6. Dlaczego nie piszemy własnego JWT, tylko bierzemy Better-Auth?
  7. Co to Neon branches per PR i po co to jest?
  8. Jak publikuje się apkę do App Store od zera?
  9. Stripe vs Lemon Squeezy — kiedy który?
  10. Gdzie trafia błąd z produkcji i co się z nim dzieje?

Klucz do odpowiedzi

  1. Coolify = apki Node/Docker, środowiska podglądowe, SSH, API. CyberFolks = statyczne pliki HTML, WordPress, PHP. Apkę z bazą = Coolify. Stronę landing = CyberFolks.
  2. Lokalnie: Doppler. CI: zmienna DOPPLER_TOKEN + Doppler. Produkcja: integracja Coolify ↔ Doppler. Nigdy .env w repo.
  3. TRL 6 = środowisko podglądowe działa. Bramka: URL podglądowy się otwiera + testy e2e Playwright zielone na podglądzie.
  4. Opus = architektura, debugowanie, refaktoryzacja. Sonnet = drobne edycje, dokumentacja. Haiku = operacje masowe (100+ plików).
  5. Gdy SCOUT znajdzie OSS pokrywający ≥60% wymagań i licencja pasuje (MIT/Apache zawsze, AGPL gdy publiczny hosting jest OK).
  6. Better-Auth daje Argon2id + OAuth + MFA + ograniczenie prób z pudełka. Własny JWT = 2 tygodnie + dziury.
  7. Każdy PR ma własną kopię bazy Postgres (Neon branch). Zniszczyłeś migrację? Dropnij branch, zrób nowy. Zero ryzyka dla produkcji.
  8. (1) Stwórz apkę w App Store Connect z bundleId. (2) Skopiuj 10-cyfrowy ascAppId do eas.json. (3) eas build --platform ios --auto-submit. (4) Po recenzji Apple klikasz „Release".
  9. Stripe = B2B z NIP-em, USA. Lemon Squeezy = B2C w UE, Merchant of Record, MVP.
  10. Sentry łapie błąd → tworzy issue w GitHubie → AI czyta → pisze fix + test → PR → środowisko podglądowe → human merge → wdrożenie → Sentry obserwuje 5 min → issue zamknięte.

30. Cheatsheet — komendy do skopiowania

GitHub push (nowe repo)

cd <folder-apki>
git init && git add -A && git commit -m "init"
gh auth login --with-token <<< "$GITHUB_TOKEN"
gh repo create TGFTID/<nazwa> --public --source=. --push

Wdrożenie na Coolify (OVH)

bash .TRL-up/scripts/deploy-app.sh <nazwa> TGFTID/<repo> 3000

# Dodaj klucze API z .TRL-up
bash .TRL-up/scripts/add-env-to-coolify.sh <APP_UUID>

Upload na CyberFolks (gft.pl)

npm run build
bash .TRL-up/scripts/cyberfolks-ftp.sh ./dist/ /public_html/<subfolder>/

Build i wysyłka do sklepów

# Oba sklepy naraz:
bash .TRL-up/scripts/deploy-stores-eas.sh all production
# Albo bezpośrednio:
eas build --platform all --profile production --auto-submit
# Status:
eas build:list

SSH na VPS

ssh ubuntu@57.131.51.124
# hasło w .TRL-up/credentials.md

Coolify API — szybkie operacje

COOLIFY_TOKEN="..."  # z .TRL-up/credentials.md
BASE="http://57.131.51.124:8000/api/v1"

# Lista aplikacji
curl -s "$BASE/applications" -H "Authorization: Bearer $COOLIFY_TOKEN" \
  | jq '.[] | {name, uuid, fqdn, status}'

# Ponowne wdrożenie
curl -X POST "$BASE/applications/$APP_UUID/restart" \
  -H "Authorization: Bearer $COOLIFY_TOKEN"

# Dodaj zmienną środowiskową
curl -X POST "$BASE/applications/$APP_UUID/envs" \
  -H "Authorization: Bearer $COOLIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"key":"MOJ_KLUCZ","value":"wartosc","is_build_time":false}'

Doppler — sekrety

# Lokalnie odpal apkę z hasłami z Doppler:
doppler run -- pnpm dev
# Lista sekretów:
doppler secrets
# Ustaw nowy:
doppler secrets set MOJ_KLUCZ=wartosc

Materiał szkoleniowy · Fabryka aplikacji TRL · GFT

Pytania: t@gft.pl

Materiały źródłowe: .TRL-up/ + ovh/

Strona: trl.gft.pl