Warum HelpMe?
Die Idee kam aus einem echten Problem: Handwerker suchen ist mühsam. Anrufen, Termine abstimmen, keine Transparenz über Preise oder Verfügbarkeit. Ich wollte das lösen — mit einer modernen App, die den Prozess vom Schadensfoto bis zur Beauftragung in einem Flow bündelt.
Die Architektur-Entscheidung: Flutter + Supabase
Ich wusste von Anfang an, dass ich eine Cross-Platform-Lösung brauche. Flutter war die klare Wahl — eine Codebase, iOS und Android, und eine Performance die nativ wirkt.
Für das Backend fiel die Wahl auf Supabase aus mehreren Gründen:
- PostgreSQL as a Service mit eingebautem Row-Level Security
- Realtime-Subscriptions out of the box (kein extra WebSocket-Setup)
- Auth-System ist sofort produktionsreif
- Storage für Bilder und Videos inklusive
// Beispiel: Realtime-Subscription für Chat-Nachrichten
supabase
.from('messages')
.stream(primaryKey: ['id'])
.eq('chat_id', chatId)
.listen((data) {
setState(() => messages = data);
});
Die größte Herausforderung: RLS-Policies
Row-Level Security ist mächtig — aber komplex. Am Ende hatte ich 17+ RLS-Policies, die sicherstellen, dass jeder Nutzer nur auf seine eigenen Daten zugreifen kann.
Ein häufiger Fehler: Zu viele Policy-Checks verlangsamen Queries spürbar. Die Lösung war Indexierung aller Foreign Keys und das Vermeiden von verschachtelten Policy-Aufrufen.
KI-Integration mit Gemini API
Der spannendste Part: Die KI-Auftragserstellung. Der Flow funktioniert so:
- Nutzer fotografiert den Schaden
- Bild wird base64-encoded und an Gemini API geschickt
- Gemini analysiert das Bild und gibt JSON zurück: Titel, Beschreibung, Gewerk
- Auftrag wird pre-filled — ein Tap zum Absenden
final response = await gemini.generateContent([
Content.multi([
TextPart('Analysiere dieses Schadensbild. Gib JSON zurück mit: title, description, trade.'),
DataPart('image/jpeg', imageBytes),
])
]);
Das Ergebnis ist beeindruckend genau — der KI-Assistent erkennt zuverlässig, ob es sich um einen Wasserschaden, einen Elektrikfehler oder eine beschädigte Wand handelt.
State Management mit Riverpod 2.0
Nach Erfahrungen mit Provider und Bloc fiel die Wahl auf Riverpod 2.0 mit Codegen. Die typsichere API und die klare Trennung von UI und Logik haben sich bewährt:
@riverpod
Future<List<Job>> activeJobs(ActiveJobsRef ref) async {
final userId = ref.watch(currentUserProvider).id;
return ref.read(jobRepositoryProvider).getActiveJobs(userId);
}
Was ich gelernt habe
1. Privacy by Design zahlt sich aus. DSGVO-Anforderungen von Anfang an einplanen ist viel einfacher als sie nachträglich einzubauen.
2. Repository Pattern ist kein Overhead. Die saubere Trennung von JobRepository und UI hat debugging und testing massiv vereinfacht.
3. Realtime + Performance = Sorgfalt. Zu viele aktive Subscriptions gleichzeitig können die App spürbar bremsen. Subscriptions konsequent in dispose() canceln.
Fazit
HelpMe ist das Projekt, auf das ich am stolzesten bin. Nicht weil es perfekt ist — sondern weil es echte Probleme löst, mit einem Stack, den ich vollständig verstehe und den ich skalieren kann.
Die vollständige Dokumentation findest du hier.