Full Vibe Coding ile App Store'a Uygulama Çıkarmak: LevelUpStudy Deneyimi
"Vibe coding" son bir yılın en çok konuşulan terimi: kodu satır satır yazmak yerine ne istediğinizi anlatıyorsunuz, model yazıyor, siz sonucu değerlendiriyorsunuz. Peki bu yöntemle gerçekten App Store'da yayınlanan bir uygulama çıkarılabilir mi?
Çıkarılabilir. LevelUpStudy tam olarak böyle geliştirildi: SwiftUI arayüz, SceneKit ile üretilen 3B çalışma masası, PHP + MySQL API, Firebase kimlik doğrulama ve App Store'da yayında bir sürüm. Ama "yapay zekâya söyle, o yapsın" cümlesinin gizlediği bir sürü ayrıntı var. Bu yazıda işe yarayan yöntemi, yolda çarptığım üç somut duvarı ve aynı yolu deneyecek olanlara önerilerimi anlatıyorum.
Vibe coding ne değildir
Önce beklentiyi doğru yere koyalım. Vibe coding:
- Mimari kararları sizin yerinize vermez. "Veri nerede tutulacak, kime güvenilecek, gün ne zaman biter" sorularının cevabını modelden alırsanız, aldığınız cevap makul görünür ama tutarsız olur.
- Kendi kendini denetlemez. Model, ürettiği kodun içindeki tekrarı, ölü fonksiyonu ya da sessiz kırılmayı size söylemez. Sormazsanız görmezsiniz.
- Ürün kararı vermez. "Kullanıcı molada puan kazanmalı mı?" sorusu bir ürün sorusudur; teknik olarak her iki cevap da uygulanabilir.
Vibe coding'in gerçekten hızlandırdığı şey, kararı verildikten sonraki uygulama kısmı. Ekran kurmak, model tanımlamak, endpoint yazmak, testi genişletmek, refactor etmek. Bu iş yükü bir uygulamanın toplam emeğinin büyük kısmı, dolayısıyla kazanç da büyük.
LevelUpStudy neydi?
Kısaca: sınavına hazırlanan öğrencinin çalışma süresini ölçen, ölçtüğü süreyi puana çeviren, puanla 3B bir çalışma masası kurduran sosyal bir uygulama. Rakamlarla:
- 94 Swift dosyası; tamamı SwiftUI
- Kod içinde geometriden üretilen bir 3B masa sahnesi (hazır model dosyası yok)
- Kendi PHP API'm ve MySQL şeması; Firebase yalnızca kimlik, bildirim, analiz ve kilitlenme raporu için
- Saf mantık için 39, gerçek veritabanına karşı çalışan 24 test
- 12 sınav türü, 40 başarım rozeti
Bu ölçekte bir uygulamayı tek başıma, akşamları çalışarak çıkardım. Yöntem şuydu.
İşe yarayan yöntem: önce belge, sonra kod
En büyük farkı yaratan alışkanlık şu oldu: koda başlamadan önce kararları yazmak. Projede iki belge tutuyorum:
ARCHITECTURE.md— sistemin nasıl çalıştığı, güven sınırının nerede olduğu, hangi değerin nereden geldiği.NEW_VERSION.md— sıradaki sürümün fazları; her faz için hangi dosya, hangi sütun, hangi endpoint.
Bu belgeler yapay zekâ için de birer sözleşme. "Oturum tamamlama endpoint'ini yaz" demek yerine, "güven sınırı kuralına uyarak oturum tamamlamayı yaz; süre iki sunucu zaman damgasının farkı, istemcinin bildirdiği değer yalnızca üst sınır" diyebiliyorsunuz. Çıkan kodun doğruluk ihtimali kat kat artıyor.
Uygulamanın en kritik kuralı da bu belgeden doğdu:
Oyun ekonomisini belirleyen hiçbir değer istemciden gelmez.
Pratikte şu demek:
süre = min(sunucu farkı, planlanan süre, istemcinin bildirdiği süre)İstemci "3 saat çalıştım" diyemiyor; yalnızca daha erken bitirdiğini söyleyebiliyor. Bu tek satırlık kural, liderlik tablosunun anlamlı kalmasını sağlayan şey.
Duvar 1: Zaman dilimi, herkesin serisini yaktı
İlk mimaride gece çalışan bir iş, "dün çalışmayanların serisini sıfırla" görevini üstleniyordu. İş İstanbul saatiyle 00:00'da tetikleniyordu ama sunucu UTC'ydi. Sunucunun "dün" dediği gün, kullanıcının iki gün öncesiydi. Sonuç: her sabah, düzenli çalışan kullanıcıların serisi sıfırlanmış oluyordu.
Bu hatayı yapay zekâ üretmedi; ben "gün" kavramını hiçbir yerde tanımlamadığım için ortaya çıktı. Çözüm, tanımı tek bir yere yazmak oldu: gün her zaman Europe/Istanbul. İstemcide AppConfig.appTimeZone, sunucuda Domain\Time. Calendar.current, date('Y-m-d') ve new Date().setHours(0,0,0,0) kullanımı proje genelinde yasak — üçü de çalıştığı makinenin yerel saatine bağlı.
Ders: Modelden "doğru" kod istemek için önce "doğru"nun tanımını yazmanız gerekiyor.
Duvar 2: 800 satır ölü kod
3B objeleri üreten dosya 2.615 satıra çıkmıştı. İncelediğimde sekiz fonksiyonun iki kez tanımlı olduğunu gördüm: eski sürümler parametresizdi, yeni sürümler itemName alıyordu ve çağrı yeri yalnızca yenileri kullanıyordu. Yarım kalmış bir refactor'ün kalıntısıydı; yaklaşık 800 satır kod hiçbir yerden erişilemiyordu.
Bu, vibe coding'in en tipik yan etkisi. Model bir fonksiyonu "güncellemek" yerine yenisini yazar, eskisi orada kalır. Swift, çağrılmayan private fonksiyon için uyarı üretmediğinden derleme de sessiz kalır.
Ders: Düzenli olarak "bu dosyada erişilemeyen kod var mı?" diye sorun. Silmeden önce her fonksiyonun çağrı yerini grep ile bir kez daha doğrulayın; derlemenin geçmesi tek başına kanıt değil.
Duvar 3: Görünen ada göre eşleşme
Masadaki 3B modeller, eşyanın Türkçe görünen adına bakılarak seçiliyordu:
if itemName.contains("Kalem Kutusu") { ... }
else if itemName.contains("Kalem") { ... } // sıraya bağımlı!Çalışıyordu, ama üç sorunu vardı: veritabanına yeni eşya eklediğimde uygulamada gri kutu olarak çıkıyordu (yani her yeni eşya bir App Store güncellemesi demekti), adı değiştirdiğimde model sessizce bozuluyordu ve İngilizceye geçtiğim anda tüm eşleşmeler çökecekti.
Çözüm: eşleşmeyi görünen addan kararlı bir anahtara taşımak. shop_items tablosuna model_key sütunu, istemcide switch modelKey. Artık katalog denemeleri (fiyat, seviye kilidi, sezonluk eşya) sunucudan yapılabiliyor.
Ders: Yapay zekâ, istediğinizi en kısa yoldan çalıştırır. "Çalışıyor" ile "sürdürülebilir" arasındaki farkı sizin sormanız gerekir.
App Store'a çıkarken
Kod bittiğinde iş bitmiyor. Yayınlama tarafında zaman alan kalemler şunlardı:
- Ekran görüntüleri. 6.5" iPhone ve iPad boyutları zorunlu. Simülatörden alınan ham görüntüleri, üstüne kısa bir başlık ekleyerek düzenlemek dönüşümü belirgin şekilde etkiliyor.
- Gizlilik beyanı. App Store Connect'te hangi verinin toplandığını ve kimliğe bağlı olup olmadığını tek tek işaretliyorsunuz. Uygulamanın gerçek davranışıyla birebir uyuşmalı; buradaki tutarsızlık ret sebebi.
- Gizlilik politikası ve destek adresi. İkisi de erişilebilir bir URL olmak zorunda. Bu yüzden LevelUpStudy'nin gizlilik politikasını ve destek sayfasını kendi siteme koydum; bir doküman paylaşım bağlantısı yerine kalıcı bir adres vermek hem inceleme sürecinde hem de kullanıcı tarafında daha güvenilir duruyor.
- Yaş derecelendirmesi. Uygulama sosyal özellikler ve kullanıcı içeriği barındırdığı için 13+ oldu.
- Hesap silme. Hesap açan bir uygulama, hesabın uygulama içinden silinebilmesini de sunmak zorunda. Bunu sonradan eklemek yerine baştan planlayın.
İnceleme sürecinde en sık takılınan yer, bu maddelerin uygulamayla uyuşmaması. Kodun kendisi genellikle sorun değil.
Aynı yolu denemek isteyenler için kontrol listesi
- Mimari kararları siz verin, yazıya dökün, sonra modele o yazıyı verin.
- Görevleri küçük tutun: "oturum akışını yaz" değil, "oturum tamamlama endpoint'ini yaz, tek transaction, aynı oturum iki kez tamamlanamasın".
- Para, puan, süre, kimlik gibi değerlerin doğruluğunu teste bağlayın. Bu üç beş test, modelin sonraki değişiklikte aynı yeri bozmasını engelliyor.
- Her fazdan sonra "erişilemeyen kod, tekrar eden fonksiyon, sihirli string var mı?" diye sorun.
- Yayın gereksinimlerini (gizlilik, destek URL'si, hesap silme, ekran görüntüsü boyutları) geliştirmenin sonuna değil başına yazın.
Yapay zekâ ile geliştirme, iyi bir geliştiriciyi gereksiz kılmıyor; iyi bir geliştiricinin ne kadar iş çıkarabildiğini değiştiriyor. Kararları veren, sınırları koyan ve sonucu denetleyen hâlâ siz olmak zorundasınız.
Sık Sorulan Sorular
Vibe coding ile sıfırdan uygulama çıkarmak gerçekten mümkün mü?
Mümkün. LevelUpStudy bunun bir örneği: SwiftUI arayüz, 3B sahne, kendi API'si ve testleriyle App Store'da yayında. Ancak mimari kararları, güvenlik sınırlarını ve ürün kararlarını insanın vermesi gerekiyor; model bu kararların uygulanmasını hızlandırıyor.
Yapay zekâ ile yazılan kodun kalitesi nasıl kontrol edilir?
Üç şeye bakın: erişilemeyen ya da tekrar eden kod, sihirli metinlere dayanan eşleşmeler ve kritik hesaplamaların test kapsamı. Süre, puan ve kimlik gibi değerleri saf fonksiyonlara ayırıp testle korumak, sonraki değişikliklerde en çok işe yarayan alışkanlık.
App Store incelemesinde en çok neye takılıyor?
Kodun kendisinden çok beyanların uyuşmaması: App Store Connect'teki gizlilik beyanının uygulamanın gerçek davranışıyla örtüşmemesi, çalışmayan bir gizlilik politikası ya da destek bağlantısı, hesap açan bir uygulamada hesap silme adımının bulunmaması.
Bir uygulama için Firebase mi yoksa kendi sunucum mu?
İkisi birlikte de olabilir. LevelUpStudy'de kimlik doğrulama, bildirim, analiz ve kilitlenme raporu Firebase'de; veri, oyun ekonomisi ve zamanlanmış işler kendi PHP + MySQL API'mde. Böylece ücretsiz katmanda kalırken, sıralama gibi toplu sorguları tek bir SQL ile yapabiliyorum.
Uygulamayı yayınlamak ne kadar sürdü?
Fikirden App Store'daki ilk sürüme kadar birkaç ay, akşamları çalışarak. Süreyi asıl uzatan kısım kod yazmak değil; ekran görüntüleri, gizlilik beyanı, hesap silme akışı ve inceleme döngüsü gibi yayın hazırlıkları oldu.
İlgili Yazılar
Swift'e Giriş: Optionals, Guard Let ve If Let Kullanımı
Flutter'dan sonra iOS geliştirme için Swift öğrenmeye başladım. İlk karşılaştığım kavramlardan Optionals ve güvenli unwrapping yöntemlerini paylaşıyorum.
En İyi Swift Öğretmeni Nasıl Bulunur? 2026 Rehberi
iOS geliştirme için en iyi Swift öğretmenini nasıl seçersiniz? Deneyimli bir Swift uzmanından öğrenmenin avantajları ve doğru öğretmeni bulma kriterleri.
LevelUpStudy Nedir? YKS, KPSS ve LGS İçin Çalışma Takip Uygulaması
Günde kaç saat çalıştığınızı gerçekten biliyor musunuz? LevelUpStudy'nin odak oturumları, seri sistemi, liderlik tablosu ve 3B çalışma masasıyla sınav hazırlığını nasıl ölçülebilir hale getirdiğini anlatıyorum.