Zum Hauptinhalt
Zurück zu Projekten
Rahmina logo

Rahmina

Mobile Anwendung

Architekturdiagramm von Rahmina 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.
Eine Local-First-App auf Expo / React Native ohne Server. Inhalte werden Woche für Woche als JSON verfasst, mit Zod validiert, und das Release-Gate stoppt das Deployment, sobald auch nur ein Block nicht freigegeben ist. Die Inhalte kommen im App-Bundle mit, ein Download-Schritt entfällt. Auf dem Gerät ist expo-sqlite die einzige Quelle der Wahrheit; der Import ist versioniert, idempotent und läuft in einer Transaktion. Persönliche Daten verlassen das Gerät nicht.

Eine mobile App mit religiösen und wissenschaftlichen Inhalten für jede Schwangerschaftswoche, mit Quellenangaben. Sie funktioniert offline; persönliche Daten bleiben auf dem Handy und werden an keinen Server gesendet.

Verwendete Technologien

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

Hauptmerkmale

  • Local-first — die Inhalte sind in der App eingebettet, es gibt keinen Download-Schritt
  • Versionierter Import in die Gerätedatenbank, der in einem Schritt abläuft und bei Wiederholung dasselbe Ergebnis liefert
  • Der Kernablauf funktioniert offline
  • Keine personenbezogenen Daten an einen Server — kein Konto, keine Synchronisation
  • Mit ungeprüften Inhalten lässt sich kein Release bauen: das Tor stoppt den Build
  • Zwei Sprachen (TR/EN) und eine zeitzonenunabhängige Wochenberechnung

Entwicklungszeit

1,5 Monate

Problem

Die Inhalte dieser Anwendung sind in zweierlei Hinsicht heikel: Die eine Seite ist religiöse Referenz, die andere Gesundheitsinformation. In beiden Fällen unterscheidet sich der Preis eines falschen Satzes vom Preis eines Softwarefehlers — die Nutzerin handelt in der Annahme, die Information sei richtig. Das eigentliche technische Problem ist deshalb nicht der Bildschirm, sondern der Weg des Inhalts in ein Release: Es brauchte einen Mechanismus, der ungeprüfte Texte davon abhält, in eine Version zu rutschen. Der zweite Punkt ist der Datenschutz: Schwangerschaftsdaten gehören zu den sensibelsten Daten überhaupt. "Auf dem Server halten, später verschlüsseln" ist hier die falsche Antwort; die richtige lautet, sie gar nicht erst zu erheben.

Nutzer

Ein Nutzertyp, aber wechselnde Nutzungsbedingungen: Die App wird über den Tag in kurzen Abständen geöffnet, meist zu Hause, manchmal ohne Verbindung und höchstwahrscheinlich auf dem einen Gerät, auf dem sie installiert wurde. Diese drei Bedingungen machen Startgeschwindigkeit und Offline-Betrieb zur Pflicht statt zur Vorliebe. Es gibt eine zweite Partei, aber nicht in der App: die Person, die die Inhalte prüft. Ihre Entscheidung steht im Repository als Feld.

Meine Rolle

Einzelner Entwickler. Inhaltsschema und Prüfpipeline, Gerätedatenbank und Importlogik, Fachlogik der Schwangerschaftswoche, Oberfläche und Release-Tor.

Architektur

Das System ist serverlos: Es gibt keine API, mit der die App spricht. Die Inhalte liegen als wochenweise JSON-Dateien im Repository und sind durch ein Zod-Schema definiert; beim Paketieren wandern sie in das Binary. Beim ersten Start werden sie in die SQLite-Datenbank des Geräts importiert. Der Import trägt drei Eigenschaften zugleich: versioniert — eine Einheit wird nur überschrieben, wenn ihre Inhaltsversion steigt; idempotent — ein zweiter Lauf desselben Imports ändert nichts; und in einer einzigen Transaktion — er hinterlässt keinen halbfertigen Zustand. Große Importe werden in Stücke geteilt, damit die Oberfläche nicht blockiert; jedes Stück läuft in einer eigenen Transaktion, und zwischen den Stücken wird die Kontrolle abgegeben. Die Schichten sind getrennt: reine Fachfunktionen (Wochenberechnung, Wochenzugriff), Datenbankschicht, Inhaltsschema und Routen. Die Wochenberechnung ist zeitzonenunabhängig — da sie über eine Tagesdifferenz erfolgt, springt die Woche beim Zonenwechsel des Geräts nicht.

