Seria: Vibe coding na własnych zasadach — post 1 z 2
Zapowiedź posta 2: „Z localhosta na produkcję: jak opublikować aplikację z vibe codingu na chmurowym serwerze WWW"
Alternatywne propozycje tytułu:
- Zbuduj własne Lovable: darmowe, lokalne środowisko do vibe codingu na Macu
- Vibe coding bez subskrypcji: VSCode + Cline + Ollama + Supabase
Czym w ogóle jest vibe coding?
Vibe coding to sposób tworzenia oprogramowania, w którym opisujesz zwykłym językiem, czego chcesz, a kod pisze za ciebie AI — podczas gdy ty sterujesz, robisz review i reagujesz na to, co pojawia się na ekranie. Pozostajesz za kierownicą jako osoba od produktu: „dodaj przełącznik trybu ciemnego", „przycisk usuwania powinien pytać o potwierdzenie", „posortuj listę po dacie". AI ogarnia składnię, strukturę plików, boilerplate. Ty ogarniasz vibe: co aplikacja ma robić i jak ma się z nią pracować.
Termin zrobił karierę na początku 2025 roku (ukuł go badacz AI Andrej Karpathy) i trafił w sedno, bo opisuje coś realnego: dla ogromnej klasy aplikacji — narzędzi wewnętrznych, prototypów, side projectów, małych produktów — nie musisz już pisać większości kodu samodzielnie. Musisz umieć kierować powstającym kodem i rozpoznawać, kiedy coś jest nie tak.
Czym jest Lovable?
Lovable to jedna z najpopularniejszych platform do vibe codingu. Wpisujesz w okno czatu, czego chcesz, a ona buduje na twoich oczach działającą aplikację webową — interfejs, bazę danych, logowanie, upload plików, cały komplet — z podglądem na żywo aktualizującym się w trakcie rozmowy. Pod maską Lovable generuje dość standardowy, nowoczesny webowy stack: React z TypeScriptem, stylowany Tailwind CSS i komponentami shadcn/ui, z backendem opartym na Supabase (baza Postgres z wbudowanym uwierzytelnianiem i przechowywaniem plików).
To świetny produkt. Ale to też subskrypcja z kredytami rozliczanymi za użycie, twój kod mieszka w ich chmurze, a zapytania do AI idą do modeli komercyjnych. Co u majsterkowiczów rodzi oczywiste pytanie:
Czy da się złożyć to samo doświadczenie samemu — za darmo, lokalnie i prywatnie?
Da się. I właśnie o tym jest ten post.
Cel tego posta
Na koniec będziesz mieć kompletne środowisko do vibe codingu działające na twoim Macu:
| Co daje ci Lovable | Twój darmowy lokalny odpowiednik |
|---|---|
| Okno czatu, które buduje aplikację | Cline (agent AI do kodowania wewnątrz VSCode) |
| Mózg AI | Ollama z open-source'owym modelem uruchomionym lokalnie |
| Podgląd na żywo | Serwer deweloperski Vite w przeglądarce, z hot reloadem przy każdej zmianie |
| Ukryty kod | VSCode — ten sam kod, tyle że możesz go zobaczyć i dotknąć |
| Baza danych, auth, storage | Supabase uruchomiony lokalnie w kontenerach — dokładnie ta sama technologia, której Lovable używa w chmurze |
| Publikacja jednym kliknięciem | Nadchodzi w poście 2 tej serii |
Koszt całkowity: 0 €. Twój kod nigdy nie opuszcza twojej maszyny. Twoje prompty nigdy nie opuszczają twojej maszyny. A ponieważ to ten sam stack, którego używa Lovable, wszystko, co zbudujesz, ma później czystą ścieżkę do prawdziwego hostingu w chmurze.
Jedno uczciwe zastrzeżenie na start: lokalny open-source'owy model na konsumenckim sprzęcie nie jest tak zdolny jak frontierowe modele, które wynajmuje Lovable. Twój lokalny agent od czasu do czasu zrobi coś głupiego, a ten post pokazuje ci zabezpieczenia, dzięki którym da się nad tym zapanować (to połowa wartości tego artykułu — każdą z opisanych niżej pułapek zaliczyłem naprawdę, podczas konfiguracji).
Czego potrzebujesz przed startem
- Mac (zalecany Apple Silicon; 16 GB RAM to komfort, 8 GB da radę z trikami z sekcji o RAM-ie poniżej)
- Zainstalowany VSCode z rozszerzeniem Cline
- Zainstalowana Ollama z pobranym modelem do kodowania —
qwen2.5-coder(7b lub 14b) to obecnie jedna z najmocniejszych opcji mieszczących się na konsumenckim sprzęcie
Konfiguracja VSCode + Cline + Ollama jest dobrze opisana w innych miejscach; ten post zaczyna się tam, gdzie większość poradników się kończy: lokalny serwer testowy i baza danych — czyli część, która zamienia „AI edytujące pliki" w „doświadczenie à la Lovable z prawdziwą, działającą aplikacją".
Faza 1: jednorazowa konfiguracja maszyny (~20 minut)
Cztery narzędzia wiersza poleceń, instalowane raz, używane przez każdy przyszły projekt. Otwórz terminal (w VSCode: Terminal → New Terminal).
1. Homebrew — menedżer pakietów Maca
Sprawdź, czy już go masz:
brew --versionJeśli komenda wypisuje wersję, idź dalej. Jeśli nie:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"Na Apple Silicon uruchom jeszcze dwie dodatkowe komendy, które instalator wypisuje na końcu (dodają brew do twojego PATH), a potem otwórz nowy terminal.
2. OrbStack — środowisko uruchomieniowe kontenerów
Twoja lokalna baza danych będzie działać w kontenerach. Standardowym narzędziem jest Docker Desktop, ale OrbStack to jego zamiennik typu drop-in, który zużywa zauważalnie mniej RAM-u i baterii — a RAM ma znaczenie, bo Ollama i tak już zjada go sporo.
brew install orbstack
open -a OrbStackZaakceptuj monity; potem OrbStack siedzi sobie cicho na pasku menu. Zweryfikuj:
docker --version3. Node.js — napędza serwer deweloperski
brew install node
node -vPułapka #1 — groźnie wyglądające komunikaty przy instalacji. Homebrew może wypisać „Caveats" w rodzaju "Single Executable Application is disabled" albo "Temporal support is disabled." Wyglądają jak błędy; to nieszkodliwe informacje o niszowych funkcjach Node'a, których nic w tym stacku nie używa. Jeśli widzisz kufel piwa 🍺, instalacja się powiodła.
4. Supabase CLI — cały twój backend w jednym narzędziu
brew install supabase
supabase --versionTo jest element, który pomija większość poradników. Supabase CLI uruchamia kompletny lokalny backend — bazę Postgres, uwierzytelnianie, przechowywanie plików i wizualny panel administracyjny — jedną komendą. To to samo open-source'owe oprogramowanie, które stoi za chmurowym backendem Lovable. Sam Postgresa nie instalujesz ani nie konfigurujesz nigdy.
Faza 2: tworzenie projektu (~20 minut, raz na projekt)
5. Scaffolding aplikacji
Wybierz jeden folder, w którym będą mieszkać wszystkie twoje projekty, i trzymaj się go religijnie:
mkdir -p ~/Projects && cd ~/Projects
npm create vite@latest my-first-app -- --template react-ts
cd my-first-app
npm installScaffolder pyta "Which linter to use?" — wybierz ESLint. To ugruntowany od lat standard, a (motyw, który będzie tu wracał) lokalne modele AI widziały w treningu nieporównanie więcej projektów z ESLintem niż z nowszymi alternatywami, więc robią z nim mniej błędów.
Otwórz projekt w VSCode komendą code . — a jeśli terminal odpowie command not found: code, to jednorazowe ustawienie VSCode: wciśnij Cmd+Shift+P, wpisz „shell command", wybierz "Shell Command: Install 'code' command in PATH", po czym otwórz nowy terminal.
Pułapka #2 — pułapka złego folderu. To kosztowało mnie więcej czasu niż cokolwiek innego w całej konfiguracji. Jeśli otworzysz VSCode, gdy twój terminal siedzi w jakimś innym katalogu, twoje edycje trafiają do niewłaściwego projektu — a późniejsze komendy w tajemniczy sposób zawodzą, bo pliki, których oczekują, nigdy nie zostały zmienione. Dwa nawyki eliminują to całkowicie: przed każdą komendą zerknij na prompt terminala albo uruchom pwd — ścieżka musi kończyć się nazwą twojego projektu; a w VSCode używaj File → Open Folder, żeby otworzyć dokładnie folder projektu, nic powyżej.Teraz zweryfikuj serce całej konfiguracji — twój lokalny serwer testowy:
npm run devOtwórz http://localhost:5173 — ładuje się strona startowa. Ten serwer Vite robi hot reload przeglądarki w ciągu sekundy od każdej zmiany pliku, i to właśnie tworzy to lovable'owe uczucie „patrz, jak buduje się na żywo". Zostaw go działającego w osobnej karcie terminala; nowe karty (ikona +) otwieraj na pozostałe komendy.
Pułapka #3 — port 5174? Jeśli w URL-u kiedykolwiek pojawi się 5174 zamiast 5173, masz drugi serwer deweloperski działający w zapomnianej karcie terminala. Nie jest to szkodliwe, ale bywa mylące. Zamknij duplikaty; niech działa dokładnie jeden.
6. Tailwind CSS + shadcn/ui — wizualny język Lovable
npm install tailwindcss @tailwindcss/vite(Jeśli npm ostrzega o fsevents i „install scripts not yet covered by allowScripts" — to nowsza funkcja bezpieczeństwa npm. fsevents to zaufany pomocnik macOS do obserwowania plików; zatwierdź go komendą npm approve-scripts fsevents albo po prostu jedź dalej, wszystko zadziała tak czy tak.)
Zastąp całą zawartość src/index.css jedną linią:
@import "tailwindcss";Pułapka #4 — wklejanie zastępuje, a nie dokleja. Kiedy poradnik mówi „zastąp zawartość pliku", zaznacz wszystko (Cmd+A), usuń, dopiero potem wklej. Mnie udało się wkleić nowyvite.config.tsponiżej starego, co dało plik ze zduplikowanymi importami i dwoma domyślnymi eksportami — natychmiastowa awaria. Jeśli coś sypie błędami zaraz po edycji, sprawdź, czy nie masz zawartości pliku dwa razy.
Teraz, zanim uruchomisz instalator shadcn, wykonaj konfigurację, której on po cichu wymaga. To krok, na którym moja konfiguracja po raz pierwszy porządnie się wyłożyła:
Pułapka #5 — shadcn potrzebuje „aliasu importu", którego Vite nie dostarcza. shadcn/ui generuje komponenty importujące z@/components/...— gdzie@to skrót do twojego folderusrc. Szablon Vite tego skrótu nie definiuje, więcnpx shadcn initoblewa swoje wstępne kontrole z komunikatem "Could not find valid path aliases." Rozwiązaniem są trzy drobne edycje, wykonywane raz na projekt:
Zainstaluj pomocnika typów:
npm install -D @types/nodeZastąp vite.config.ts tym:
import path from "path"
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [react(), tailwindcss()],
resolve: {
alias: { "@": path.resolve(__dirname, "./src") },
},
})Zastąp tsconfig.json tym:
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
],
"compilerOptions": {
"baseUrl": ".",
"paths": { "@/*": ["./src/*"] }
}
}A w tsconfig.app.json dodaj te dwie linie na początku istniejącego bloku "compilerOptions":
"baseUrl": ".",
"paths": { "@/*": ["./src/*"] },Teraz shadcn przejdzie swoje kontrole:
npx shadcn@latest init
npx shadcn@latest add button card inputInit zadaje dwa pytania, o których aktualne poradniki rzadko wspominają. "Select a component library?" — wybierz Radix UI, mimo że narzędzie rekomenduje Base UI. Radix to fundament, na którym shadcn został pierwotnie zbudowany, i to, czego używa Lovable — co znów oznacza, że to właśnie znają najlepiej twoje lokalne modele. "Which preset?" — Nova (ikony Lucide, klasyczny wygląd shadcn). Reszta na domyślnych.
7. Uruchom lokalny backend + bazę danych
supabase init
supabase startPierwszy supabase start pobiera około tuzina obrazów kontenerów — daj mu kilka minut.
Pułapka #6 — pobieranie losowo się nie udaje. Jeden z moich trzynastu obrazów (storage-api) nie chciał się pobrać, rzucając zagadkowym błędem rejestru, podczas gdy pozostałych dwanaście się udało. Z moją konfiguracją nie było nic nie tak — rejestry kontenerów miewają czkawkę. Rozwiązanie jest antyklimatyczne: uruchomsupabase startjeszcze raz. Wznawia pracę i dociąga tylko to, czego brakuje.
Kiedy skończy, uruchom supabase status, żeby zobaczyć, co teraz masz:
| Usługa | Adres |
|---|---|
| Twoja aplikacja (serwer testowy) | http://localhost:5173 |
| Studio — wizualna administracja bazą | http://127.0.0.1:54323 |
| API (REST/Auth/Storage) | http://127.0.0.1:54321 |
| Postgres, połączenie bezpośrednie | port 54322 |
Otwórz Studio w przeglądarce i rozejrzyj się: edytor tabel, konsola SQL, użytkownicy auth, buckety storage. To twoje okno na bazę danych w całym workflow vibe codingu — kiedy AI twierdzi, że coś zapisało, to w Studio sprawdzasz, czy naprawdę to zrobiło.
(Możesz też zobaczyć „Stopped services: imgproxy, pooler" — to opcjonalne komponenty; to normalne.)
8. Podłącz aplikację do bazy danych
npm install @supabase/supabase-jsPułapka #7 — klucze nie wyglądają tak, jak mówią tutoriale. Większość poradników każe ci skopiować „anon key" wyglądający jakeyJhbGci.... Nowsze wersje Supabase zastąpiły ten format:supabase statuswypisuje teraz klucz Publishable (sb_publishable_...) i klucz Secret (sb_secret_...). Klucz Publishable to klucz twojej aplikacji. Klucz Secret to klucz administracyjny — nigdy nie zbliża się do kodu frontendu.
Utwórz plik o nazwie .env.local w katalogu głównym projektu:
VITE_SUPABASE_URL=http://127.0.0.1:54321
VITE_SUPABASE_ANON_KEY=sb_publishable_...your-key-here...I klienta w src/lib/supabase.ts:
import { createClient } from '@supabase/supabase-js'
export const supabase = createClient(
import.meta.env.VITE_SUPABASE_URL,
import.meta.env.VITE_SUPABASE_ANON_KEY
)9. Plik .clinerules — najbardziej niedoceniany krok
Utwórz plik o nazwie .clinerules w katalogu głównym projektu. Cline czyta go automatycznie przed każdym zadaniem i to on stanowi różnicę między agentem, który trzyma się twojej architektury, a takim, który improwizuje:
# Project rules
## Stack
- React + TypeScript + Vite
- Tailwind CSS v4 + shadcn/ui (components live in src/components/ui)
- Supabase for database, auth, and storage (client in src/lib/supabase.ts)
## Rules
- Use existing shadcn/ui components before writing custom ones.
- Never hand-write authentication logic; always use supabase.auth methods.
- All database schema changes go into SQL migration files via
`supabase migration new <name>` — never apply schema changes directly.
- After schema changes, apply with `supabase db reset`.
- Read environment variables only via import.meta.env.VITE_*.
- Keep components small; one component per file.
- Do not add new dependencies without asking first.Frontierowe modele często same wnioskują takie konwencje; małe lokalne modele potrzebują ich spisanych. Za chwilę zobaczysz dokładnie dlaczego.
10. Kontrola wersji — twój przycisk „cofnij" na błędy AI
git init
git add -A
git status # check the list: .env.local must NOT appear (your keys stay out of git)
git commit -m "Project scaffold: Vite + React + Tailwind + shadcn + Supabase"Kiedy AI edytuje twój kod, git jest twoją siatką bezpieczeństwa: rób commit po każdym działającym feature'ze, a każdy bałagan wywołany przez AI jest o jedno git checkout -- . od cofnięcia.
Pułapka #8 — pliki tymczasowe Supabase puchnące w commitach. Po pierwszym commicie z feature'em możesz zauważyć tysiące dodanych linii zsupabase/.temp/...— wewnętrznych plików roboczych, które nie mają czego szukać w kontroli wersji. Wyklucz je raz:echo "supabase/.temp/" >> .gitignore, potemgit rm -r --cached supabase/.tempi commit.
Faza 3: pierwszy feature — i co agenci AI robią źle z bazami danych
Konfiguracja skończona. Czas na vibe. Z uruchomionymi supabase start i npm run dev otwórz panel Cline i wpisz prompt:
Create a todos feature: a migration for a `todos` table (id uuid pk default gen_random_uuid(), title text not null, done boolean default false, created_at timestamptz default now()), then a page using shadcn/ui components that lists, adds, and toggles todos via the supabase client.
(Prompty do AI zostawiam po angielsku — modele radzą sobie z nimi najlepiej właśnie w tym języku.)
Cline zaproponuje zmiany w plikach, ty je zatwierdzisz, a przeglądarka hot-reloadem załaduje UI listy todo. Magia — dopóki nie spróbujesz dodać todosa. Tu zaczyna się uczciwa część, którą większość tutoriali pomija. Mój pierwszy feature zawiódł dwukrotnie, na dwa pouczające sposoby:
Pułapka #9 — "Could not find the table 'public.todos'". UI istnieje, ale tabela w bazie nie. Bazy danych zmienia się przez pliki migracji — małe skrypty SQL wsupabase/migrations/, aplikowane komendąsupabase db reset. Mój lokalny model zbudował UI, ale pominął migrację (tak, mimo pliku z regułami — małym modelom to się czasem zdarza). Nawyk, który wyłapuje to za każdym razem: po każdym feature dotykającym danych sprawdź, czy wsupabase/migrations/pojawił się nowy plik.sql. Jeśli nie, powiedz Cline'owi: „Put the schema changes in a migration file viasupabase migration new." Potem zaaplikuj przezsupabase db reset.
Pułapka #10 — "permission denied for table todos". Postęp — tabela już istnieje — ale Postgres odmawia twojej aplikacji dostępu do niej. Aplikacje Supabase rozmawiają z bazą jako ograniczona rola „anon", a nowe tabele potrzebują jawnie nadanych praw dostępu plus polityki Row Level Security. Solidnym rozwiązaniem jest migracja, która załatwia utworzenie tabeli i uprawnienia razem. Utwórz ją przez supabase migration new create_todos i nadaj jej taki kształt:create table if not exists public.todos (
id uuid primary key default gen_random_uuid(),
title text not null,
done boolean not null default false,
created_at timestamptz not null default now()
);
grant usage on schema public to anon, authenticated;
grant select, insert, update, delete on table public.todos to anon, authenticated;
alter table public.todos enable row level security;
drop policy if exists "dev allow all" on public.todos;
create policy "dev allow all" on public.todos
for all using (true) with check (true);Potem supabase db reset, odśwież przeglądarkę — i działa. Dodaj todosa, przeładuj stronę — jest, trzyma się. Otwórz Studio, a tam twój wiersz w Postgresie. To pełny łańcuch, zweryfikowany: twój prompt → lokalne AI → kod + migracja → prawdziwa baza danych → działające UI.
(Ta polityka „allow all" jest celowo szeroko otwarta — poprawna dla lokalnego developmentu, gdzie jedynym użytkownikiem jesteś ty, i dokładnie ta, którą zastąpisz prawdziwymi regułami bezpieczeństwa, zanim cokolwiek pójdzie na produkcję. To temat na post 2.)
Pułapka #11 — zduplikowane migracje. Po naprawie mój agent poniewczasie utworzył własną migrację tworzącą tabelę, która wywaliłaby następnysupabase db reset(tworzenie tabeli, która już istnieje, to błąd). Jeśli dwie migracje tworzą tę samą tabelę, usuń zbędną i uruchom ponowniesupabase db reset, żeby udowodnić, że zestaw jest zdrowy.
Zrób commit z kamieniem milowym: git add -A && git commit -m "Add todos feature".
Jak naprawdę wygląda codzienny vibe coding
Jedno źródło zamieszania warte wyjaśnienia: VSCode ma wbudowany własny panel czatu AI, a Cline dodaje drugi. Nie mają ze sobą nic wspólnego. Używaj wyłącznie panelu Cline — to ten podłączony do Ollamy i ten, który potrafi edytować pliki i uruchamiać komendy. Schowaj wbudowany czat i nigdy więcej o nim nie myśl.
Mapowanie na Lovable, jeden ekran, dwie połówki: VSCode z panelem Cline po lewej, przeglądarka z twoją aplikacją po prawej. Czat Lovable = Cline. Podgląd Lovable = localhost:5173. Ukryty kod Lovable = widoczny w twoim edytorze, co jest feature'em, a nie bugiem.
Codzienny rytm:
# session start
supabase start
npm run devPotem pętla: opisz jeden feature Cline'owi → przejrzyj diffy → zatwierdź → patrz, jak przeglądarka robi hot reload → jeśli w grę wchodziły dane, zerknij do supabase/migrations, czy jest nowy plik → przetestuj → git add -A && git commit -m "feature". Kiedy coś idzie nie tak, powiedz to Cline'owi albo cofnij się gitem. Na koniec sesji supabase stop — co prowadzi nas do sprzętu.
Uwaga o RAM-ie (posiadacze MacBooków Air, to dla was). Ollama z modelem 7b chce 5–8 GB; lokalny stack Supabase bierze 1,5–2,5 GB; Vite i przeglądarka kolejne 1–2 GB. Na 16 GB wszystko szczęśliwie współistnieje. Na 8 GB stosuj trik z przełączaniem: supabase stop, gdy model wykonuje ciężką generację, supabase start, gdy chcesz testować. I trzy nawyki, które szczególnie pomagają małym lokalnym modelom: trzymaj zadania małe (jeden feature na jedną konwersację z Cline, potem zaczynaj świeże zadanie — długie czaty degradują małe modele), używaj trybu Plan przed trybem Act przy wszystkim, co nietrywialne, i aktualizuj .clinerules w miarę rozrastania się projektu.
Co masz teraz — i co dalej
Za cenę jednego popołudnia i zero euro miesięcznie masz teraz ten sam stack, który sprzedaje Lovable: agenta AI budującego aplikację React + Tailwind + shadcn na prawdziwej bazie Postgres, z podglądem na żywo, w całości na własnej maszynie. Plus trzy rzeczy, których Lovable ci nie daje: pełną prywatność, widoczny kod, który naprawdę posiadasz i rozumiesz, oraz zabezpieczenia (git, migracje, plik z regułami), których używają zawodowi programiści.
Wszystko do tej pory mieszka na localhost — widoczne tylko dla ciebie. Post 2 tej serii omawia brakujący rozdział: publikowanie. Jak wypuścić aplikację z vibe codingu na prawdziwy chmurowy serwer WWW — GitHub na kod, Vercel na frontend, Supabase Cloud na bazę danych — gdzie całe przejście z lokalnego na produkcyjne sprowadza się do zmiany dwóch zmiennych środowiskowych i uruchomienia dwóch komend. I, co kluczowe, jak zastąpić tę szeroko otwartą deweloperską politykę bezpieczeństwa prawdziwymi regułami Row Level Security, zanim twoja aplikacja spotka publiczny internet.
Do tego czasu: supabase start, npm run dev i buduj coś fajnego.
To jest post 1 serii „Vibe coding na własnych zasadach". Post 2: „Z localhosta na produkcję: jak opublikować aplikację z vibe codingu na chmurowym serwerze WWW".