Understanding AI Apps:- matargashti-AI travel-planner
Live demo:- demo
I built this app called matargashti because I was honestly tired of travel planners that either feel too static or just spam API calls every time you touch a dropdown. The idea was simple in the beginning — I wanted something where I could just pick a city, country, number of days, click a button, and get a proper itinerary that actually feels like a human planned it. That’s where the AI part came in.
So the app is basically an AI-powered travel planner where you input your destination and duration, and it generates a full itinerary — best time to visit, places to see, a day-wise plan, budget ranges, and even local tips. This is all generated using AI models through OpenRouter, integrated via the OpenAI SDK. That part was actually the fun part — getting structured, useful output from AI instead of random paragraphs.
But the real challenge wasn’t just “plug AI and done.” The moment you start working with AI APIs, you realize two things: they’re slow and they cost money. So the entire focus of this app shifted from just generating itineraries to generating them intelligently.
Initially, I had the API tied directly to the dropdowns — change city, boom, API call. Change days, another call. That was a disaster. Not only was it wasteful, but the UI also kept flickering and resetting. That’s when I realized I needed to control when the API runs.
So I introduced this idea of separating form state and query state. The dropdowns update the form state freely, but the API only cares about a separate queryParams state, which only updates when the user clicks “Generate.” That one change solved multiple problems at once — no unnecessary API calls, predictable behavior, and much better UX.
Then came the next issue — data disappearing. If I generated a plan, then changed a dropdown, everything would just vanish. That felt terrible from a user perspective. The fix here was subtle but powerful. Instead of tying the UI directly to input changes, I let React Query hold onto the previous data using placeholderData. So even when a new request is triggered, the old data stays on screen until the new one arrives. No flicker, no blank states.
Another interesting bug was around loading states. The loader worked perfectly the first time, but on subsequent requests, nothing showed. It looked like the app wasn’t doing anything. Turns out React Query treats initial load and refetch differently — isLoading vs isFetching. Once I handled both, the UI finally behaved the way it should. I also wired this into the button so it switches from “Generate” to “Generating…” properly every time.
One more thing I didn’t expect was the navigation issue. If I generated a plan, navigated to another page, and came back — everything was gone. Not because React Query lost the data, but because my component lost the reference to it. That’s when I started using queryClient to store and retrieve the last used query parameters. So now when you come back, the app restores your last search and instantly shows the cached result. No localStorage needed, no hacks — just using the tools properly.
From a UX perspective, this app became way better after these changes. The user is always in control, nothing happens unexpectedly, and the app feels fast even though AI calls take time. The biggest win is that it doesn’t feel like a “loading machine” — it feels stable.
What I really took away from building this is that integrating AI is the easy part. The hard part is making it usable. Managing when to call it, how to cache it, and how to present it without breaking the experience — that’s where the real work is.
If I take this further, I’d probably add saving itineraries, user accounts, and maybe even shareable links so people can send their travel plans around. But even in its current state, this project taught me a lot about handling server state, optimizing expensive APIs, and building smoother user experiences.
Overall, this wasn’t just about building a travel app. It was about learning how to build something that feels thoughtful — both technically and from a user’s perspective.
SOCIAL SHARE CARD GENERATOR