Problem: strona portfolio, która nic nie robi
Buduję systemy dla klientów — ratowanie produkcji, MVP, automatyzacje AI. Ale moja własna strona była statyczną wizytówką z formularzem kontaktowym. 80% zapytań: “ile kosztuje aplikacja” bez kontekstu, budżety 2000 zł na SaaS, niejasne briefy.
Klasyczny schemat: klient pisze, ja pytam o budżet i termin, on odpowiada za 3 dni, ja zadaję kolejne pytania. Po tygodniu mam informacje, które mógłbym mieć w 10 minut.
Postanowiłem zbudować stronę, która nie tylko prezentuje portfolio — ale aktywnie kwalifikuje leady. Klient rozmawia z AI, które zbiera pełen kontekst projektu. Ja dostaję gotowy brief zanim napiszę pierwszego maila.
58 commitów. 8 dni. 5 integracji. Oto jak to wyglądało naprawdę.
Dzień 1-2: Od pustego repo do działającego lejka (28 commitów)
Fundament
Pierwszy commit (1a99878) — Astro 6 z TypeScriptem, Tailwind CSS, Vercel. Dlaczego Astro? Bo strona portfolio to w 90% statyczny content — nie potrzebuje React runtime na każdej podstronie. Ale endpointy API (czat, płatności, webhooky) wymagają server-side renderingu. Astro obsługuje oba scenariusze natywnie.
Dwupoziomowy system konsultacji
Kluczowy commit (4657ef3). Dwa poziomy:
Darmowa rozmowa — Claude Haiku klasyfikuje zapytanie (projekt vs spam), potem Sonnet prowadzi kwalifikację w 8 wymianach. Zbiera: problem, technologie, budżet, termin, skalę. Koszt per sesja: grosze.
Premium konsultacja — 200 zł przez Stripe. 25 wymian z pogłębioną analizą techniczną. Sonnet z pełną mocą: architektura, rekomendacje, ryzyka. 200 zł odliczane od wyceny projektu.
Ciągłość kontekstu między tierami — UUID darmowej sesji zapisuje się w metadanych Stripe Checkout, webhook powiązuje sesje w Supabase, Sonnet ładuje podsumowanie z darmowej rozmowy do system promptu. Klient nie powtarza się.
5 commitów na Stripe (rzeczywistość vs plan)
Żaden system nie działa za pierwszym razem na produkcji.
6ffbcf4 Fix checkout: use card only, add error details
69e7448 Fix Stripe on Vercel: use fetch HTTP client
5ad5dfa Fix checkout URL: add process.env fallback for SITE_URL
661320f Switch chat to query param route for Vercel compatibility
6e4c41b Fix: trim STRIPE_PRICE_ID to remove trailing newline
Trailing newline w zmiennej środowiskowej — 30 sekund do naprawienia gdy go znajdziesz, godzina do zdiagnozowania. Serverless to inne środowisko niż localhost. Takie rzeczy nie pojawiają się w tutorialach.
Koniec dnia 2
Działający czat z AI, płatności Stripe, emaile transakcyjne (Resend), baza danych (Supabase), formularz kontaktowy, podsumowania JSON. MVP kompletne. Brzydkie, ale działające.
Dzień 2-3: Prompt engineering (15 commitów)
O tym etapie napisałem osobny artykuł — bo to okazał się najtrudniejszy kawałek projektu. Skrót:
Problem tożsamości. Bot mówił “ja realizuję projekty” — klient myślał, że rozmawia ze mną. Fix: reguła trzeciej osoby.
15 reguł, które się gryzły. Każdy bug w rozmowie = nowa reguła. 15 reguł = model gubi kontekst. Rozwiązanie: skurczyłem do 10.
Eksperyment z Gemini. Haiku miał kiepski polski. Przeszedłem na Gemini 3 Flash — lepszy język, ale hallucynował doświadczenia (“Artur stosuje eBPF”). 4 commity do kosza. Pełny revert.
Przełom. Disclaimer “Ustalenia techniczne będą weryfikowane przez Artura” zadziałał lepiej niż lista 15 zakazów. Kontekst > regulamin.
Dzień 3-4: Architektura i porządki
Silent Router
Commit a6d897f — nowa architektura AI. Haiku nie prowadzi rozmowy — tylko klasyfikuje pierwszą wiadomość (PROJECT/SPAM). Sonnet przejmuje rozmowę. Efekt: lepsza jakość konwersacji, Haiku tylko jako tani filtr.
Visitor ID i historia czatu
Commity 2f08b79 i 2868c43. Visitor ID w localStorage, historia czatu widoczna na stronie konsultacji. Klient wraca — widzi swoje poprzednie rozmowy. Zero logowania, zero rejestracji. Każda bariera wejścia to potencjalny lead, który odchodzi.
Polityka prywatności
Commit 911244f. RODO wymaga informacji o przetwarzaniu danych i AI. Nie feature — konieczność. Dwie wersje (PL + EN).
Dzień 5-8: Identyfikacja wizualna i optymalizacja lejka
Tu zaczął się drugi etap. Strona działa — teraz musi sprzedawać.
Redesign wizualny
Commit a56786f. Odszedłem od generycznego dark theme z cyan akcentami. Nowa paleta: ciemne tło, ciepły brąz, kremowy tekst. Typografia: DM Serif Display dla nagłówków (architektura, solidność), Inter dla treści.
Dlaczego brąz? Bo cyan to “generic tech startup”. Brąz to “architekt, który buduje solidne systemy”. Kolorystyka komunikuje pozycjonowanie. Jeśli nie wybierasz świadomie — wysyłasz losowy sygnał.
Przepisanie copy
Commit 712188b. Każde zdanie na stronie przeszło przez filtr: “czy klient wie, co z tego ma?”
Przed: “Nowoczesne rozwiązania IT dla Twojego biznesu.”
Po: “Stabilizuję systemy, buduję MVP, automatyzuję procesy.”
Zero przymiotników. Czasowniki. Konkrety. Nikt nie kupuje “nowoczesnych rozwiązań” — kupuje kogoś, kto rozwiąże konkretny problem.
Redesign homepage
Commit 6cf0555. Asymetryczny hero, solidne CTA, animacje blueprint. Każda sekcja homepage ma jedno zadanie: prowadzić do /konsultacja. Jeśli sekcja tego nie robi — nie ma jej na stronie.
Optymalizacja lejka
Commit b786ed2. Usunąłem to, co nie konwertowało:
Premium tier — nikt nie płaci 200 zł nieznajomemu z internetu bez rozmowy. Darmowa diagnostyka zostaje jako punkt wejścia. Premium może wrócić, ale po zbudowaniu zaufania.
Korepetycje — rozpraszały pozycjonowanie. Strona ma komunikować jedno: “architekt systemów, który rozwiązuje problemy.” Nie “gość, który uczy i buduje i naprawia i streamuje.”
Mniej = więcej. Każdy element strony albo prowadzi do leada, albo aktywnie mu przeszkadza.
Dark theme na wszystkim
Commit 652384d. Blog, portfolio, kontakt — wszystko w dark theme z blueprint animations. Spójna identyfikacja wizualna. Niby kosmetyka, ale klient, który przechodzi z homepage na blog i widzi inny design — traci zaufanie.
Dwie drogi kontaktu — nie jedna
Pierwsza wersja miała jeden lejek: homepage → AI diagnostyka → lead. Prosty, czysty, elegancki. I błędny.
Problem: nie każdy chce rozmawiać z botem. CTO, który wie czego chce, woli napisać maila z trzema zdaniami. CEO w pośpiechu nie ma czasu na 8 wymian z AI. Ktoś na mobile nie chce pisać elaboratu w okienku czatu.
Rozwiązanie: dwie ścieżki.
Primary path — AI diagnostyka. Bot zbiera kontekst, generuje brief, ja dostaję gotowy materiał do wyceny. Rekomendowana ścieżka, promowana na każdej stronie.
Droga poboczna — formularz kontaktowy. Klasyczne pola: imię, email, usługa, opis problemu. Dla tych, którzy wolą bezpośrednio. Strona kontaktu nie jest ślepym zaułkiem — na górze jest banner “Rekomendowane: Rozpocznij diagnostykę” kierujący na AI. Ale nie wymusza.
CTABanner na homepage ma pod głównym przyciskiem subtelny link: “Wolisz napisać bezpośrednio?” — to jedyny element strony, który prowadzi na /kontakt zamiast /konsultacja. Wystarczający dla tych, którzy szukają alternatywy. Niewidoczny dla tych, którzy idą głównym lejkiem.
Lekcja: jeden lejek to nie zawsze najlepszy lejek. Czasem najlepsza konwersja wynika z dania ludziom wyboru — pod warunkiem, że jasno rekomendujesz preferowaną ścieżkę.
Kompromis: techniczny autorytet vs nietechniczny odbiorca
Najtrudniejsza decyzja designerska. Strona musi jednocześnie:
-
Budować autorytet wśród ludzi technicznych — CTO, lead dev, DevOps. Ci chcą widzieć stack, architekturę, case studies z metrykami. “Shaka Player zamiast Bitmovin” mówi im więcej niż “zoptymalizowałem koszty video.”
-
Być dostępna dla osób nietechnicznych — CEO, founder, manager. Ci mają problem biznesowy (“system się sypie”, “chcę zautomatyzować”), ale nie wiedzą co to webhook ani RBAC.
Zbyt techniczny język na homepage odstraszy CEO. Zbyt prosty — nie zbuduje zaufania CTO.
Rozwiązanie: prosty wjazd → głębia na żądanie.
Strony wejściowe (homepage, konsultacja) mówią językiem biznesowym. Hero: “Twoje IT zjada budżet?” — nie “Optymalizuję pipeline CI/CD.” Karty sytuacyjne: “Chcę zautomatyzować procesy” — klik, AI poprowadzi rozmowę bez wymagania wiedzy technicznej.
Strony głębi (blog, portfolio, case study) dają pełną techniczną treść. Tu pojawia się “Stripe webhook desync”, “PostgreSQL race condition”, “Claude Haiku triage + Sonnet conversation.” Kto tu dotarł, jest albo techniczny, albo na tyle zaangażowany, że terminologia go nie odstraszy.
CTA zawsze proste — niezależnie czy jesteś na technicznym deep dive czy na homepage. “Masz podobny problem? Opisz go AI.” Zero barier, zero żargonu w przyciskach.
SocialProof na homepage celowo łączy oba światy. Metryka biznesowa: “Bug płatności naprawiony w 3 dni.” Kontekst techniczny pod spodem drobnym drukiem: “Stripe webhook desync, PostgreSQL race condition.” CEO widzi rezultat. CTO widzi, że wiem o czym mówię.
Co z tego wyszło
System, który pracuje 24/7:
- Klient wchodzi na stronę
- Klika “Rozpocznij diagnostykę”
- AI prowadzi rozmowę — zbiera problem, technologie, budżet, termin
- Generuje JSON z pełnym kontekstem
- Ja dostaję email z briefem — klient dostaje podsumowanie
- Pierwsza ludzka interakcja zaczyna się od pełnego zrozumienia problemu, nie od “w czym mogę pomóc?”
Konkretne liczby
| Element | Wartość |
|---|---|
| Stron | 16+ (PL + EN) |
| Endpointów API | 5 |
| Integracji | Anthropic, Stripe, Supabase, Resend, Vercel |
| Modele AI | 2 (Haiku router + Sonnet rozmowa) |
| Języki | PL + EN |
| Commitów | 58 |
| Czas budowy | 8 dni |
| Koszt utrzymania | ~0 zł/msc (free tiers) + grosze per rozmowa AI |
4 lekcje, które wyniosłem
1. Zbuduj dla siebie to, co budujesz dla klientów
Freelancerzy budują systemy lead gen dla klientów — a sami mają formularz kontaktowy ze strony z 2015 roku. Twoja strona to twój najważniejszy produkt. Jeśli nie umiesz sprzedać siebie, jak przekonasz klienta, że sprzedasz jego produkt?
2. Ship brzydką wersję, iteruj szybko
5 commitów na debugging Stripe. Trailing newline w env variable. Process.env fallback na Vercel. Te problemy nie pojawiły się w planie — pojawiły się na produkcji. Na produkcji się dowiadujesz, co naprawdę nie działa. W planie — co wygląda ładnie na kartce.
3. AI to narzędzie biznesowe, nie feature
Bot nie istnieje, żeby strona miała “AI”. Istnieje, bo kwalifikacja leadów zjadała mi godziny tygodniowo. Teraz zjada grosze per rozmowa. Jeśli twoje wdrożenie AI nie rozwiązuje konkretnego problemu biznesowego — to demo, nie produkt.
4. Usuwanie kodu > dodawanie kodu
Premium tier i korepetycje brzmiały dobrze w teorii. W praktyce rozmywały komunikat. Najważniejsze commity w projekcie to b786ed2 — który usuwa setki linii kodu. Każdy element, który nie prowadzi do konwersji, aktywnie jej przeszkadza.
Linia czasu (pełny git log)
Dzień 1-2 (14-15 marca):
1a99878 Initial commit — arturmrowicki.pl
4657ef3 feat: two-tier consultation system
+ 5 fixów Stripe na Vercel
+ emaile, sesje, formularz, podsumowania
Dzień 2-3 (15 marca):
c8c8bee fix: bot identity — never impersonate Artur
003a9c0 fix: harden bot prompts
fe01dd1 feat: switch to Gemini ← eksperyment
00e293e revert: back to Haiku ← revert
a6477b4 refactor: 15 rules → 10 ← przełom
e9af61a feat: urgent form + Telegram
Dzień 3-4 (16-17 marca):
c3eeac6 feat: dual-model chat (Haiku triage + Sonnet)
a6d897f refactor: silent router
2f08b79 feat: visitor ID + chat history
911244f feat: privacy policy
Dzień 5-8 (19-22 marca):
a56786f feat: premium visual redesign
712188b copy: brutal professional rewrite
6cf0555 feat: homepage redesign
b786ed2 refactor: remove premium tier + tutoring
652384d feat: dark theme everywhere
58 commitów. 4 z nich w koszu. System, który z tego wyszedł, jest lepszy niż gdybym trafił za pierwszym razem — bo wiem dlaczego każda decyzja jest taka, a nie inna.
Chcesz zobaczyć, jak to działa w praktyce? Porozmawiaj z botem — zbierze kontekst Twojego problemu w 5 minut. Ja dostanę pełny brief, Ty dostaniesz podsumowanie mailem.
Budujesz SaaS, automatyzujesz procesy, ratujesz system po kimś? Opisz sytuację — diagnoza gratis, odpowiedź w 48h.