Rotavi

A customized AI travel planner — day-by-day trips with real

Visit Website
June 29, 2026 AI travel planner that doesn't hallucinate places or flights

'm Emir, a software engineer, and for the past few months I've been building Rotavi, an AI travel planner — solo. I want to share the one architectural decision the whole product is built around, because it's the thing most "AI trip planner" demos get wrong: the model is not allowed to invent facts.

The problem

Every AI travel tool I tried did two things badly:

  1. It hallucinated — confidently recommending restaurants that don't exist, hotels at the wrong address, or flights that aren't real.

  2. It ignored visas — especially transit visas, where a cheap layover can leave you stuck at the airport because you needed a visa you didn't know about.

Both come from the same root cause: letting a language model act as a source of facts.

The core idea: separate reasoning from facts

The fix is boring but effective. The LLM only structures the plan; it never supplies facts.

  • The model decides the shape of the trip — how many days, the rhythm, what kind of place fits each slot, the narrative flow.

  • Every factual detail — place names, ratings, addresses, flight options, links — comes from authoritative APIs, not the model's memory.

So the model never "recalls" a restaurant. It outputs something like "day 2 afternoon: a well-rated traditional restaurant near the old town" — an intent — and a real query to a places API fills that slot with a real, currently-open venue. If the API returns nothing, the slot stays empty instead of getting invented.

The pipeline, concretely

  1. A short survey: traveler count, profile, preferences (food, history, nature, nightlife, pace).

  2. The LLM produces a structured day-by-day skeleton (JSON) made of typed slots that describe intent, not specific facts.

  3. A resolver layer fills each slot from real sources: a places API for venues, a flight-search API for routes, currency data, and so on.

  4. Validation: anything the resolver can't back with real data is dropped or flagged. The model doesn't get to fill the gap.

  5. Render: day-by-day itinerary, one-tap map links, a PDF, currency notes.

The mental model that helped me: treat the LLM like a creative director, not an encyclopedia.

Keeping API cost sane

Two things did most of the work:

  • Cache aggressively. The same city/query resolves to the same real data for many users — cache it instead of re-hitting the API. It kept the monthly bill tiny.

  • Use a small/cheap model where it's enough. The structuring task doesn't need a frontier model; a fast, cheap one (I use Gemini Flash) handles it well. The "no hallucination" guarantee comes from the architecture, not the model size — which is the whole point.

Visas: the same philosophy, taken further

Transit-visa rules are multi-conditional: your passport, the layover country, whether you leave airside, what other visas you already hold. That's exactly the kind of thing LLMs state confidently and get wrong. So it's a structured rule engine over authoritative data, not the model guessing.

Honest scope: the visa/transit engine currently covers the Turkish passport — that's my own reality and where I could verify the rules. Broadening it is on the roadmap.

Stack & solo notes

For the curious: Next.js + Supabase, a fast LLM (Gemini Flash) for structuring, plus search/places APIs for the real data.

Being solo, the meta-lesson is the usual one: ruthlessly narrow scope, one priority per week, and lean on AI for code and content speed — while never trusting it for facts.

Try it / tell me where it breaks

It's live and free, currently 39 countries / 400+ cities across 4 continents: https://rotavi.app/en?utm_source=indiehackers&utm_medium=referral&utm_campaign=backlink

I'd genuinely love feedback from this crowd — especially on the resolver/validation approach and where you'd push the architecture. Happy to go deeper on any part in the comments.

11 Comments

  1. 2

    Nice UX! Don't think the English language toggle is fully working, I still got a lot of Turkish - but hopefully that suits your real users!

    1. 2

      Thank you! I'm currently working on making it 100% English — since I'm building this alone, some updates take a bit of time. Beyond that, I'd genuinely love to hear any feedback you have, positive or negative, on anything at all.

  2. 1

    Really like the framing of treating the LLM as a creative director, not an encyclopedia — that distinction is so often missing from "AI does X" pitches. I've been thinking about a similar boundary problem from a different angle: scoring connection reliability for multi-leg train journeys, where the temptation is to let an AI "explain" why a connection is risky, but the actual trust has to come from the underlying historical delay data being verifiable, not from how confidently it's phrased. Curious how you're handling cases where the resolver comes back with multiple plausible matches (e.g. several similarly-rated restaurants) — is that ranking also rule-based, or does the LLM get some discretion there once the facts are pinned down?

    1. 1

      Thanks — and your train example is the same shape. To answer directly: on my side there isn't a separate rule engine doing the ranking. Once the resolver has pinned the real candidates (actual places, real ratings/reviews/location — nothing invented), the LLM makes the final pick, guided by a strict prompt that encodes the user's stated preferences. So to your exact question: yes, the model does keep some discretion once the facts are locked.

      The line I hold is the split between facts and selection: zero discretion over facts (it can never conjure a place or a rating that isn't real), but bounded discretion over which of the verified candidates best fits this particular traveler. That subjective match — "which of these three equally-good spots suits a history-leaning couple on a relaxed day" — is exactly where a little model judgment earns its keep, with the strict prompt and the pinned data as the guardrails.

      1. 1

        It's making me think about where the equivalent line would sit for something like connection-safety scoring — there isn't really a "selection" step the same way, since the output is a single probability/label, not a pick among valid candidates. So the discretion question becomes less "which option" and more "how much do I trust a thin data sample" — e.g. a route with only 20 historical runs vs. 2000. Curious whether you've run into anything similar on the resolver side — cases where the real data exists but is too sparse to fully trust, and whether that pushes more toward showing nothing vs. showing it with a caveat.

        1. 1

          Honestly, I don't have a system that reasons about this as strictly yet. What does happen is that the model is already steered toward well-regarded spots rather than picking blind, and every place is then verified against Google Places and surfaced with its real rating and review count — but you're right that that's a quality pass, not a confidence test.

          The thin-sample weighting you're describing is exactly the kind of thing I'll fold in down the line, because a place with 1 review and one with 200 simply don't carry the same trust, even at the same star rating. Rotavi is a solo project — I build and keep improving it on my own — so these refinements get layered in over time. I wouldn't quite call the current state a flaw, but fully internalizing that "how much do I trust this sample" check would be a genuinely nice upgrade.

          1. 1

            That framing makes sense — a quality pass and a confidence test are solving different problems, and conflating them early probably creates more complexity than it's worth. The review-count surfacing at least gives the user the raw signal to make their own call, which is honest.

            The solo-builder tradeoff is real — you can see the right refinement clearly and still rationally defer it. Good luck with it; genuinely interesting architecture to follow.

            1. 1

              Thank you so much.

  3. 1

    I like that the core innovation isn't a better prompt—it's deciding what the model should never be responsible for. Treating the LLM as the planner and external systems as the source of truth feels like a much more durable pattern than trying to make the model "know" everything. That architectural boundary is what makes the promise believable.

    1. 1

      Exactly — thank you for putting it so well. The hard part wasn't drawing that boundary but enforcing it: there's a validation layer that only keeps what's backed by real data and drops anything that isn't, so the model can never quietly fill a gap. Visas were the extreme case — the rules are too conditional to trust to a model at all, so that part is a structured rule engine rather than generation. Really appreciate you engaging with the architecture.

      1. 1

        That's exactly what I was curious about.

        Reading your reply, it feels like there's one much bigger strategic business decision sitting underneath that architectural boundary that I don't think I can properly unpack in a thread.

        Happy to explain what I mean if it's useful. What's the best email to reach you?

About

Planning a trip takes several steps, it makes the process difficult and hard to connect. Rotavi offers everything about a trip in a single platform and makes it much easier.