Ana içeriğe geç
Projelere Dön
Rahmina logo

Rahmina

Mobil Uygulama

Rahmina mimari şeması Rahmina Local-first mobil — içerik uygulamayla gelir, kişisel veri cihazdan çıkmaz Expo SDK 57 · React Native · expo-sqlite Sunucu yok — bu bir eksiklik değil, karar. DERLEME ÖNCESİ İçerik kaynağı hafta hafta JSON · TR ve EN Zod şeması · kaynak referansı zorunlu her blokta review durumu: draft | approved Yayın kapısı content:check:release onaysız tek blok varsa dosyaları listeler, sıfırdan farklı çıkar dini ve tıbbi içerik onaysız yayına çıkamaz Uygulama paketi içerik ikili dosyanın içinde indirme adımı yok ilk açılışta içerik zaten orada CİHAZDA expo-sqlite — cihazdaki tek gerçek kaynak Sürümlü import contentVersion artmadıkça yazmaz aynı sürüm ikinci kez atlanır idempotent Tek transaction yarım kalan import yok parçalara bölünür, arada kontrol devredilir arayüz donmaz Kişisel durum hafta, ilerleme, tercihler yalnız cihazda sunucuya gönderilmez Kazanç Çekirdek akış internetsiz çalışır. Sunucu maliyeti yok, sızdırılacak kullanıcı veritabanı yok, gizlilik metni "veri toplamıyoruz" diyebiliyor. Bedeli İçerik düzeltmesi mağaza güncellemesi gerektiriyor; bir yazım hatası bile sürüm çıkmadan kullanıcıya ulaşmıyor. Cihaz değişince ilerleme taşınmıyor.
Local-first bir Expo / React Native uygulaması; sunucu yoktur. İçerik hafta hafta JSON olarak yazılır, Zod ile doğrulanır ve yayın kapısında onaysız tek blok bile bulunursa dağıtım durur. İçerik uygulama paketinin içinde gelir, indirme adımı yoktur. Cihazda expo-sqlite tek gerçek kaynaktır; import sürümlüdür, idempotenttir ve tek transaction içinde çalışır. Kişisel durum cihazdan çıkmaz.

Gebeliğin her haftası için dini ve bilimsel içeriği kaynaklarıyla sunan mobil uygulama. İnternetsiz çalışıyor; kişisel veriler telefonda kalıyor, hiçbir sunucuya gönderilmiyor.

Kullanılan Teknolojiler

  • Expo SDK 57
  • React Native
  • TypeScript
  • expo-sqlite
  • expo-router
  • Zod
  • i18next
  • Jest

Öne Çıkan Özellikler

  • Local-first — içerik uygulamayla gömülü geliyor, indirme adımı yok
  • Cihaz veritabanına sürümlü, tek adımda tamamlanan ve tekrar çalıştırılsa da aynı sonucu veren içerik aktarımı
  • Çekirdek akış internetsiz çalışıyor
  • Kişisel veri sunucuya gönderilmiyor — hesap ve senkronizasyon yok
  • Onaysız içerikle sürüm alınamıyor: yayın kapısı build'i durduruyor
  • İki dil (TR/EN) ve saat diliminden bağımsız hafta hesabı

Geliştirme Süresi

1,5 ay

Problem

Bu uygulamanın taşıdığı içerik iki açıdan hassas: bir yanı dini referans, öbür yanı sağlık bilgisi. İkisinde de yanlış bir cümlenin bedeli, bir yazılım hatasının bedelinden farklı — kullanıcı bilgiyi doğru varsayarak hareket ediyor. Dolayısıyla asıl teknik problem ekran değil, içeriğin yayına nasıl çıktığı: gözden geçirilmemiş bir metnin sürüme sızmasını engelleyen bir mekanizma gerekiyordu. İkinci mesele gizlilik: gebelik verisi kişinin en hassas verilerinden biri. "Sunucuda tutalım, sonra şifreleriz" yaklaşımı burada yanlış cevap; doğru cevap veriyi hiç toplamamak.

Kullanıcılar

Tek kullanıcı tipi ama kullanım koşulu değişken: uygulama gün içinde kısa aralıklarla açılıyor, çoğu zaman evde, bazen bağlantısız bir ortamda ve büyük ihtimalle uygulamanın kurulduğu tek cihazda. Bu üç koşul birlikte, açılış hızını ve çevrimdışı çalışmayı bir tercih değil zorunluluk hâline getiriyor. İkinci bir taraf var ama uygulamanın içinde değil: içeriği gözden geçiren kişi. Onun kararı depoda bir alan olarak duruyor.