Zentrale Entscheidungen

  1. Local-first — kein Server, kein Konto, keine Synchronisation

    Schwangerschaftsdaten sind sensibel; nicht erhobene Daten können nicht abfließen. Da die Inhalte ohnehin mit der App kommen, wäre die einzige Aufgabe eines Servers die Synchronisation des persönlichen Zustands — und der Preis dieser einen Funktion sind ein Kontosystem, eine Datenschutzpflicht und laufende Betriebskosten. Dieser Tausch wurde abgelehnt.

    KompromissWechselt jemand das Gerät, wandert der Fortschritt nicht mit; wird die App gelöscht, sind die Daten weg — es gibt keine Sicherung. Auch Inhaltskorrekturen kommen nicht vom Server: Damit ein Tippfehler die Nutzerin erreicht, braucht es ein neues Store-Release.

  2. Der Inhaltsimport ist versioniert und idempotent

    Die App kann den Import bei jedem Start aufrufen, und derselbe Pfad läuft nach einem Update. Wie oft der Import läuft, darf das Ergebnis also nicht verändern. Verglichen wird über die Inhaltsversion: Ist sie nicht gestiegen, bleibt die Zeile unangetastet. Bei einem Update werden nur geänderte Einheiten geschrieben.

    KompromissDie Garantie hängt daran, dass die Inhaltsversion korrekt erhöht wird; einen Text zu ändern und die Version zu vergessen, heißt, dass die Änderung das Gerät nie erreicht — ein stiller Fehler. Nichts erzwingt die Erhöhung.

  3. Das Release-Tor prüft die Freigabe, nicht das Schema

    Eine Schemaprüfung sagt, dass ein Feld gefüllt ist, nicht, dass es richtig ist. Bei religiösen und medizinischen Inhalten zählt das Zweite. Deshalb trägt jeder Inhaltsblock einen Prüfstatus, und das vor einem Release laufende Tor listet die Dateien auf und endet mit einem Fehlercode, wenn es einen ungeprüften Block findet — der Build stoppt.

    KompromissDas Tor sieht nur den Wert eines Feldes; ob die Freigabe selbst zutrifft, hängt an einem Menschen. Einen versehentlich freigegebenen Text fängt nichts ab, nur nie geprüften Text. Außerdem lässt sich während der Arbeit an Entwürfen kein Release bauen.

  4. Die Quellenangabe ist ein Pflichtfeld im Inhaltsschema

    Sowohl auf religiöser als auch auf wissenschaftlicher Seite zählt die Quelle einer Aussage so viel wie der Text selbst. Ist die Quelle als Schemafeld statt als Gewohnheit definiert, kann Text ohne Quelle nicht ins Repository. Ein eigenes Kommando prüft, ob die Links noch auflösen.

    KompromissDie Linkprüfung geht ins Netz und hängt von der Erreichbarkeit externer Seiten ab; ein kurzer Ausfall lässt die Prüfung fehlschlagen. Deshalb ist sie nicht Teil des Release-Tors, sondern ein separat ausgeführtes Kommando.

Technologiewahl

