Aurora AIOpisz swój przypadek

Oferta

UsługiProduktyRealizacje

Dla kogo

Private EquityEnterpriseMŚP
UsługiProduktyRealizacjeO nasBlogKontakt

Baza wiedzy

Start tutajWikiSłownikPrzewodniki

Kursy Baza wiedzy

Zbuduj produkt SaaS z AI od zera — od pomysłu do pierwszej płatności

Sześć etapów od pomysłu do działającego produktu SaaS z AI: walidacja bólu, obietnica, plan, konta i płatności, własna domena i twarda weryfikacja.

Jedna ciągła świetlista nić przechodzi przez kolejne bryły na grafitowym tle — od rozproszonych punktów po lewej po zwartą, skrystalizowaną formę po prawej.
Jedna ciągła świetlista nić przechodzi przez kolejne bryły na grafitowym tle — od rozproszonych punktów po lewej po zwartą, skrystalizowaną formę po prawej.
Kursy#saas #budowanie-produktu #claude-code #codex #stripe #kurs

Najtrudniejszy moment w budowaniu produktu z AI nie przychodzi wtedy, kiedy coś się psuje. Przychodzi wtedy, kiedy wszystko wygląda na skończone. Strona się ładuje, przyciski reagują, plik PDF się generuje, a dopiero ktoś z zewnątrz zauważa, że aplikacja wypuszcza gotowy dokument do klienta na podstawie pustego formularza. Agent zrobił dokładnie to, o co go poproszono. Nikt go nie poprosił, żeby to sprawdził.

Pokażę ci całą drogę tak, żeby ten moment cię nie zaskoczył. Sześć etapów, w tej kolejności: ból, obietnica, produkt, hydraulika, opakowanie, dowód.

Przez cały tekst prowadzę jeden przykład roboczy: ClientPack, narzędzie, które zamienia transkrypcje rozmów sprzedażowych właściciela agencji w gotową prezentację ofertową w barwach jego firmy. To przykład ilustracyjny, na którym pokazuję kolejne decyzje. Aurora tego produktu nie zbudowała, nie sprzedaje i nie ma dla niego klientów. Traktuj go jak makietę do nauki, nie jak opis wdrożenia.

Ból: sprzedaj, zanim zbudujesz

Zacznij od zdania, które oszczędzi ci najwięcej czasu: nie buduj, dopóki nie masz dowodu, że ktoś tego chce. Brzmi banalnie, a mimo to większość projektów idzie odwrotnie. Najpierw powstaje produkt, potem szuka się dla niego problemu.

Kolejność, którą polecam, wygląda tak. Opisujesz problem, o którym myślisz, i konfrontujesz go z żywymi ludźmi: pytasz, czy go mają, ile ich kosztuje i ile by zapłacili za jego zniknięcie. Potem pokazujesz makietę albo krótkie demo i pytasz jeszcze raz. Dopiero z tymi odpowiedziami siadasz do budowania. Na tym polega „sprzedaj, zanim zbudujesz”: nie na wystawieniu faktury przed napisaniem kodu, tylko na zebraniu dowodu, zanim wydasz na to tydzień.

Najgorsze, co możesz zrobić na tym etapie, to poprosić model o pomysł. Prompt w rodzaju „znajdź mi dobry pomysł na biznes” nie ma w sobie niczego twojego, więc dostaniesz odpowiedź, którą tego samego dnia dostanie kilkaset innych osób. Zamiast tego wykorzystaj dane, które już masz i których nikt inny nie ma. Jeśli prowadzisz kanał, społeczność albo listę mailingową, to jest twoje źródło: komentarze, powtarzające się pytania, rzeczy, na które ludzie regularnie narzekają. Jeśli tego nie masz, źródłem jest twoja własna branża. Znasz od środka firmy budowlane, kancelarie albo gabinety stomatologiczne? Szukaj bólu tam, bo tam odróżnisz prawdziwy problem od pozornego.

Samo zbieranie i porządkowanie danych możesz spokojnie zlecić agentowi: kilku podagentom, z których każdy przeczesuje jedno źródło, a na końcu jeden zbiera wnioski w jeden dokument. Możesz oddać maszynie zbieranie i wstępne przetwarzanie. Nie możesz oddać jej zrozumienia. To ty patrzysz na wynik i decydujesz, co on właściwie mówi.