Rolüm

Tek geliştirici. İçerik şeması ve doğrulama hattı, cihaz veritabanı katmanı ve aktarım mantığı, gebelik haftası alan mantığı, arayüz ve yayın kapısı.

Mimari

Sistem sunucusuz: uygulamanın konuştuğu bir API yok. İçerik depoda hafta hafta JSON olarak duruyor ve Zod şemasıyla tanımlı; uygulama paketlenirken bu içerik ikili dosyanın içine giriyor. İlk açılışta içerik cihazdaki SQLite veritabanına aktarılıyor. Aktarım üç özelliği bir arada taşıyor: sürümlü — bir birimin içerik sürümü artmadıkça üzerine yazılmıyor; idempotent — aynı aktarım ikinci kez çalıştığında hiçbir şey değişmiyor; ve tek transaction'lı — yarım kalmış bir aktarım bırakmıyor. Büyük aktarımlar arayüzü kilitlememek için parçalara bölünüyor, her parça kendi transaction'ında çalışıyor ve parçalar arasında kontrol devrediliyor. Uygulama katmanları ayrılmış: saf alan fonksiyonları (gebelik haftası hesabı, hafta erişim kontrolü), veritabanı katmanı, içerik şeması ve rotalar. Hafta hesabı saat diliminden bağımsız — gün farkı üzerinden hesaplandığı için cihazın dilimi değiştiğinde hafta atlamıyor.

Kritik Kararlar

  1. Local-first — sunucu yok, hesap yok, senkronizasyon yok

    Gebelik verisi hassas; toplanmayan veri sızdırılamaz. İçerik zaten uygulamayla geldiği için bir sunucunun tek işi kişisel durumu senkronize etmek olurdu — ve bu tek özelliğin bedeli bir hesap sistemi, bir gizlilik yükümlülüğü ve sürekli bir işletme maliyeti. Bu değiş tokuş kabul edilmedi.

    ÖdünleşimKullanıcı cihaz değiştirdiğinde ilerlemesi taşınmıyor ve uygulama silindiğinde veri kayboluyor; yedekleme yok. İçerik düzeltmesi de sunucudan gelmiyor: bir yazım hatasının kullanıcıya ulaşması yeni bir mağaza sürümü gerektiriyor.

  2. İçerik aktarımı sürümlü ve idempotent

    Uygulama her açılışta aktarımı çağırabilir; güncelleme sonrası da aynı yol çalışıyor. Bu yüzden aktarımın "kaç kez çalıştığı" sonucu değiştirmemeli. Karşılaştırma içerik sürümü üzerinden yapılıyor: sürüm artmadıysa satıra dokunulmuyor. Böylece güncellemede yalnız değişen birimler yazılıyor.

    ÖdünleşimGaranti içerik sürümünün doğru artırılmasına bağlı; bir metni değiştirip sürümü artırmayı unutmak, değişikliğin cihaza hiç ulaşmaması demek ve bu sessiz bir hata. Sürüm artışını zorlayan bir kontrol yok.

  3. Yayın kapısı onaya bakıyor, şemaya değil

    Şema doğrulaması bir alanın dolu olduğunu söyler, doğru olduğunu söylemez. Dini ve tıbbi içerikte gereken ikincisi. Bu yüzden her içerik bloğu bir gözden geçirme durumu taşıyor ve sürüm öncesi çalışan kapı, onaysız blok bulursa dosyaları listeleyip sıfırdan farklı çıkıyor — build duruyor.

    ÖdünleşimKapı yalnız bir alanın değerine bakıyor; onay bilgisinin doğruluğu insana bağlı. Yanlışlıkla onaylanmış bir metni yakalayan bir mekanizma yok, yalnız hiç gözden geçirilmemiş metni yakalayan bir mekanizma var. Ayrıca taslak içerikle çalışırken sürüm alınamıyor.

  4. Kaynak referansı içerik şemasında zorunlu alan

    Hem dini hem bilimsel tarafta iddianın kaynağı metnin kendisi kadar önemli. Kaynak bir alışkanlık olarak değil şema alanı olarak tanımlandığında, kaynaksız bir metin depoya giremiyor. Bağlantıların hâlâ çalıştığını denetleyen ayrı bir komut var.

    ÖdünleşimBağlantı denetimi ağa çıkıyor ve dış sitelerin erişilebilirliğine bağlı; geçici bir kesinti denetimi başarısız gösteriyor. Bu yüzden bağlantı kontrolü sürüm kapısının bir parçası değil, ayrı çalıştırılan bir komut.

