Lovable kodunu GitHub'a çıkarmak: ne geliyor, ne kalıyor
Kodu almak iki dakika. Veritabanı, kullanıcılar, yüklenen dosyalar ve bütün secret'lar barındırılan projede kalıyor. Kimsenin yazmadığı kısım burası.

Lovable'dan çıkmanın iki yolu var ve ikisi de dakikalar sürüyor. Projeyi Project settings, Git, GitHub üzerinden bağlarsın, ya da ücretli planda aynı yerdeki Download codebase ile indirirsin. Diskine inen şey sıradan React, TypeScript ve Tailwind. İnmeyen şey ise veritabanı, kayıtlı kullanıcılar, yüklenmiş dosyalar ve uygulamanın çalışırken okuduğu bütün secret'lar. Çünkü bunlar bağlı Supabase projesinde duruyor ve hiçbir zaman kodun parçası olmadılar.
ÖzetKodu çıkar, sonra backend'i yeniden ayağa kaldır. Süreyi ikinci yarıya göre planla, birinciye göre değil. Kimseye tarih vermeden önce aşağıdaki denetim script'ini çalıştır.
Hangi yoldan çıkmalısın?
İkisi de sana aynı dosyaları veriyor. Fark sonrasında ortaya çıkıyor ve önemsemenin tek sebebi bu.
| GitHub bağlantısı | Download codebase | |
|---|---|---|
| Yön | Çift yönlü. Lovable'daki değişiklik repoya gidiyor, aktif dala yaptığın push geri geliyor. | Tek yönlü. Anlık kopya, sonrasında hiçbir şey senkronlanmıyor. |
| Repo kimin | Lovable oluşturuyor, varsayılan olarak gizli, senin hesabının altında. | Repo yok. Kendin açıyorsun. |
| Dallar | Aynı anda tek dal, sen değiştirmezsen varsayılan dal. | Geçerli değil. |
| Geri dönüş | Bağlantıyı kesip yeniden kurmak yeni bir repo oluşturuyor. Eski bağ geri gelmiyor. | İstediğin zaman tekrar indirirsin. |
Hâlâ Lovable içinde geliştiriyorsan ve karar verirken gerçek bir geçmiş tutmak istiyorsan GitHub bağlantısını seç. Çıkmaya çoktan karar verdiysen indirmen yeterli. Gidiş dönüş planlamadan önce bilmen gereken bir sınır var: var olan bir GitHub reposunu Lovable'a geri almak desteklenmiyor. Yol tek yönlü işliyor.
Klasörün içinde gerçekte ne var?
Bir Vite projesi. Bileşenler, sayfalar, hook'lar, Tailwind ayarı, iki ortam değişkeni okuyan bir Supabase istemci modülü ve proje sunucu tarafı mantık kullandıysa migration'lar ile edge function kaynağını taşıyan bir supabase/ klasörü. Tescilli hiçbir şey yok, gizlenmiş hiçbir şey yok. Bu kısım gerçekten senin ve Node çalışan her yerde koşuyor.
Çıkarmanın beklenenden sönük hissettirmesinin sebebi de bu. Klasör derleniyor, geliştirme sunucusu açılıyor ve uygulama kimseyi doğrulayamayan bir giriş ekranı gösteriyor.
Klasörün içinde ne yok?
Yazının tamamı tek görselde burada. Sol sütun makinene taşındı. Sağ sütun hiç kıpırdamadı ve kodu ne kadar okursan oku ortaya çıkmayacak.
supabase/migrations/ altındaki migration dosyalarısupabase/functions/ altındaki edge function kaynağıSecret tarafı kendi cümlesini hak ediyor, çünkü insanları asıl şaşırtan bu. Güvenli alandan girilen değerler barındırılan projede saklanıyor ve geri okunmuyor, isteyen aracın kendisi tarafından bile. Yani onları üretecek bir dışa aktarma düğmesi yok. Değeri yazarken bir yere not almadıysan gitmiştir, yenisini oluşturursun.
Eksikleri patlamadan önce nasıl bulursun?
Bu listeyi kodu okuyarak elle çıkarmak bir öğleden sonra alıyor ve yine de birini kaçırıyorsun. Bunu bir saniyede yapan bir script yazdık. Dışa aktardığın klasöre koy ve çalıştır. Kodun neye referans verdiğini okuyor, gerçekte neyin tanımlı olduğuyla karşılaştırıyor ve hangi parçanın sadece az önce terk ettiğin sunucuda durduğunu söylüyor.
# audit-export.sh - dışa aktarılan klasörün içinde çalıştır
SRC="${1:-.}"
echo "== 1. Kodun okuduğu ortam değişkenleri =="
grep -rhoE 'import\.meta\.env\.[A-Z_][A-Z0-9_]*|process\.env\.[A-Z_][A-Z0-9_]*' \
"$SRC/src" "$SRC/supabase" 2>/dev/null \
| sed -E 's/.*env\.//' | sort -u > /tmp/_used.txt
sed 's/^/ /' /tmp/_used.txt
echo "== 2. Bunlardan hangileri tanımlı =="
cat "$SRC"/.env "$SRC"/.env.* 2>/dev/null \
| grep -oE '^[A-Z_][A-Z0-9_]*' | sort -u > /tmp/_have.txt
comm -23 /tmp/_used.txt /tmp/_have.txt | sed 's/^/ - /'
echo "== 3. İstemcide asla durmaması gereken secret'lar =="
grep -rniE 'service_role|SERVICE_ROLE_KEY|secret_key' "$SRC/src" 2>/dev/null | head -5
echo "== 4. Şema seninle birlikte geliyor mu? =="
ls "$SRC"/supabase/migrations/*.sql 2>/dev/null | wc -l
echo "== 5. Sunucu tarafı fonksiyonlar =="
ls "$SRC"/supabase/functions 2>/dev/null
Bu projelerin çıktığı şekle benzeyen örnek bir dışa aktarmada, yani bir Supabase istemcisi, bir ödeme sayfası ve bir edge function ile, script şunu basıyor. Aşağıdaki çıktı gerçek bir koşudan, temsili değil.
== 1. Env vars the code reads ==
VITE_STRIPE_PUBLISHABLE_KEY
VITE_SUPABASE_ANON_KEY
VITE_SUPABASE_URL
== 2. Which of them are defined anywhere ==
MISSING (app will start and fail at runtime):
- VITE_STRIPE_PUBLISHABLE_KEY
- VITE_SUPABASE_ANON_KEY
== 3. Secrets that must never be client-side ==
clean
== 4. Does the database schema travel with you? ==
NO migrations - the schema exists only in the hosted project
== 5. Server-side functions ==
function: send-invite
-> these are DEPLOYED artifacts; their secrets are not in this folder
O çıktının iki satırı taşımanın tamamı. 2. bölüm, uygulamanın neden derlenip ilk tıklamada öldüğünü söylüyor. 4. bölüm ise bir öğleden sonra ile bir hafta arasındaki farkı söylüyor, çünkü migration dosyası olmayan bir projenin şeması tam olarak tek bir yerde duruyor ve onu panelden tablo tablo okuyarak yeniden kuruyorsun.
Yerelde ilk çalıştırdığında ne bozuluyor?
Sırayla, ve dördü de aynı kök sebebin farklı mesajlar giymiş hali.
- Boş sayfa ve konsolda tanımsız URL hatası. Supabase istemcisi iki değişkeni için
undefinedaldı..envoluştur, proje URL'ini ve anon anahtarını içine yaz. - Giriş hiçbir şeyi kabul etmiyor. Authentication ayarlarında yerel adresin yönlendirme URL'leri arasında olmayan bir projeye bakıyorsun. Ekle.
- Sorgular hata yerine boş dizi dönüyor. Satır seviyesi güvenlik işini yapıyor ve hiçbir politika senin rolüne bir şey vermiyor. Boş dizi, doğru kilitlenmiş bir tablonun dışarıdan görünüşü.
- Dün çalışan özellik 500 dönüyor. Eski projede dağıtılmış bir edge function çağırıyor ve o fonksiyon yeni projene karşı çalışmıyor.
Bunların hiçbiri üretilen koddaki hata değil. Dışa aktarmanın bıraktığı boşluğun şekli.
Backend'i nasıl yeniden ayağa kaldırırsın?
Önce şuna karar ver: var olan barındırılan projeyi mi tutuyorsun, sıfırdan yenisini mi kuruyorsun. Tutmak daha hızlı ve veri önemliyse, proje de sağlıklıysa doğru karar. Yeniden kurmak ise güvenmediğin bir şeyi devraldıysan doğru olan.
Tutuyorsan iş küçük: ortam dosyasını oluştur, yeni alan adını yönlendirme listesine ekle ve devam et. Yeniden kuruyorsan şu sırayla çalış, çünkü her adım bir üstüne bağlı.
- Önce şema. Varsa migration dosyalarını uygula. Yoksa şemayı eski projeden dışa aktarıp repoya koy, böylece bunu elle yapan son kişi sen ol.
- Sonra politikalar. Her tabloda satır seviyesi güvenlik açık ve her politika bilerek yazılmış olsun. İnsanların atladığı adım bu ve sızdıran adım da bu.
- Sonra veri. Tablo tablo dışa aktar ve içe al, yabancı anahtar sırasına saygı göstererek.
- Sonra kullanıcılar. Auth kullanıcıları kendi başına bir taşıma işi, tablo kopyalamak değil.
- Sonra dosyalar. Bucket'lar, içerikleri ve tablo politikalarından ayrı olan erişim politikaları.
- En son fonksiyonlar, secret'ları kopyalanarak değil yeniden üretilerek, çünkü orijinalleri geri okunamıyor.
Dağıtımın kendisi kolay kısmı. Bu bir Vite build'i, yani statik çıktı ve ortam değişkenlerini servis eden her yer iş görüyor. Biz bunları genelde Vercel'e ya da müşterinin sahip olduğu bir Coolify sunucusuna alıyoruz, dışa aktarmanın sebebiyle aynı sebeple: kimse iki kere kilitlenmek istemiyor.
Hazır girmişken hangi açıkları kapatmalısın?
Zaten her dosyaya dokunuyorsun. Bu kod tabanlarının düzenli olarak yanlış yaptığı dört şeyi düzeltmek için eline geçecek en ucuz an bu ve dördü de uygulama düzgün görünürken görünmez.
Her tabloda satır seviyesi güvenliğin açık olduğunu ve her politikanın sandığın şeyi söylediğini doğrula. Tarayıcının erişebildiği hiçbir yerde service role anahtarı durmadığını doğrula, script'in 3. bölümü tam olarak bunu izliyor. Storage bucket'larının, dosyalar gerçekten herkese açık olmadıkça, açık olmadığını doğrula. Kimin neyi yapabileceğine dair her şeyin arayüzde gizlenmek yerine sunucuda uygulandığını doğrula. Görünmeyen bir buton bir yetki değildir.
Biten taşıma neye benziyor?
Bu iş bittiğinde altı şey doğru oluyor. Beş değil.
.env.example kodun okuduğu her değişkeni listeliyor.Bunu ne zaman kendin yapmamalısın?
Uygulamanın henüz kullanıcısı ve tutulmaya değer verisi yoksa kendin yap. Yukarıdaki liste bir hafta sonu sürer ve sonrasında kendi sistemini daha iyi anlarsın.
Şu üçünden biri doğruysa dur ve yardım al: uygulama para alıyorsa, kaybedemeyeceğin gerçek kullanıcı kayıtları varsa, ya da projede migration dosyası yoksa ve şema tablo tablo okumayı başlı başına bir işe çevirecek kadar büyükse. Buradaki başarısızlık şekli bozuk bir build değil, onu fark ederdin. Sessiz olanı: okunur kalmış bir tablo, açık kalmış bir bucket, doğru görünen ama olmayan bir politika. İncelemeyi taşımadan sonra değil önce istiyorsan, yapay zeka projesi tamamlama işimiz tam olarak bu ve önce kod incelemesi geliyor.
Kodun nereye ineceğine karar veriyorsan, nasıl çıkacağına değil, şu da işine yarar: WordPress mi Next.js mi karar matrisi aynı ödünü platform tarafından ele alıyor.
Sık sorulanlar
GitHub bağlamadan dışa aktarabilir miyim? Evet. Ücretli planda Project settings, Git altındaki Download codebase ile, ya da kod editörü kenar çubuğundan.
Kod bana mı ait? Evet. Standart React, TypeScript ve Tailwind, repo da senin hesabının altında duruyor.
Veritabanım da geliyor mu? Hayır. Veritabanı, kullanıcılar, dosyalar ve secret'lar barındırılan projede kalıyor. Şemayı yalnızca varsa migration dosyaları tarif ediyor.
Yerelde düzenledikten sonra kodu geri gönderebilir miyim? GitHub bağlantısıyla evet, aktif dal üzerinden. İlgisiz var olan bir repoyu içe almak desteklenmiyor.
GitHub bağlantısını kesip sonra yeniden kurarsam ne olur? Yeni bir repo alırsın. Önceki bağ geri gelmiyor, yani bağlantıyı kesmeyi tek yönlü bir işlem olarak düşün.
Taşımanın tamamı ne kadar sürüyor? Kodu çıkarmak dakikalar. Backend'i yeniden ayağa kaldırmak bir öğleden sonra ile bir hafta arasında ve hangisine denk geldiğini en iyi tahmin eden şey yukarıdaki script'in 4. bölümü.