Kiedy masz już kilka kandydatur, wybierz według kryteriów, które chronią cię przed utknięciem. Ja stosuję cztery: da się to zbudować w jeden dzień, efekt jest widoczny na ekranie, obietnica mieści się w jednym zdaniu, a nowy użytkownik dostaje wartość w kilka minut, bez wdrożenia i szkolenia. Produkt wymagający dwóch tygodni nauki nie nadaje się na pierwszy własny produkt, nie dlatego, że jest zły, tylko dlatego, że nie zdążysz się z niego niczego nauczyć.

W przykładzie, który prowadzę, wybór padł na ClientPack: właściciel agencji po każdej rozmowie sprzedażowej składa ofertę od zera, za każdym razem inaczej, i nie ma jak pokazać klientowi, skąd bierze się cena. Ból jest powtarzalny, efekt widoczny, obietnica mieści się w linijce.

Ostatnia rzecz na tym etapie, i ta, którą najczęściej traktuje się jako ozdobę przed premierą: lista oczekujących. Strona z jednym zdaniem obietnicy i polem na adres e-mail to przyrząd pomiarowy. Wysyłasz link tam, gdzie siedzą ludzie, do których naprawdę mówisz, i patrzysz. Zero zapisów oznacza jedną z dwóch rzeczy: albo mówisz do niewłaściwych ludzi, albo obietnica jest za słaba. Obie odpowiedzi dostajesz w dzień, a nie po miesiącu budowania.

Obietnica: jedno zdanie dla jednej osoby

Obietnica to jedno zdanie na stronie, które mówi, co narzędzie robi i jak odpowiada na ból z poprzedniego etapu. Nie akapit. Nie trzy warianty. Jedno zdanie, które ktoś rozumie, zanim zdecyduje, czy czytać dalej.

Praktyczny test, który stosuję: pokaż samo to zdanie komuś z twojej grupy odbiorców i poproś, żeby powiedział własnymi słowami, co dostanie. Jeśli musi dopytać, zdanie jest za szerokie. Szerokość to zresztą najczęstszy błąd na tym etapie. Wąskie narzędzie dla jednej roli wygrywa z szerokim narzędziem dla wszystkich, bo tylko wąskie potrafi nazwać ból tak, że czytelnik rozpoznaje w nim własną robotę z zeszłego tygodnia.

W przykładzie odbiorca jest opisany konkretnie: ktoś, kto prowadzi agencję AI albo dopiero ją zakłada, ma kilku klientów i zaczyna tonąć w składaniu materiałów po rozmowach. Z tego wychodzi nagłówek: zamień rozmowy rozpoznawcze w gotowe pakiety ofertowe. Pod nim jedno zdanie z konkretem, co dokładnie jest w pakiecie: oferta w barwach twojej agencji, zakres prac, wyliczenie zwrotu z inwestycji i plan projektu, bez składania każdego dokumentu od nowa. I krótkie hasło marki, cztery słowa: rozmowa na wejściu, gotowy materiał na wyjściu.

Zanim zatwierdzisz taki zestaw, rozbij go o cudze głowy. Jeśli nie masz pod ręką pięciu osób z grupy docelowej, poproś agenta, żeby uruchomił kilka person, na przykład właściciela firmy, właściciela agencji i prezesa, i żeby każda z nich powiedziała, jakie jest jej pierwsze wrażenie: rozumie, ufa, czy odbiera to jako kolejne ogólne narzędzie. Persona to tu po prostu odgrywana rola: model wciela się w opisany typ odbiorcy i reaguje z jego perspektywy. Rozmowy z żywym człowiekiem to nie zastąpi. Wyłapuje za to zdania zrozumiałe wyłącznie dla ciebie, a to często wystarczy, żeby przepisać nagłówek raz jeszcze i skończyć z ostrzejszą wersją.

Jedna uwaga, która na tym etapie rzadko pada. Sama obietnica nie jest jeszcze przewagą. W przykładzie, który prowadzę, każdy, kto pomęczy narzędzie przez miesiąc, może zbudować sobie własne. To nie powód, żeby nie budować. To powód, żeby od początku wiedzieć, gdzie naprawdę będzie leżała twoja przewaga. Wrócę do tego na końcu.

Produkt: najpierw plan, dopiero potem kod

