← Insights
28 kwietnia 2026 Insights PL

Vibe coding — 6 miesięcy później: co się posypało i czego nie zrobiłbym ponownie

Prędkość jest realna. Dług techniczny też. Rok budowania trzech aplikacji z AI bez zewnętrznych developerów nauczył mnie pięciu błędów i sześciu reguł, których teraz pilnuję. Post-mortem z naswoim.org, industrverse i marcinpaszkiewicz.com.

Vibe coding — 6 miesięcy później: co się posypało i czego nie zrobiłbym ponownie

Kwiecień 2024. Właśnie wrzuciłem pierwszą działającą wersję naswoim.org na produkcję. Aplikacja działa. Użytkownicy mogą się logować. Dane są w Supabase. Na papierze — sukces.

Pod maską: dwa konkurujące ze sobą design systemy, siedemnaście zduplikowanych funkcji pomocniczych rozsianych po dwunastu plikach i polityka Supabase RLS, która po cichu zawodzi w jednym konkretnym przypadku brzegowym — który odkryję dopiero za trzy tygodnie.

Vibe coding działa. Ale zawodzi w sposób niewidoczny — aż przestaje być niewidoczny.

Ekran z kodem w neonowym podświetleniu
Foto: Jakub Żerdzicki / Unsplash

Szybki kontekst: co zbudowałem

W ciągu mniej więcej dwunastu miesięcy zbudowałem trzy aplikacje z użyciem vibe codingu — prawie bez zewnętrznych developerów:

  • naswoim.org — platforma dla inwestorów budowlanych: checklisty, budżety, dokumenty, marketplace ekspertów, mapy działek, asystent AI. Web + Android + iOS + portal admina.
  • industrverse.com — B2B SaaS do szkoleń VR w przemyśle: 7 ról użytkowników, 9 dashboardów na rolę, komunikacja real-time, gateway sesji VR, pełne API backendu.
  • marcinpaszkiewicz.com — ta strona. Astro SSR + WordPress headless. Prostsza, ale też pouczająca.

Claude Code był moim głównym narzędziem, z okazjonalną pomocą Cursora. Napisałem w ten sposób gdzieś między 40 000 a 60 000 linii kodu produkcyjnego. Wszystko wyszło. Wszystko działa.

Oto co zrobiłem źle.

Błąd #1: Pozwoliłem AI wybrać architekturę

Kiedy zaczynałem naswoim.org, opisałem projekt Claude’owi i zapytałem, jaki stack poleca. Dostałem solidną odpowiedź: React 19, Vite, Supabase, Tailwind CSS 4. Świetne wybory.

Potem zapytałem o komponenty UI. Zaproponował MUI 7. Zgodziłem się — był szybki, miał wszystko czego potrzebowałem.

Problem: już używałem Tailwind CSS 4. Teraz miałem dwa design systemy:

Diagram — konflikt design systemów / design system conflict

Tailwind CSS 4
▸ utility-first
▸ spacing: rem scale
▸ breakpoints: sm/md/lg/xl
▸ tokens: CSS vars

każdy
nowy ekran

MUI 7
▸ component-first
▸ spacing: 8px grid
▸ breakpoints: xs/sm/md/lg
▸ tokens: theme object

Dwa systemy spacingu. Dwie filozofie responsywności. Dwie warstwy CSS do utrzymania. — Two spacing systems. Two responsiveness philosophies. Two CSS layers to maintain.

Wniosek: AI nie zna Twojej wizji na osiemnaście miesięcy do przodu. Optymalizuje pod „działające teraz”. Decyzje architekturalne — szczególnie dotyczące design systemów, modeli danych i granic modułów — muszą wychodzić od Ciebie. AI implementuje. Ty decydujesz co implementować.

Co bym zrobił inaczej: napisał jednostronicowy dokument decyzji architekturalnych przed pierwszym promptem. Nie pełna specyfikacja — tylko: co jest jedynym źródłem prawdy o stylach? Jakie jest podejście do zarządzania stanem? Jak dzielimy moduły? Daj AI ograniczenia, nie blank permission.

Błąd #2: AI nigdy nie mówi „nie” — i to jest niebezpieczne

Po trzech miesiącach pracy nad industrverse backend miał 13 modułów NestJS, 7 ról użytkowników i 9 osobnych dashboardów. Każda rola miała własną logikę dostępu do danych, własny system powiadomień, własny workflow.

Nic z tego nie było w oryginalnej specyfikacji.

industrverse — plan MVP vs rzeczywistość

