Familie — Die Familien-App, die uns keiner verkaufen wollte
Kennst du das? Du willst einfach nur wissen, wer diese Woche das Bad putzt, was noch eingekauft werden muss und wann das Kind zum Sport gebracht werden soll — und am Ende hast du fünf verschiedene Apps, drei WhatsApp-Gruppen und trotzdem vergisst jemand den Termin beim Zahnarzt.
Familie ist eine iOS-App, die ich für meine eigene Familie baue. Kein Startup, kein Abo-Modell, keine Cloud-Abhängigkeit. Einfach eine App, die das Familienchaos in den Griff kriegt.
Was kann die App?
Gemeinsamer Kalender
Der Familienkalender zeigt alle Termine aller Familienmitglieder auf einen Blick — farblich nach Person kodiert. Monats-, Wochen- und Listenansicht, wiederkehrende Termine (RFC 5545, also richtig gemacht), und Import aus dem Apple-Kalender. Wenn die Tochter dienstags immer Turnen hat, tragt ihr das einmal ein und fertig.
Aufgabenlisten
Geteilte To-Do-Listen mit drei Modi: "Jeder" (alle sehen es), "Zugewiesen" (einer ist verantwortlich) oder "Irgendwer" (wer es zuerst erledigt, hat gewonnen). Prioritaeten, Faelligkeitsdaten und Wiederholungen inklusive.
Putzplan
Der Klassiker. Raeume, Aufgaben und Zustaendigkeiten — alles konfigurierbar. Wer ist diese Woche fuer Kueche dran? Die App weiss es. Push-Benachrichtigungen erinnern an faellige Aufgaben, und mit "Erledigt" oder "Spaeter" kann man direkt aus der Notification heraus reagieren.
Einkaufsliste
Getrennt von den To-Dos, weil Einkaufen sein eigenes Ding ist. Artikel lassen sich nach Laden sortieren (Lidl, REWE, etc.), und beim Einkaufen zeigt die App nur die Artikel fuer den aktuellen Laden an. Abgehaktes laesst sich mit einem Tap loeschen.
Familienverwaltung
Ein Familienmitglied ist Admin und laedt die anderen ein. Jedes Mitglied bekommt eine Farbe, und man kann auswaehlen, wessen Daten man sehen moechte — praktisch, wenn man nicht immer alles von allen auf dem Schirm braucht.
Warum selbst bauen?
Die ehrliche Antwort: Weil ich es kann und weil mir keine existierende App gefallen hat. Die meisten Familien-Apps wollen entweder ein Abo, schieben alles in irgendeine Cloud, oder sehen aus wie 2015.
Offline-First und Self-Hosted Sync
Die App funktioniert komplett ohne Internet. Alle Daten liegen lokal auf dem Geraet in einer eingebetteten Datenbank (Couchbase Lite). Wer moechte, kann optional einen eigenen CouchDB-Server aufsetzen und die Daten zwischen den Geraeten der Familie synchronisieren. Kein Apple-Cloud-Lock-in, keine fremden Server, keine Abhaengigkeit von Diensten, die naechstes Jahr vielleicht eingestellt werden.
Die Sync-Engine ist netzwerk-aware — sie pausiert automatisch, wenn kein Internet da ist, und setzt fort, sobald die Verbindung steht. Konflikte werden ueber Three-Way-Merge aufgeloest, also gehen keine Daten verloren, selbst wenn zwei Leute gleichzeitig offline etwas aendern.
Datenschutz
Keine Telemetrie, keine Analytics, kein Account-Zwang. Die App weiss nicht mal, dass es mich gibt — und das ist Absicht.
CouchDB selbst hosten
Wer die Sync-Funktion nutzen will, braucht eine laufende CouchDB-Instanz. Das klingt erstmal nach viel Aufwand, ist mit Docker aber in ein paar Minuten erledigt. Die Anleitung hier orientiert sich an einem Setup-Guide aus der Obsidian LiveSync Community, die CouchDB fuer ein aehnliches Offline-First-Sync-Szenario nutzen.
Voraussetzungen
- Ein Server mit Docker und Docker Compose (ein kleiner VPS bei Hetzner fuer ein paar Euro im Monat reicht voellig)
- Eine Domain oder Subdomain mit HTTPS (z.B. ueber Caddy oder Traefik als Reverse Proxy)
Docker Compose
Erstellt eine docker-compose.yml:
services:
couchdb:
image: couchdb:3
restart: unless-stopped
environment:
COUCHDB_USER: admin
COUCHDB_PASSWORD: ein-sicheres-passwort-hier
volumes:
- couchdb_data:/opt/couchdb/data
- ./local.ini:/opt/couchdb/etc/local.d/local.ini
ports:
- "5984:5984"
volumes:
couchdb_data:CouchDB Konfiguration
Legt eine local.ini neben der docker-compose.yml an:
[chttpd]
bind_address = 0.0.0.0
max_http_request_size = 4294967296
[httpd]
enable_cors = true
[cors]
origins = *
credentials = true
methods = GET, PUT, POST, HEAD, DELETE
headers = accept, authorization, content-type, origin, referer
[chttpd_auth]
require_valid_user = true
[couchdb]
single_node = true
max_document_size = 50000000Starten und einrichten
docker compose up -dDanach CouchDB als Single Node initialisieren:
curl -X POST http://admin:ein-sicheres-passwort-hier@localhost:5984/_cluster_setup \
-H "Content-Type: application/json" \
-d '{"action":"finish_cluster"}'Die Datenbank fuer die App anlegen:
curl -X PUT http://admin:ein-sicheres-passwort-hier@localhost:5984/family-appFertig. In den App-Einstellungen traegt man dann die URL (https://deine-domain.de/family-app), Benutzername und Passwort ein, und die Sync-Engine uebernimmt den Rest.
HTTPS nicht vergessen
CouchDB selbst spricht nur HTTP. Fuer den Betrieb uebers Internet braucht ihr einen Reverse Proxy davor, der TLS terminiert. Caddy ist dafuer am einfachsten — ein Caddyfile mit zwei Zeilen reicht:
couchdb.deine-domain.de {
reverse_proxy localhost:5984
}Caddy holt sich automatisch ein Let's-Encrypt-Zertifikat. Alternativ tut es auch Traefik oder nginx mit certbot.
Andere Wege
Es muss kein eigener Server sein. CouchDB laesst sich ueberall betreiben, wo Docker-Container laufen — ob bei einem Cloud-Anbieter eurer Wahl, auf einem Raspberry Pi im Keller oder sonstwo. In der Obsidian LiveSync Community gibt es beispielsweise eine Anleitung fuer ein Fly.io-Deployment mit Dockerfile und persistentem Volume. Das ist keine Empfehlung fuer Fly.io im Speziellen — nur ein Beispiel dafuer, dass das Setup auf verschiedenen Plattformen funktioniert.
Tech-Stack
Fuer die technisch Interessierten:
- Swift 6.0 mit striktem Concurrency-Checking (Xcode 16+)
- SwiftUI fuer die gesamte UI
- Couchbase Lite 4.0 als eingebettete Datenbank
- CouchDB fuer optionalen Self-Hosted-Sync
- EventKit fuer Apple-Kalender-Integration
- MapKit / CoreLocation fuer Orte in Kalendereintraegen
Die Architektur folgt einem modularen Ansatz mit sauberer Trennung: Domain-Schicht (Protokolle und Value Types), Data-Schicht (Persistenz und Sync) und Feature-Module fuer jede Funktionsgruppe. Jedes Feature ist ein eigenes Swift Package.
Concurrency
Swift 6 mit striktem Concurrency ist kein Spass — aber es garantiert zur Compile-Zeit, dass es keine Race Conditions gibt. ViewModels sind @MainActor @Observable, Repositories ebenfalls @MainActor, und alles, was tatsaechlich ueber Thread-Grenzen geht, ist explizit markiert und abgesichert.