Tu zaczyna się część, w której najłatwiej stracić dzień. Odruch jest taki, żeby otworzyć agenta kodującego i powiedzieć mu „zbuduj mi aplikację, która robi X”. Agent kodujący to narzędzie, w którym model sam czyta pliki, pisze kod i uruchamia kolejne kroki na twoim komputerze. Dostaniesz coś działającego. Dostaniesz też architekturę, której nikt nie wybrał, i listę decyzji podjętych za ciebie po cichu.

Zrób inaczej: najpierw jedna sesja wyłącznie na plan. Powiedz modelowi wprost, że w tej rozmowie jest kierownikiem projektu, a nie wykonawcą, że nie wolno mu niczego budować i że jego jedynym produktem jest dokument planu, z którego inne agenty będą potem brały zadania. To rozróżnienie brzmi jak formalność, a robi ogromną różnicę: model, któremu wolno pisać kod, zacznie pisać kod i przestanie myśleć o całości.

Potem opisz mu docelowe doświadczenie użytkownika, najlepiej mówiąc, nie pisząc. Dyktowanie głosem jest tu realną dźwignią, bo plan wymaga długiego, luźnego opisu, a nie zwięzłego promptu. W przykładzie opis brzmiał mniej więcej tak: użytkownik zakłada konto, raz wgrywa swoje logo, kolory i opisy wcześniejszych realizacji, potem zakłada projekt dla klienta, wrzuca jedną lub kilka transkrypcji rozmów, model wyciąga z nich bolączki wraz z dosłownymi cytatami klienta, przeformułowuje prawdziwe ograniczenie, proponuje plan i wskaźniki do poprawy, a na wyjściu powstaje prezentacja w barwach agencji.

Z takiego opisu wychodzi dokument, który realnie da się rozdzielić na równoległe prace. W przykładzie zawierał trzy warstwy. Pierwsza to struktura wyniku: dziesięć slajdów w stałej kolejności, czyli okładka, gdzie jesteś dziś, prawdziwe ograniczenie, plan, co się zmieni, wyliczenia, jak to działa, dlaczego my, zakres oraz inwestycja i następne kroki. Druga to architektura: Next.js App Router jako szkielet aplikacji i jej adresów, Supabase jako autentykacja i baza danych, Stripe jako płatności, plus dwa wywołania modelu na jeden projekt, z których jedno analizuje transkrypcje, a drugie generuje prezentację. Trzecia to fazy: faza zero to fundament, dalej dwie fazy rozbite na osiem strumieni, z zaznaczeniem, które zależą od siebie, a które mogą iść równolegle.

Dopiero mając ten dokument, przełączasz agenta w tryb wykonawczy. Mówisz mu: pracuj z planu, rozdzielaj zadania podagentom, wszystko, co da się zrobić równolegle, rób równolegle, każdy podagent ma raportować postęp do wspólnego pliku, a mnie wołaj tylko wtedy, gdy zabraknie ci klucza dostępowego. Reszta należy do niego.

Jest przy tym pułapka, o której trzeba wiedzieć zawczasu. Jeżeli puścisz dwa różne narzędzia AI w tym samym folderze, potrafią nadpisać sobie pracę, a zorientujesz się dopiero po tym, jak coś, co działało, przestało. Rozwiązanie jest proste i sprawdza się też przy jednym narzędziu z wieloma podagentami: każdy dostaje własny tor. Jedno narzędzie buduje funkcje, drugie wyłącznie testuje i audytuje, bez prawa zmiany kodu. Podagenty pracujące jednocześnie dostają odizolowane kopie robocze repozytorium, więc fizycznie nie mogą wejść sobie w drogę. Do tego jeden wspólny plik z kontekstem projektu w katalogu głównym, żeby oba narzędzia znały te same zasady i tę samą historię decyzji.

Świetlisty szkielet planu w lewym górnym rogu rozdziela się na cztery równoległe kanały biegnące w osobnych, oddzielonych ściankami rowkach, które nigdzie się nie stykają.
Świetlisty szkielet planu w lewym górnym rogu rozdziela się na cztery równoległe kanały biegnące w osobnych, oddzielonych ściankami rowkach, które nigdzie się nie stykają.

Hydraulika: konta, dane i płatności

Hydraulika to trzy rzeczy: kto się loguje, gdzie lądują dane i jak wchodzą pieniądze. Zanim przejdziesz do kroków, cztery pojęcia po polsku, bo będą wracać.