Expo erlaubt es einer einzelnen Person, für beide Plattformen zu liefern, und ist in einem Umfang ohne native Module der günstigste Weg. Als Gerätedatenbank fiel die Wahl auf SQLite, weil die Inhalte relational und abfragbar sein müssen; in einem Schlüssel-Wert-Speicher lässt sich keine Abfrage über Woche, Schicht und Sprache schreiben. Die synchrone Datenbankschnittstelle hält die Lesepfade ohne asynchrone Zustandsverwaltung einfach. Zod dient als Inhaltsschema und als Typquelle — ein Schema, zwei Aufgaben, wie bei MedAtlas. i18next lässt beide Sprachen mit den Inhalten ausliefern; auch Übersetzungen sind eingebettet und werden nicht aus dem Netz geholt.

Sicherheit

Die Angriffsfläche ist bewusst schmal: Es gibt keinen Server, mit dem die App spricht, kein Kontosystem und keine Authentifizierungsschicht. Der persönliche Zustand — Woche, Fortschritt, Einstellungen — liegt nur in der Gerätedatenbank und wird nirgendwohin gesendet. Da die Inhalte mit der App kommen, gibt es zur Laufzeit auch keine heruntergeladene Nutzlast, die geprüft werden müsste. Das einzige verbleibende Risiko sind die Inhalte selbst, und die schützt das Release-Tor: Ungeprüfte Inhalte kommen nicht in eine Version.

Performance

Dies ist eine mobile Anwendung; eine Seitengeschwindigkeitsmessung ist bedeutungslos, und da keine gespeicherte Messung der Startzeit vorliegt, steht hier keine Zahl. Strukturell gibt es zwei Entscheidungen. Erstens: Da die Inhalte mit der App kommen, wird beim ersten Start kein Download abgewartet — der Bildschirm ist auch ohne Verbindung gefüllt. Zweitens: Der Inhaltsimport ist in Stücke geteilt, damit der Haupt-Thread nicht blockiert; jedes Stück läuft in einer eigenen Transaktion, und zwischen den Stücken wird die Kontrolle abgegeben — die Oberfläche friert beim ersten Start nicht ein.

Ergebnisse

Aktive Entwicklung
2026-07 · 31 Commits
TypeScript-Quelldateien
80
Testdateien
14 — Import, Fachlogik und Inhaltsschema
Inhalt
Zwei Sprachen (TR/EN), wochenbasierte JSON-Einheiten; in jedem Block eine Pflichtquelle und ein Prüfstatus
Architekturgarantie
Personenbezogene Daten verlassen das Gerät nicht — es gibt keinen Server, mit dem die App spricht
Architekturgarantie
Der Import ist idempotent: Dieselbe Version wird nicht zweimal geschrieben, kein halbfertiger Import bleibt zurück
Architekturgarantie
Ein einziger ungeprüfter Inhaltsblock stoppt den Release-Build

Was ich heute anders machen würde

Das Release-Tor an die Inhaltsfreigabe zu binden, war die richtigste Entscheidung dieses Projekts, und ihr Ursprung liegt in MedAtlas: Dort fragte das Tor "passt es zum Schema", und für Bildungsinhalte reichte diese Frage nicht. Hier wurde daraus "wurde es geprüft". Offen bleibt die Versionsnummer selbst: Die Idempotenz des Imports hängt daran, dass die Inhaltsversion korrekt erhöht wird, und nichts erzwingt das — einen Text zu ändern und die Version zu vergessen, heißt, dass die Änderung das Gerät nie erreicht. Heute würde ich eine Prüfung schreiben, die die Inhaltsdatei hasht und mit der Version vergleicht, damit die Regel im Tor statt in der Aufmerksamkeit eines Menschen liegt. Es ist dieselbe Lehre wie bei Bergaz Operations: Solange eine Garantie in einer Gewohnheit statt in einer Prüfung steckt, vergisst sie früher oder später jemand.

Prototyp

Finden wir gemeinsam den richtigen Einstieg

Sagen Sie mir, was Sie bauen möchten; ich sage Ihnen vorab, wie lange es dauert und was der sinnvolle erste Schritt ist.