Moduły backendu
plan 5 → rzeczywistość 13

Role użytkowników
plan 3 → rzeczywistość 7

Dashboardy
plan 3 → rzeczywistość 9

Każdy z tych elementów miał sens w izolacji. Problem pojawia się, gdy zsumuje się wszystkie decyzje z 11:00 wieczorem.
Ściana pokryta kolorowymi karteczkami — efekt braku ograniczeń scope
Foto: Jakub Żerdzicki / Unsplash

Oto co się dzieje: masz pomysł o 23:00. Opisujesz go Claude’owi. Buduje go w dwadzieścia minut. Działa. Wrzucasz to. Trzy tygodnie później zauważasz, że dodanie tej funkcji zepsuło model mentalny dla następnej funkcji. Ale AI ci tego nie mówi — po prostu buduje to, o co go prosisz.

Każdy developer w zespole ma kolegę, który mówi „chwila — czy na pewno tego potrzebujemy?” AI nie mówi chwila. AI mówi tak.

Wniosek: Musisz być PM-em dla swojego AI. Nie tylko wizjonerem — osobą, która mówi nie. Pytanie nie brzmi „czy AI to zbuduje?” (zbuduje). Pytanie brzmi „czy to w ogóle powinno istnieć?”

Mam teraz regułę przed każdą nową funkcją: piszę jedno zdanie o tym, jaki problem rozwiązuje dla konkretnego użytkownika. Jeśli nie potrafię tego zdania napisać, nie piszę promptu.

Błąd #3: Debugowanie kodu, którego nie pisałeś, jest wolniejsze niż wygląda

Lupa nad labiryntem — szukanie bugu w kodzie
Foto: TSD Studio / Unsplash

W naswoim.org miałem błąd w politykach Supabase Row Level Security. Użytkownicy w jednej roli mogli okazjonalnie widzieć dokumenty, których nie powinni — ale tylko gdy wcześniej zaszła konkretna sekwencja operacji.

Szukanie tego zajęło mi trzy dni.

Nie dlatego, że błąd był skomplikowany. Dlatego, że kod był generowany przez AI i nie przeczytałem go wystarczająco uważnie w momencie powstawania. Polityka RLS wyglądała poprawnie. Była poprawna składniowo. Przechodziła moje podstawowe testy. Przypadek brzegowy był subtelny — kombinacja dwóch różnych warunków polityki, które oddziaływały na siebie w nieoczywisty sposób.

Kiedy piszesz kod sam, budujesz model mentalny w trakcie pisania. Kiedy pisze AI, recenzujesz — co jest szybsze, ale płytsze. Model w głowie jest mniej kompletny. A płytkie modele mentalne spowalniają debugowanie.

Wniosek: Nigdy nie merguj kodu AI, którego nie potrafisz wyjaśnić linijka po linijce. W szczególności dla wszystkiego, co dotyczy auth, dostępu do danych i logiki krytycznej dla biznesu: czytaj jak code reviewer, nie jak ktoś sprawdzający listę zakupów.

Błąd #4: Kontekst się kończy — i AI „zapomina” wszystko

W długiej sesji Claude Code widzi wszystko, co razem zbudowaliście. Zna Twoje konwencje nazewnicze, wzorce, preferencje. Jest spójny.

W następnej sesji zaczyna od zera.

Schemat — pamięć kontekstu między sesjami / context memory across sessions

Sesja 1
▸ React hooks
▸ TanStack Query
▸ Zustand atoms

↺ reset
Sesja 2
▸ useEffect pattern
▸ local useState
▸ API calls inline

↺ reset
Sesja 3
▸ custom hooks
▸ Context API
▸ Axios interceptors

Każda sesja generowała spójny kod — ale każda sesja nie wiedziała nic o poprzedniej. — Each session generated coherent code — but knew nothing about the previous one.

W naswoim.org zacząłem nową sesję po dwudniowej przerwie i poprosiłem Claude’a o zbudowanie nowego komponentu. Wygenerował coś, co działało — ale używało zupełnie innych wzorców niż reszta kodu. Inne podejście do zarządzania stanem. Inny styl obsługi błędów. Inne nazewnictwo.

Po czterech miesiącach codebase miał trzy wyraźne „ery” — każda odzwierciedlająca konwencje z rozmów prowadzonych w danym czasie.

Wniosek: Plik CLAUDE.md nie jest opcjonalny. Ustaw go pierwszego dnia. Powinien zawierać: konwencje nazewnicze, wzorce do stosowania, wzorce do unikania, których bibliotek używać do jakich problemów. To jest trwała pamięć między sesjami.