Autentykacja to sprawdzanie, czy osoba przy klawiaturze jest tym, za kogo się podaje: rejestracja, logowanie i potwierdzenie adresu e-mail. Baza danych to uporządkowany magazyn na wszystko, co aplikacja musi pamiętać między jedną wizytą a drugą. Klucz API to długi ciąg znaków, którym twoja aplikacja przedstawia się cudzej usłudze; kto go ma, ten może działać w twoim imieniu i na twój rachunek. Zmienna środowiskowa to nazwane ustawienie podawane aplikacji z zewnątrz, zwykle właśnie po to, żeby klucze i adresy nie leżały w kodzie.

Krok pierwszy: zanim cokolwiek założysz, zapytaj agenta, który pisał plan, czego właściwie potrzebuje. Odpowiedź w przykładzie była jednoznaczna: Supabase obsługuje konta i bazę, Stripe wyłącznie płatności i nie dotyka logowania. Dzięki jednemu pytaniu wiesz, jakie konta zakładasz i jakie klucze pobierasz, i nie tracisz godziny na usługę, której nikt nie zamawiał.

Krok drugi: Supabase. Zakładasz darmowy projekt, ustawiasz hasło do bazy i zapisujesz je sobie w bezpiecznym miejscu. Potem wchodzisz w ustawienia projektu, sekcja API, i wyjmujesz trzy rzeczy: adres projektu, publiczny klucz anon oraz sekret service role. Ten ostatni ma pełne uprawnienia do bazy, więc traktuj go jak hasło do sejfu i nigdy nie umieszczaj go w kodzie, który trafia do przeglądarki.

Krok trzeci: plik .env. To zwykły plik tekstowy w katalogu projektu, gdzie leżą wszystkie klucze, wpisany na listę plików pomijanych przez system kontroli wersji. Dzięki temu kod trafia do repozytorium, a sekrety zostają na twoim dysku. Poprosisz agenta, żeby założył ten plik, wkleisz do niego wartości i każesz sprawdzić, czy wszystkie są poprawne.

Krok czwarty: tabele. Agent nie zakłada ich sam, tylko pisze zapytanie SQL i podaje ci je do wykonania. Wklejasz je w edytor SQL w Supabase, klikasz uruchom i po chwili masz komplet tabel: subskrypcje, transkrypcje, zdarzenia zużycia, prezentacje, opisy realizacji, profile marki i kilka pomocniczych. W przykładzie było ich osiem, wszystkie powiązane identyfikatorem użytkownika. Od tego momentu agent zna strukturę bazy i może pisać resztę.

Krok piąty: Stripe, koniecznie w trybie sandbox, czyli w piaskownicy: pełnej kopii systemu płatności, w której nic nie jest prawdziwe. Zakładasz konto, wchodzisz w sekcję dla programistów, kopiujesz klucz tajny i klucz publikowalny. W piaskownicy mają one przedrostki sk_test i pk_test; wersje produkcyjne mają sk_live i pk_live i podmienisz je dopiero na samym końcu, kiedy cała ścieżka przejdzie od początku do końca. Płacisz numerami kart testowych z dokumentacji Stripe i nic nie schodzi z niczyjego konta.

Dochodzi do tego prawdziwa subskrypcja, a nie jednorazowa opłata: cykliczne obciążenie plus portal klienta, czyli gotowy ekran Stripe, na którym użytkownik sam zmienia dane i rezygnuje. Portal jest równie ważny jak sama płatność, bo subskrypcja, z której nie da się wyjść samodzielnie, wraca do ciebie jako zgłoszenie do obsługi. Jedna zmienna, sekret webhooka, poczeka do pierwszego wdrożenia, bo zależy od adresu, pod którym aplikacja stanie. Webhook to powiadomienie, które Stripe sam wysyła do twojej aplikacji, kiedy coś się u niego wydarzy, na przykład kiedy płatność przeszła. Sekret służy do potwierdzenia, że wiadomość naprawdę pochodzi od Stripe.

