Live on the App Store · Android in closed testing
Nomad TravelGuide
A travel app with an AI planner, a map, chat and community. iOS and Android from one Flutter codebase, backed by Firebase.
- Read the case study
- View on the App Store
- nomad-travelguide.de
- Google Play: currently in closed testing
Planning a trip usually means juggling a search engine, maps, booking sites and a notes document. Nomad puts the planning, the content and the people currently travelling the same route into one app — iOS and Android from a single Flutter codebase.
The planner walks you through five steps, from dates, countries and modes of transport to the finished itinerary. Suggestions come from the Gemini API, and the daily structure is built around real travel times between stops rather than a wish list.
The selection turns into a day-by-day itinerary with accommodation and activities. Every entry can be removed before the plan is finalised.
The social half is the harder one: spots with user-submitted photos and text, a map to go with them, one-to-one and group chat, quests, challenges and a friends book. The moment users can upload content, an app turns into an operation — with reports, moderation and liability.
- Reporting and moderation workflow, enforced on the server rather than hidden in the client
- One central media upload path with video compression
- Offline persistence and image caching for poor connections while travelling
- Aggregated usage statistics with no personal reference
- GDPR implemented entirely by me and checked against my own code
One decision
Firestore has no full-text search. The usual shortcut is a prefix search built on range queries — it only matches from the beginning of a string and breaks on capitalisation, umlauts and words in the middle of a name.
Instead, a Cloud Function computes the search index at write time: the text is normalised, split up and stored as a field on the document. The client only ever queries that field.
The cost is extra writes. In return, results are correct regardless of spelling, without pulling in another service — one I would have to pay for, operate, and declare as a data recipient in the privacy policy.



