FitApp
Tek bir .NET API, üç native istemci ve insanı geri getiren alışkanlıklar.

- Rolüm
- Tek geliştirici — API tasarımı, veri modeli, üç istemcinin tamamı ve dağıtım.
- Durum
- Canlı
Problem
Form takibi verisi ancak cihazı değil kişiyi takip ettiğinde işe yarar — ve ikinci haftadan sonra kimsenin açmadığı bir takip uygulaması hiç işe yaramaz. Aynı özellik setini platform başına bir kez, üç kez yazmak üç ayrı doğruluk kaynağı ve üç ayrı hata kümesi demekti; yalnızca takibi yazmak ise geri dönmek için sebebi olmayan bir uygulama demekti.
Ne yaptım
Tek doğruluk kaynağı olarak MySQL üzerinde çalışan bir C# .NET 8 API, üzerinde ince istemciler: iOS'ta SwiftUI, Android'de Kotlin, web'de Next.js. Öğün, su, adım ve antrenman kaydının ötesinde, alışkanlık hâline getiren kısmı da sunucu yürütüyor — Gemini destekli bir koç, günlük ve arkadaş görevleri, mağazası olan bir altın bakiyesi, liderlik tablosu ve SignalR üzerinden sohbet. Kimlik doğrulama, doğrulama ve her kural API'de; istemciler durumu gösterip girdi topluyor.
Nasıl görünüyor

Gemini destekli koç. API'nin arkasında çalışıyor; böylece anahtar sunucuda kalıyor ve prompt bir mağaza sürümü beklemeden değişiyor. 
Liderlik tablosu, görevler ve altın bakiyesi — her istemcide aynı servisler, çünkü sıralamanın kendisiyle tutarlı olması gerekiyor. 
Web istemcisinde antrenman programları, telefonların kullandığı uç noktaların aynısıyla. 
Günlük rapor — her istemcinin gösterdiği, hiçbirinin hesaplamadığı sayılar.
Mimari
İstemciler
Durumu gösterip girdi toplarlar. İş kuralı taşımazlar; bu yüzden hiçbir platform bir kalori, bir seri ya da bir bakiye konusunda diğeriyle çelişemez.
- SwiftUI (iOS)
- Kotlin (Android)
- Next.js (Web)
API
Kimlik doğrulama, doğrulama ve her hesaplama — bir kuralın yazılı olduğu tek yer; istemcilerin üzerine inşa edildiği bir OpenAPI dokümanının arkasında.
- .NET 8
- JWT
- BCrypt
- Google sign-in
Bağlılık servisleri
Koç, görevler, para birimi ve liderlik tablosu: her biri ayrı bir servis. Çünkü bir form uygulamasının birinci ayı atlatıp atlatamayacağını belirleyen kısım, kalorileri toplayan kısım değil.
- Gemini
- SignalR
- Daily & friend quests
- Gold and shop
Kalıcılık ve medya
Kullanıcılar, öğünler, antrenmanlar, görevler ve bakiyeler için ilişkisel bir şema; yeniden yazılarak değil migration'larla büyütüldü. Görseller nesne depolamaya gider, asla veritabanına değil.
- EF Core 8
- MySQL on AWS RDS
- Cloudinary
- S3
Kararlar ve ödünleşmeler
İş mantığı API'de, asla istemcide değil
Swift, Kotlin ve TypeScript'te çoğaltılmış bir kalori formülü, er ya da geç üç farklı cevap verecek bir formüldür. Sunucuda tutmak istemcileri değiştirilebilir kıldı — ve dördüncü bir uygulama yazmadan web istemcisini mümkün hâle getirdi.
AI koç sunucuda yaşıyor
Modeli üç uygulamadan çağırmak, anahtarı üç ikili dosyaya gömmek ve prompt her yanlış olduğunda bir mağaza sürümü için yalvarmak demekti. Koç, API'nin arkasında tek bir servis: anahtar sunucudan hiç çıkmıyor ve tavsiye bir salı öğleden sonra değişebiliyor.
Oyunlaştırma bir şema, feature flag değil
Görevler, altın, mağaza ve liderlik tablosu; takip koduna sonradan iliştirilmiş koşullar değil, kendi tabloları ve kendi servisleri. Yeni bir görev tipi eklemek bir satır. Büyüyen bir sistemle özel durum biriktiren bir sistem arasındaki fark bu.
Durumsuz JWT kimlik doğrulama
Oturum ömürleri farklı üç istemci, sunucu tarafı oturumların darboğaza dönüşeceği anlamına geliyordu. Token tabanlı doğrulama, her platformun yenilemeyi kendi SDK'sının beklediği şekilde yönetmesine izin verdi.
Sonuç
Bir özellik, birbirinden uzaklaşan üç ayrı uygulama yerine tek bir API değişikliği ve üç sunum katmanı demek — ve otuzuncu gün uygulamayı açma sebebi bir bildirim değil, sunucu tarafında çalışan bir sistem.