Na koniec ekonomia, bo hydraulika ma rachunek. W przykładzie plan darmowy to jedna prezentacja ze znakiem wodnym, a plan płatny kosztuje 39 USD miesięcznie albo 390 USD rocznie za maksymalnie 25 prezentacji. Pełny przebieg nowego użytkownika w teście (rejestracja, ustawienia marki, analiza transkrypcji, wygenerowanie prezentacji, płatność) kosztował około 0,13 USD w wywołaniach modelu, z czego mniej więcej 4 centy poszły na analizę i 9 centów na generowanie. Ten sam przebieg oszacował jednak koszt jednego pakietu na 16 do 20 centów, więc uczciwie: jedna prezentacja kosztuje gdzieś między kilkunastoma a dwudziestoma kilkoma centami, zależnie od długości transkrypcji. Przy pełnym wykorzystaniu limitu wychodzi z tego około 3 USD na użytkownika miesięcznie wobec 39 USD, które ten użytkownik płaci, a przy dłuższych transkrypcjach odpowiednio więcej. Do tego infrastruktura: przy około pięćdziesięciu użytkownikach Supabase Pro za 25 USD miesięcznie i Vercel Pro za 20 USD miesięcznie. Wszystkie te liczby to szacunki zależne od zużycia, nie cennik. Policz swoje, zanim ustawisz cenę.

Przy okazji jedna decyzja produktowa, która wygląda na kosmetyczną, a jest finansowa: między analizą a generowaniem stoi ekran przeglądu, na którym użytkownik zatwierdza wyciągnięte bolączki i liczby. Stoi tam po to, żeby nie palić droższego wywołania modelu na materiale, którego nikt nie sprawdził. Zapamiętaj ten ekran, bo wróci w następnej sekcji z zupełnie innej strony.

Trzy połączone przewodami moduły w rzędzie — wąska bramka, warstwowa płyta i zawór z podziałką — a poza ich obrysem, w osobnym polu ciemności, unosi się na cienkiej nici jeden świecący na zielono klucz.
Trzy połączone przewodami moduły w rzędzie — wąska bramka, warstwowa płyta i zawór z podziałką — a poza ich obrysem, w osobnym polu ciemności, unosi się na cienkiej nici jeden świecący na zielono klucz.

Opakowanie: marka, strona i własna domena

Opakowanie da się prowadzić równolegle z budową, bo nie zależy od kodu. Potrzebna jest tylko decyzja, czym produkt jest.

Nazwa najpierw. Poproś o warianty dosłowne, opisujące działanie, a nie abstrakcyjne, i od razu zażądaj sprawdzenia kolizji: czy takiej nazwy nie używa już produkt robiący prawie to samo. W przykładzie ten jeden warunek odrzucił dwie propozycje, które inaczej weszłyby do finału. Do tego wytyczne dla marki złożone z ograniczeń, bo ograniczenia działają lepiej niż przymiotniki: bez czerwieni, wrażenie poważnego doradztwa, nowocześnie i czysto, bez związku z twoją marką osobistą i bez estetyki „wygenerowane przez AI”. Dostajesz kilka zestawów logo z paletą, wybierasz jeden i ustalasz go jako obowiązujący dla całego produktu.

Potem strona z listą oczekujących. Tu jest miejsce na instrukcję, która oddziela stronę działającą od atrapy: powiedz wprost, że zapis adresu e-mail ma trafiać do konkretnego miejsca i że agent nie kończy pracy, dopóki tego nie sprawdzi, czyli dopóki nie otworzy strony, nie wpisze adresu, nie wyśle formularza i nie pokaże, że rekord się pojawił. Bez tego zdania dostaniesz ładny plik HTML, w którym przycisk „zapisz się” nie robi nic, i dowiesz się o tym od pierwszej osoby, która próbowała się zapisać. Dorzuć drugi ekran, chroniony hasłem, z listą zapisów i pobieraniem do pliku CSV, a potem sam wpisz testowy adres i sprawdź, czy widzisz go na liście. Zajmuje to trzydzieści sekund i zamyka całą klasę problemów.

Dalej kod idzie na GitHub, do prywatnego repozytorium. Repozytorium to zdalny magazyn plików projektu z pełną historią zmian: widzisz, co i kiedy się zmieniło, i możesz cofnąć się do dowolnej wersji. Stamtąd importujesz projekt do Vercela, czyli usługi, która bierze kod z repozytorium i sama publikuje z niego działającą stronę. Każde kolejne wgranie zmian automatycznie aktualizuje to, co widzą użytkownicy.

Pierwsze wdrożenie w przykładzie zwróciło błąd 404, czyli „nie znaleziono strony”. Zamiast szukać przyczyny ręcznie, zrób zrzut ekranu i wklej go agentowi razem z jednym zdaniem kontekstu: podłączyłem to repozytorium do Vercela, kliknąłem publikuj, widzę to. Agent widzi komunikat, konfigurację i strukturę projektu naraz, i poprawia. Zrzut ekranu to pełnoprawne zgłoszenie błędu, a szkoda czasu na opisywanie słowami czegoś, co można pokazać.