Teknoloji Seçimi

Expo, tek geliştiricinin iki platforma birden teslim etmesini mümkün kılıyor ve yerel modül yazmayı gerektirmeyen bir kapsamda maliyeti en düşük yol. Cihaz veritabanı olarak SQLite seçildi çünkü içerik ilişkisel ve sorgulanabilir olmalı; anahtar-değer bir depoda hafta, katman ve dil kırılımında sorgu yazmak mümkün değil. Senkron veritabanı arayüzü, okuma yollarını asenkron durum yönetimi gerektirmeden basit tutuyor. Zod hem içerik şeması hem tip kaynağı olarak çalışıyor — MedAtlas'ta olduğu gibi tek şema, iki iş. i18next, iki dilin içerikle birlikte gelmesini sağlıyor; çeviri de uygulamayla gömülü, ağdan çekilmiyor.

Güvenlik

Saldırı yüzeyi bilinçli olarak dar: uygulamanın konuştuğu bir sunucu, bir hesap sistemi ve bir kimlik doğrulama katmanı yok. Kişisel durum — hafta, ilerleme, tercihler — yalnız cihazdaki veritabanında duruyor ve dışarı gönderilmiyor. İçerik uygulamayla geldiği için çalışma anında indirilen ve doğrulanması gereken bir yük de yok. Geriye kalan tek risk içeriğin kendisi ve o da yayın kapısıyla korunuyor: onaysız içerik sürüme giremiyor.

Performans

Bu bir mobil uygulama; sayfa hızı ölçümü anlamlı değil ve saklanmış bir başlangıç süresi ölçümü de bulunmadığı için buraya bir sayı yazılmadı. Yapısal tarafta iki karar var. Birincisi: içerik uygulamayla geldiği için ilk açılışta indirme beklenmiyor — bağlantısız bir ortamda bile ekran dolu geliyor. İkincisi: içerik aktarımı ana iş parçacığını kilitlememek için parçalara bölünmüş, her parça kendi transaction'ında çalışıyor ve parçalar arasında kontrol devrediliyor; böylece ilk açılışta arayüz donmuyor.

Sonuçlar

Aktif geliştirme
2026-07 · 31 commit
TypeScript kaynak dosyası
80
Test dosyası
14 — aktarım, alan mantığı ve içerik şeması
İçerik
İki dil (TR/EN), hafta bazlı JSON birimleri; her blokta zorunlu kaynak referansı ve gözden geçirme durumu
Mimari garanti
Kişisel veri cihazdan çıkmaz — uygulamanın konuştuğu bir sunucu yoktur
Mimari garanti
Aktarım idempotenttir: aynı sürüm ikinci kez yazılmaz, yarım kalmış aktarım bırakılmaz
Mimari garanti
Onaysız tek bir içerik bloğu varsa sürüm kapısı build'i durdurur

Bugün Ne Farklı Yapardım

Yayın kapısını içerik onayına bağlamak bu projede aldığım en doğru karar oldu ve kökeni MedAtlas'ta: orada kapı "şemaya uyuyor mu" diye soruyordu ve o soru eğitim içeriği için yetmiyordu. Burada soru "gözden geçirildi mi" hâline geldi. Eksik kalan taraf ise sürüm numarasının kendisi: aktarımın idempotentliği içerik sürümünün doğru artırılmasına bağlı ve bunu zorlayan hiçbir şey yok — metni değiştirip sürümü unutmak, değişikliğin cihaza hiç ulaşmaması demek. Bugün içerik dosyasının özetini alıp sürümle karşılaştıran bir kontrol yazardım; böylece kural insanın dikkatinde değil, kapının içinde dururdu. Bergaz Operasyon'da öğrendiğim şeyin aynısı: garanti kontrolün içinde değil de alışkanlıkta durduğu sürece er geç biri unutuyor.

Prototip

Nereden başlayacağınızı birlikte bulalım

Ne yapmak istediğinizi anlatın; ne kadar süreceğini ve en mantıklı ilk adımı baştan söylerim.