Inspiration

Every trip plan I ever made was dead by lunch on day one. A museum closed, it rained, we slept in, a friend suggested a bar. Itinerary apps treat the plan as a document you write before you leave. I wanted the opposite: a plan that expects to be wrong and keeps up with you, and that leaves behind a record of what you actually did instead of a list of things you failed to do.

What it does

  • Ten-second start. A city and your dates. Nuoli writes a plan for every day: times, places and the reason each stop is there. Where you stay, how you arrive and what you like can be added later, when you feel like it.
  • A plan that bends. Every stop can be marked done, "not today" or moved to another day in one tap, with undo on everything.
  • Something changed? Say so. Rain, a closed door, running late, worn out: tell Nuoli in the chat and it reworks the day. Every AI change is shown as a list of what it did, and anything it removed can be put back.
  • Near me. Real places open right now within a short walk, from Google Places, filtered to the radius on our server so the list never invents a restaurant.
  • Nuoli, the assistant. One conversation per trip that knows your plan, the local time and where you are, and only answers questions about travel.
  • Memories, not homework. At the end you keep plan versus actual as a trip history.

Where to try it

  • iOS: live on the App Store, version 1.2.2.
  • Web: the same app compiled to WebAssembly at nuoli.app/go. No install needed.
  • Android: built from the same code and running in closed testing on Google Play. Public release coming soon.

How we built it

  • Kotlin Multiplatform + Compose Multiplatform: one codebase for iOS, Android, the web (Kotlin/Wasm) and desktop. Shared domain logic (pure reducers with undo), SQLDelight locally, Koin for DI.
  • Ktor server + MySQL (Exposed) on a VPS: AI generation and refinement with Claude, prompt caching, a daily spend cap, Google Places verification of every stop, and trip sync across devices of one account.
  • RevenueCat (purchases-kmp) for Nuoli Plus: one nuoli_plus entitlement behind a single paywall, the RevenueCat customer id equals the Nuoli account id so a purchase follows the person across devices, and the server verifies the entitlement with RevenueCat before lifting AI limits.
  • Kotzilla for Koin-aware performance monitoring on every platform, plus our own event pipeline into Grafana.

Challenges we ran into

  • Making AI edits trustworthy: a refine edits in place, so we built a diff that shows exactly what changed and lets the traveller undo any part.
  • Keeping the model honest about places: it will happily invent a café "10 minutes away". Nearby answers now come only from a closed list of real places.
  • Mobile networks: Android cuts an app's network in the background, so an answer that arrived while you checked Maps was lost. Asks now carry an id and are recovered on return.
  • Tying purchases to an account rather than a device, so Plus survives a new phone.

Accomplishments that we're proud of

  • Live on the App Store with the same codebase running on Android and the web.
  • A plan you can change with one thumb while walking, without the app ever deciding for you.

What we learned

Real travellers in real cities are the only test that matters. Most of the product changed after one road trip to Vancouver.

What's next for Nuoli

Google Play public release, Android subscriptions, a one-time trip pass, and sharing a trip with the people you travel with.

Built With

Share this project:

Updates

Submission history