Zostaje domena. Kupisz ją bezpośrednio w Vercelu (w przykładzie wyszła 11,25 USD) albo przyniesiesz z innego rejestratora, kierując rekordy DNS na projekt. DNS to książka adresowa internetu; zmieniasz w niej wpis, żeby twoja nazwa prowadziła do twojego serwera. Potem podpinasz domenę do projektu i strona pod nią staje od razu. Co nie znaczy, że wszystko pod nią zadziała, ale do tego wrócę.

I jeszcze jedna rzecz, która wyszła dopiero z zestawienia dwóch ekranów obok siebie: aplikacja zbudowana przez jedno narzędzie nie używała logo, które drugie narzędzie umieściło na stronie z listą oczekujących. Żadne z nich nie zrobiło błędu, po prostu żadne nie miało tego w zadaniu. Kiedy dwa agenty budują równolegle, spójność marki nie jest niczyją odpowiedzialnością, dopóki jej komuś nie przypiszesz. Najtańsza kontrola to otwarcie wszystkich stron obok siebie w jednym oknie i przejechanie po nich wzrokiem raz na jakiś czas.

Dowód: część, którą prawie wszyscy pomijają

Zostaje etap, który decyduje o tym, czy masz produkt, czy demo. Zasada jest jedna i brzmi nudno, dopóki nie zobaczysz, co się dzieje bez niej: weryfikacji trzeba zażądać wprost i trzeba ją zapętlić. Agent, któremu powiesz „zbuduj X”, zbuduje X i uzna zadanie za skończone. Agent, któremu powiesz „zbuduj X, potem otwórz to, przeklikaj, spróbuj zepsuć i nie kończ, dopóki nie pokażesz mi, że działa”, zrobi zupełnie inną robotę. Różnica nie leży w modelu, tylko w tym jednym zdaniu.

Drugą warstwę daje inny model. To, co zbudowało jedno narzędzie, oddaj do sprawdzenia drugiemu, w trybie wyłącznie do odczytu, z prawem zgłaszania i bez prawa zmieniania. Najwięcej wnosi tu automatyzacja przeglądarki: agent sam otwiera aplikację, klika po kolei wszystko, wgrywa transkrypcje w różnych formatach, generuje prezentacje i wpisuje w pola rzeczy, których żaden użytkownik nie powinien wpisać. Robi w kilkadziesiąt minut przegląd, na który ty poświęciłbyś dzień, i nie ma twoich odruchów: nie omija ścieżki, o której „wiadomo”, że działa.

W przykładzie taki przegląd zwrócił dwie blokady premiery. Obie są typowe.

Pierwsza: przegląd przed generowaniem nie był wymuszony. Ekran zatwierdzania z poprzedniej sekcji istniał, ale przycisk generowania pozostawał aktywny przy zerowej liczbie bolączek, zerowej liczbie rozwiązań, ujemnej kwocie inwestycji i pustych polach obowiązkowych. Reguła była w projekcie, w planie i w rozmowie. Nie było jej w kodzie. Stąd zdanie do powieszenia nad biurkiem: reguła walidacji, której nie egzekwuje kod, nie istnieje.

Druga jest konsekwencją pierwszej i pokazuje, ile to kosztuje. Przy nieznanym zwrocie z inwestycji aplikacja generowała slajd dla klienta z wartością „0x”. Dokument idzie do kogoś, kto ma zapłacić za projekt, i mówi mu, że zwrot wyniesie zero. Nikt tego nie zaprogramował. To wynik obliczenia na pustych danych, który nigdy nie miał prawa dojść do wyjścia.

Poza tym z ręcznego przeklikania wyszedł niedziałający przycisk wylogowania, a link potwierdzający adres e-mail prowadził na stronę z listą oczekujących zamiast do aplikacji. Drobiazgi, ale każdy z nich znajduje pierwszy użytkownik w pierwszej minucie.

