12 KiB
Progress Log
Faz tanımları için ROADMAP.md. Bu dosya ne yapıldığını, ne yapılmadığını ve bilinen sınırlamaları takip eder — faz atlarken buraya bakıp neyin gerçek neyin stub olduğunu hatırlamak için.
App Store Connect + RevenueCat kurulumu (2026-08-20)
App Store Connect (API ile, gerçek üretim hesabına karşı):
- Store metinleri yazıldı: alt başlık, açıklama, anahtar kelimeler, tanıtım metni, destek/pazarlama/gizlilik URL'leri, telif hakkı
- Kategori: Food & Drink
- En son build (v10) versiyona bağlandı
- Subscription group "Menulio Pro" + iki ürün oluşturuldu:
menu_pro_monthly,menu_pro_yearly(Türkçe isim/açıklama ile) - Fiyatlandırma kullanıcı tarafından App Store Connect UI'dan girildi: aylık 250 TL, yıllık 2500 TL
- Kullanıcının tamamlaması gereken: Yaş derecelendirmesi anketi, en az 1 ekran görüntüsü — API'nin güvenilir şekilde dolduramadığı/dolduramayacağı alanlar
RevenueCat (proje zaten proj0d3bc1c1 olarak mevcuttu, API ile tamamlandı):
- Gerçek App Store ürünleri (
menu_pro_monthly,menu_pro_yearly) "Menul.io (App Store)" app'ine eklendi - "Menulio Pro" entitlement'ına bağlandı
- "default" offering'in Monthly/Yearly paketlerine iliştirildi
Backend: POST /subscription/webhook gerçek mantıkla yazıldı — Authorization header'ı (shared secret) doğruluyor, RevenueCat event tipini subscriptions.status'a çeviriyor (INITIAL_PURCHASE/RENEWAL/PRODUCT_CHANGE/UNCANCELLATION → active, BILLING_ISSUE → grace_period, EXPIRATION → suspended; CANCELLATION tek başına suspend etmiyor, sadece auto-renew kapanıyor). Gerçek Supabase'e karşı uçtan uca test edildi.
Tamamlandı (devamı, 2026-08-20):
REVENUECAT_WEBHOOK_SECRETenv değişkeni API servisine eklendi, RevenueCat Dashboard'da webhook (URL + Authorization header) kullanıcı tarafından yapılandırıldı.- Mobile:
react-native-purchasesSDK'sı kuruldu (apps/mobile/src/lib/purchases.ts).Purchases.configure({ appUserID: restaurantId })restaurantId'nin bilindiği her noktada (login sonrası, cold-start rehydration, onboarding restoran oluşturma) çağrılıyor — webhook'unapp_user_id'yi doğru eşleştirmesi için bu şart. apps/mobile/src/app/account/subscription.tsx— paywall ekranı: mevcut entitlement durumu, offering paketleri (gerçek mağaza fiyatlarıyla), satın alma, restore. Hesap ekranından linklendi.
Kalan (henüz yapılmadı):
- Gerçek cihazda satın alma akışı hiç test edilmedi — native modül olduğu için Expo Go'da çalışmaz, EAS/dev-client build gerekiyor (TestFlight build'leri zaten bunu kullanıyor).
- Trial süresi / onboarding'de "7 gün ücretsiz dene" akışı henüz kurulmadı — şu an paywall sadece hesap ekranından manuel erişilebiliyor, hiçbir özellik Pro'ya kilitli değil.
Faz 0 — Altyapı ✅ (2026-08-19)
- pnpm monorepo:
apps/api(Fastify),apps/web(Next.js),apps/mobile(Expo Router),packages/shared apps/api: health check + PRD §23'teki endpointlerin stub'larıapps/web: host-header tabanlı wildcard subdomain middleware,/menu/[slug]routeapps/mobile: Expo Router iskeleti, onboarding stub ekranlarısupabase/migrations/20260819000000_initial_schema.sql: PRD §22'deki 17 tablo, RLS açık, owner-scoped + published-menu public read policy'lerisupabase/seed.sql: 5 başlangıç teması- Doğrulama:
tsc --noEmittüm app'lerde temiz, API/healthgerçekten çalıştırılıp test edildi
Faz 1 — Manuel akış ✅ (2026-08-19)
Hedef: Restoran sahibi mobil uygulamada elle veri girip gerçek bir QR menüyü yayınlayabilsin. Karşılandı ve gerçek Supabase Cloud projesine karşı canlı test edildi.
- API: auth middleware (Supabase JWT doğrulama,
requireAuth/requireRestaurantMember) + restaurant CRUD - API: menu/category/item CRUD + publish/unpublish (
menus,menu-categories,menu-itemsroute'ları) - API: QR üretimi (PNG/SVG,
/q/:idstabil redirect URL ile — PRD §12) - API:
/me/restaurant— mobile cold-start rehydration için - Supabase: Faz 1 RLS policy migration'ı (
20260819010000_public_menu_access.sql) - Web: gerçek public menü render (Supabase'ten canlı veri, 5 zengin tema desteği, canlı arama, sticky kategori barı, ürün detay modalı)
- Web:
/q/[id]QR redirect route'u - Mobile: auth ekranları (email login/register) + Supabase client (AsyncStorage session)
- Mobile: restoran onboarding formu → API'ye bağlı
- Mobile: menü editörü (kategori/ürün CRUD, yayınla butonu) —
apps/mobile/src/app/menu/index.tsx - Mobile: QR ekranı (üret, göster, native share) —
apps/mobile/src/app/menu/qr.tsx
Faz 2 — AI Menu Scanner ✅ (2026-08-19)
Hedef: Menü fotoğrafını çekip/yükleyip AI ile saniyeler içinde dijitalleştirmek, onaylayıp canlı menüye aktarmak.
- Shared: AI çıkarma (
AiExtractedCategory,AiExtractedItem), yanıt (AiImportResponse) ve uygulama (AiImportApplyPayload) veri sözleşmeleri. - API:
apps/api/src/lib/ai-scanner.ts— Gemini 1.5 Flash Vision, OpenAI GPT-4o Vision ve akıllı mutfak sezgisel fallback motoru. - API:
POST /menus/:id/import-ai— menü görselini analiz eder,ai_importsveai_import_itemsdenetim loglarını oluşturur, confidence skorları hesaplar. - API:
GET /ai-imports/:id— kaydedilmiş import durumunu döner. - API:
POST /ai-imports/:id/apply— AI Review ekranından onaylanan/düzenlenen kategori ve ürünleri menüye (menu_categories,menu_items) topluca yazar. - Mobile:
expo-image-pickerentegrasyonu (kamera & galeri izinleri ve fotoğraf seçimi). - Mobile:
apps/mobile/src/app/(onboarding)/scan.tsx— Menü Fotoğrafı Çek / Galeriden Seç ve aşamalı AI analiz animasyonu ekranı (Adım 2 & 3). - Mobile:
apps/mobile/src/app/(onboarding)/ai-review.tsx— AI Review & Onay ekranı (Adım 4):- Kategori bazlı ürün listesi
- Düşük güven skorlu öğeler için sarı uyarı rozeti (
⚠️ Düşük Güven (Fiyatı Kontrol Edin)) - Anında ürün adı, fiyat ve açıklama düzenleme
- Kategori/ürün silme ve ekleme
- "✓ Menüyü Onayla ve Kaydet" butonu ile menüye aktarma
- Mobile:
apps/mobile/src/app/menu/index.tsxiçerisine "✨ AI ile Menü Fotoğrafı Tara" tetikleyicisi. - Mobile:
apps/mobile/src/app/account/index.tsx— Hesabım & Restoran Ayarları ekranı:- Kullanıcı profili ve aktif restoran durumu
- Restoran adı, telefon ve adres güncelleme (
PATCH /restaurants/:id) - Canlı menü linki kopyalama ve tarayıcıda açma
- 5 Temadan birini seçip menüye anında uygulama (
GET/PUT /restaurants/:id/theme) - Abonelik plan durumu
- Çıkış yapma (Sign out) ve oturum temizleme
Faz 3 — Web Frontend & 5 Menü Şablonu Engine ✅ (2026-08-20)
- Web:
apps/web/src/app/page.tsx— Lüks Menulio SaaS Landing Page (Hero, 5 Şablon vitrini, Nasıl Çalışır, İstatistikler, Canlı Demo linkleri). - Web:
apps/web/src/lib/theme.ts— 5 Ayrı Tasarım Şablonu Tanımları:- 🌟 Elegant Gold (Fine dining & lüks restoranlar - Altın & Krem, serif tipografi)
- 💎 Modern Sapphire (Kafe & Fast-Casual - Mavi safir & beyaz, 2'li grid layout)
- 🌙 Luxury Dark (Gece kulübü & Kokteyl bar - Obsidian & Kehribar lüks mod)
- ❄️ Nordic Minimal (Butik kahveci & fırın - Sade monokrom liste mizanpajı)
- 🍷 Classic Bistro (Meyhane & Trattoria - Toskana bordo & rustik doku)
- Web:
apps/web/src/components/TemplateGalleryClient.tsx&/templates— İnteraktif şablon galerisi ve canlı telefon simülatörü. - Web:
apps/web/src/app/demo/page.tsx— Tam ekran interaktif demo menü. - Mobil & API: Yerel geliştirme ortamına uyumlu URL ve QR mimarisi (
http://localhost:3000/menu/[slug]). - Mobil:
ThemeSelectorSheet.tsx— Menü editöründen tek tıkla 5 şablondan birini seçme ve anında aktifleştirme. - Mobil: Ürün Görseli Ekleme & Düzenleme (
expo-image-pickerileAddItemModalveItemDetailSheetiçinde galeri seçimi ve canlı önizleme). - Mobil:
MenuItemCard.tsx— Menü ürün kartlarında görsel küçük resim (thumbnail) desteği. - Mobil:
AccountScreen.tsx— Restoran Logosu yükleme/değiştirme ve detaylı restoran bilgileri güncelleme. - Mobil: Alt barda kalıcı "👁️ Önizle" butonu ile tek tıkla canlı menüyü tarayıcıda açma.
- Web:
apps/web/src/components/PublicMenuClient.tsx— Anında arama, masa numarası parametresi (?table=X), garson çağır / hesap iste floating barı, ürün detay modalı ve canlı tema değiştirici çekmecesi.
Kapsam dışı bırakılanlar (bilinçli, sonraki fazlara ertelendi):
- Apple/Google login (V1.5+) — sadece email auth
- Abonelik/RevenueCat (Faz 5) — bu fazda erişim kısıtı yok
Production altyapı + canlı hata ayıklama (2026-08-20)
Bu tarihte proje production'a alınmış halde bulundu: menul.io (Next.js public web), api.menul.io (Fastify API), Coolify (host: Traefik değil Caddy), Cloudflare (DNS/proxy), gerçek Supabase Cloud projesi (fwahdopsyvryvjaqande), git.ayris.tech (self-hosted Gitea, main'e push → Coolify otomatik deploy). Custom domain özelliği (ad.ayris.tech → menul.io) canlıda kurulup test edildi ve çalışır hale getirildi. Bu süreçte bulunup düzeltilen gerçek prod bug'ları:
- API
SUPABASE_SERVICE_ROLE_KEYplaceholder'dı —api.menul.ioher auth isteğini 401'liyordu (mobilde sürekli login döngüsüne sokuyordu). Kullanıcı gerçek key'i env'e girdi. - Fastify default
bodyLimit1 MiB — AI menü fotoğrafı yüklerken "Request body is too large" hatası (model/key ile ilgisiz).apps/api/src/index.ts'te 20 MiB'e çıkarıldı. domains.tsDNS-CNAME doğrulaması proxied domainlerde yapısal olarak asla çalışmaz — Cloudflare proxy (turuncu bulut) gerçek CNAME hedefini public DNS'ten gizliyor (ENODATA)./verifyher çağrıldığında zaten doğrulanmış bir domain'i "pending"e geri düşürüyordu. Artık zaten verified olan bir domain bir daha downgrade edilmiyor. Kalıcı çözüm hâlâ eksik: gerçek doğrulama Cloudflare Custom Hostnames API'sininssl.status'una bakmalı — bunun için Cloudflare API token + zone ID gerekiyor (henüz alınmadı).apps/web/src/middleware.tstrailing slash bug'ı — root path istekleri/menu/<slug>/(sonda slash'lı) üretiyordu,[slug]route'u eşleştiremiyordu → her custom domain/subdomain kök isteği "Menü Bulunamadı" veriyordu. Düzeltildi.PUT /restaurants/:id/themecrash'i — tanımsızthemeDatadeğişkeni kullanılıyordu (main'de önceden var olantschatası, muhtemelen build type-check adımından geçmeden deploy edilmişti). Eksikthemessorgusu eklendi.- Coolify custom domain routing: her custom domain, ilgili Next.js servisine Coolify panelinden elle eklenmesi + redeploy gerektiriyor (otomasyon yok). Wildcard subdomain (
*.menul.io) hiç kurulmadı çünkü gerekmiyor — restoran menülerimenul.io/menu/{slug}path'i üzerinden çalışıyor, alt-domain mimarisi kullanılmıyor.
Sonraki adım (otomasyon): Cloudflare API token + zone ID alınırsa, POST /restaurants/:id/domains restoran custom domain eklediğinde otomatik Custom Hostname oluşturup gereken DNS talimatlarını döndürecek, /verify de Cloudflare'in kendi SSL durumuna bakacak şekilde güncellenebilir — böylece bugünkü manuel Cloudflare dashboard adımları (Fallback Origin, TXT kayıtları, Coolify domain ekleme) her yeni restoran için tekrarlanmaz.