Błąd #5: Security jest niewidoczna — dopóki nie jest

AI generuje działający kod. Nie generuje niezawodnie bezpiecznego kodu.

Czerwona kłódka na klawiaturze — security niewidoczna dopóki jej nie ma
Foto: FlyD / Unsplash

W industrverse miałem endpoint API dostępny tylko dla użytkowników z rolą „trainer”. Endpoint działał poprawnie. Zwracał właściwe dane. Obsługiwał błędy elegancko.

Nie weryfikował też roszczenia roli JWT przy jednej konkretnej metodzie HTTP. Użytkownik z dowolnym uwierzytelnionym tokenem mógł go wywołać.

Znalazłem to podczas ręcznego przeglądu bezpieczeństwa — nie dlatego, że Claude to oznaczył, nie dlatego, że moje testy to wyłapały. Bo pewnego popołudnia usiadłem i przeczytałem każdy endpoint związany z auth.

Security review — checklista po każdym auth feature


Czy każdy endpoint weryfikuje JWT/session?
Is every endpoint verifying JWT/session?

Czy rola użytkownika jest sprawdzana server-side?
Is the user role checked server-side?

Czy RLS działa dla wszystkich kombinacji ról?
Does RLS work for all role combinations?

Czy input jest walidowany przed zapisem do bazy?
Is input validated before writing to DB?

Czy wrażliwe pola są filtrowane w response?
Are sensitive fields filtered in the response?

Czy edge case (brak roli, wygasły token) jest obsłużony?
Is the edge case (missing role, expired token) handled?

Wniosek: Po każdej funkcji dotykającej autentykacji, autoryzacji lub danych użytkownika — rób ręczny przegląd bezpieczeństwa. Nie vibe. Checklista.

Co bym zrobił inaczej: 6 reguł

Gdybym zaczynał dzisiaj, z całą tą wiedzą:

1
Napisz brief architekturalny przed pierwszym promptem
Jedna strona. Co jest jedynym źródłem prawdy o stylach? Jakie jest podejście do stanu? Jakie są granice modułów? Daj AI ograniczenia, nie blank permission.

2
Jeden design system. Zero wyjątków.
Albo biblioteka komponentów, albo utility CSS. Nie obydwa. Jeśli Tailwind — wszystko Tailwind. Jeśli MUI — wszystko MUI.

3
Jedno zdanie problemu przed każdą nową funkcją
„To rozwiązuje [konkretny problem] dla [konkretnego użytkownika].” Jeśli nie potrafisz tego napisać — nie jesteś gotowy na prompt.

4
Jeśli nie rozumiesz linijka po linijce — nie merguj
Szczególnie dla auth, RLS, uprawnień i modeli danych. Czytaj jak code reviewer, nie jak ktoś sprawdzający listę zakupów.

5
CLAUDE.md od pierwszego dnia
Konwencje nazewnicze, preferowane wzorce, biblioteki do jakich problemów, wzorce do unikania. Aktualizuj przy każdej ważnej decyzji. To trwała pamięć między sesjami.

6
Zaplanuj przegląd bezpieczeństwa po każdej funkcji auth
Nie opcjonalnie. AI generuje działający kod, nie bezpieczny. Auth, RLS i walidacja inputu — tu zawsze czytasz ręcznie.

Czego nie mówię

Nie mówię, że vibe coding jest wadliwy ani że narzędzia AI są zawodne. Wszystkie trzy projekty, które zbudowałem, działają. Mają prawdziwych użytkowników. Rozwiązują prawdziwe problemy. Zysk produktywności jest realny — zbudowałem w rok to, co trzyosobowy zespół zrobiłby w osiemnaście miesięcy.

Mówię, że tryby awarii są konkretne i nieoczywiste na starcie.

Największe ryzyko w vibe codingu nie jest to, że AI pisze zły kod. Jest to, że AI pisze kod, który wygląda dobrze — aż coś idzie nie tak. I wtedy patrzysz na codebase, który na wpół rozumiesz, z bugiem, którego nie napisałeś, i modelem mentalnym mającym luki dokładnie w złych miejscach.

Prędkość jest realna. Zbuduj nawyki, które sprawią, że będzie bezpieczna.

// Porozmawiajmy //

Wdrażasz AI, automatyzację lub VR w swojej organizacji? Chętnie porozmawiam o Twoim przypadku.

Umów rozmowę →