Osobno idzie bezpieczeństwo, bo od momentu, w którym masz konta i płatności, przechowujesz cudze dane. Tu też najlepiej sprawdza się drugi model, prowadzony według listy kontrolnej w rodzaju OWASP, czyli publicznego katalogu typowych podatności aplikacji internetowych. Najważniejszy jest test dwóch najemców. Najemca to jedno konto klienta w aplikacji obsługującej wielu klientów naraz; test polega na założeniu dwóch kont i sprawdzeniu, czy z jednego da się dosięgnąć danych drugiego. To ta klasa błędów, która nie boli, dopóki masz jednego użytkownika, a przy dziesiątym kończy się wyciekiem. W przykładzie audyt zwrócił cztery blokady o wysokiej wadze i jeden krytyczny błąd konfiguracji, wszystkie naprawione i sprawdzone ponownie, plus krótka lista rzeczy, których agent zrobić nie może i które zostają dla ciebie: wymiana klucza API, wyłączenie trybu demonstracyjnego i wyjście z piaskownicy Stripe'a.

Gęsta siatka identycznych pól, z której jedno wyłamuje się z rytmu — wysunięte z gniazda i rozjarzone na zielono; cienka linia łączy je z ustawioną obok błękitną płaszczyzną pomiarową.
Gęsta siatka identycznych pól, z której jedno wyłamuje się z rytmu — wysunięte z gniazda i rozjarzone na zielono; cienka linia łączy je z ustawioną obok błękitną płaszczyzną pomiarową.

Najciekawszą awarię zostawiam na koniec, bo uczy najwięcej. Po podpięciu własnej domeny logowanie przestało działać, ale tylko tam. Pod adresem roboczym, tym wygenerowanym automatycznie przez Vercel, wszystko chodziło jak wcześniej. Pierwsze podejrzenie było oczywiste i błędne: parę godzin wcześniej audyt bezpieczeństwa dołożył do bazy dwie tabele, więc rozsądek podpowiadał, że coś się przy nich posypało. Przejrzenie tabel niczego nie dało i dobrze, bo szukanie szło nie w tę stronę.

Prawdziwa przyczyna leżała gdzie indziej. Zapytanie logowania w ogóle nie docierało do funkcji logowania. Zatrzymywało się wcześniej, w warstwie pośredniej pilnującej bezpieczeństwa, na kontroli CSRF. CSRF to zabezpieczenie przed sytuacją, w której formularz twojej aplikacji zostaje wysłany z cudzej strony podszywającej się pod użytkownika; mechanizm sprawdza więc, czy żądanie przyszło z adresu, którego aplikacja się spodziewa. Spodziewała się starego adresu, bo zmienna środowiskowa z adresem serwisu wciąż wskazywała roboczą domenę. Z punktu widzenia aplikacji logowanie z nowej domeny wyglądało jak atak, więc je odrzuciła. Zachowała się dokładnie tak, jak ją ustawiono.

Naprawa jest banalna, kiedy już wiadomo: podmieniasz zmienną z adresem, publikujesz aplikację jeszcze raz i przechodzisz całą ścieżkę od zera na właściwej domenie, czyli nowe konto, potwierdzenie adresu e-mail, wgranie logo i kolorów, wklejenie transkrypcji, analiza, wygenerowana prezentacja, płatność. W przykładzie ta pierwsza płatność przeszła w trybie testowym, na karcie z dokumentacji Stripe, i tak też trzeba ją czytać: ścieżka jest sprawdzona, prawdziwych klientów jeszcze nie ma.

Wniosek jest szerszy niż jeden błąd. Każda zmienna środowiskowa, w której zapisany jest adres, to mina uzbrajająca się przy każdej zmianie środowiska. Adres serwisu, adresy zwrotne po zalogowaniu, adresy powiadomień od Stripe, ustawienia potwierdzeń e-mail. Zrób z nich listę raz i przejeżdżaj po niej za każdym razem, gdy aplikacja zmienia adres. Objaw będzie przy tym nietypowy: nie „nie działa”, tylko „działa wszędzie poza tym jednym miejscem”.

Co zostaje, kiedy kod przestaje być przewagą

Wszystko powyżej daje się dziś zrobić w jeden dzień pracy, bez pisania kodu. Powiem jasno, co to naprawdę znaczy, bo obietnice krążące wokół tego tematu są rozdmuchane. Jeden dzień daje wersję pierwszą, którą da się przetestować i pokazać. Nie daje produktu skończonego, bo w tej kategorii nic nie jest skończone: klienci znajdują błędy, zgłaszają braki, a utrzymanie jest kosztem stałym, nie jednorazowym etapem.

Zostaje pytanie, które moim zdaniem powinno prowadzić całą tę pracę: skoro agent potrafi odtworzyć twoją aplikację w jeden dzień, to co właściwie jest twoje? Nie kod, bo kod jest teraz łatwo powtarzalny. Nie integracje, bo Stripe i baza danych wyglądają u wszystkich tak samo. Twoja jest wiedza zaszyta w promptach i w logice: to, co model ma wyciągnąć z transkrypcji, jak ma przeformułować problem klienta, których liczb nie wolno mu podać bez pokrycia. To są twoje lata na rozmowach i pomyłki, na których się uczyłeś, zapisane w formie, którą można uruchomić. I twój jest dowód: wyniki, które twoi użytkownicy naprawdę osiągnęli na twoim narzędziu. Tego nikt nie skopiuje, bo to nie jest plik.

Druga rzecz jest jeszcze prostsza i dotyczy podziału ról. Agent wykonuje, ty prowadzisz projekt i osądzasz wynik. To ty decydujesz, co powstaje, ty wymuszasz weryfikację, ty patrzysz na wygenerowaną prezentację i mówisz, czy poszłaby do klienta. Jeżeli produkt nie działa, odpowiedzialność jest po twojej stronie, nigdy „po stronie AI”. Zdanie „AI to źle zrobiło” opisuje wyłącznie brief, którego nie napisałeś. Ta zamiana perspektywy jest niewygodna i jednocześnie jest jedynym ustawieniem, które daje ci kontrolę nad wynikiem.

Jeśli chcesz coś z tego zrobić dzisiaj, weź jeden ból, który znasz z własnej pracy lepiej niż ktokolwiek z twojego otoczenia, i napisz do niego jedno zdanie obietnicy. A potem, zanim napiszesz choćby prompt, wypisz listę wszystkiego, co w tym produkcie musiałoby zostać sprawdzone, zanim wpuścisz do niego pierwszą osobę. Druga lista jest ważniejsza od pierwszej i prawie nikt jej nie robi.

Sześć etapów: od bólu do dowoduKolejność, w jakiej powstaje produkt: od potwierdzonego bólu, przez plan i hydraulikę, po weryfikację, zanim wpuścisz pierwszego użytkownika.Sześć etapów: od bólu do dowoduBólZbierz dowód, że ktoś tego chce, zanim wydasz na to tydzień.ObietnicaJedno zdanie dla jednej osoby: co narzędzie robi i na jaki ból odpowiada.ProduktNajpierw jedna sesja wyłącznie na plan, dopiero potem agent pisze kod.HydraulikaKonta, baza i płatności; klucze w pliku .env, nigdy w kodzie.OpakowanieNazwa, wytyczne marki, strona z listą oczekujących, własna domena.DowódWymuś weryfikację, a gotową aplikację oddaj drugiemu modelowi do sprawdzenia.
Sześć etapów: od bólu do dowoduKolejność, w jakiej powstaje produkt: od potwierdzonego bólu, przez plan i hydraulikę, po weryfikację, zanim wpuścisz pierwszego użytkownika.Sześć etapów: od bólu do dowoduBólZbierz dowód, że ktoś tego chce, zanim wydaszna to tydzień.ObietnicaJedno zdanie dla jednej osoby: co narzędzierobi i na jaki ból odpowiada.ProduktNajpierw jedna sesja wyłącznie na plan,dopiero potem agent pisze kod.HydraulikaKonta, baza i płatności; klucze w pliku .env,nigdy w kodzie.OpakowanieNazwa, wytyczne marki, strona z listąoczekujących, własna domena.DowódWymuś weryfikację, a gotową aplikację oddajdrugiemu modelowi do sprawdzenia.
Kolejność, w jakiej powstaje produkt: od potwierdzonego bólu, przez plan i hydraulikę, po weryfikację, zanim wpuścisz pierwszego użytkownika.

Sprawdź się

Pięć pytań o decyzje, które w tym tekście przesądziły o wyniku.

  1. Po co stawiać stronę z listą oczekujących, zanim powstanie produkt?

  2. Odruch jest taki, żeby otworzyć agenta kodującego i powiedzieć „zbuduj aplikację”. Co dostajesz razem z działającym efektem?

  3. Aplikacja nie używała logo, które drugie narzędzie umieściło na stronie zapisów, i żadne z nich nie zgłosiło błędu. Dlaczego?

  4. Aplikacja potrafiła wygenerować klientowi slajd z wartością „0x” z pustych danych. Gdzie leżał błąd?

  5. Po podpięciu własnej domeny logowanie działało pod adresem roboczym, ale nie pod nową domeną. Co się okazało?