Understanding AI Apps:- matargashti-AI travel-planner
Live demo:- demo
I built this app called "matargashti" because I was honestly bored of travel planner apps that either feel too basic or behave weirdly. You change one dropdown and suddenly everything refreshes, data disappears, and you’re just staring at a loader again. I wanted something simpler, pick a place, hit a button, and get a proper travel plan without all that chaos.
The idea was straightforward. You select a city, country, and number of days, and the app gives you a full itinerary. When to visit, places to go, a rough day-by-day plan, budget, and some local tips. Instead of hardcoding anything, I used AI for this. The backend sends a structured prompt through OpenRouter using the OpenAI SDK, and the response comes back in a nicely usable format.
At first, I made a pretty common mistake. I tied the API call directly to the dropdowns. So every time I changed something, it would fire a new request. It looked fine initially, but in practice it was messy. Too many unnecessary calls, UI flickering, and just a bad experience overall. Also, since this is AI, every call actually matters, it’s not something you want to spam.
So I changed the approach. I separated the state, one for what the user is typing or selecting, and one for what actually triggers the API. The API only runs when the user clicks the Generate button. That one change made everything feel more stable and predictable.
Then I ran into another issue, the data disappearing. If I generated a plan and then changed something in the dropdown, the whole UI would go blank. That didn’t feel right. So instead of clearing everything, I made sure the old data stays visible while the new data is being fetched. It sounds small, but it makes a huge difference. The app suddenly feels smoother and less jumpy.
There was also a confusing bug with the loading state. The loader showed up the first time, but not after that. For a while, it looked like the button just stopped working. Turned out React Query treats initial loading and refetching differently. Once I handled both cases properly, the button and loader started behaving the way I expected, showing Generating every time a request is in progress.
Another thing I didn’t expect was what happens when you navigate away and come back. Everything was gone. The data was actually still in React Query’s cache, but my component had no idea how to get back to it. The fix was to store the last used query parameters in the query cache and restore them when the component mounts again. After that, it just works, you come back and your last result is still there.
The interesting part of building this wasn’t really the AI, that part is relatively straightforward once you set it up. The tricky part was making the app behave well around it. Controlling when to call the API, avoiding unnecessary calls, keeping the UI stable, and making sure things don’t randomly reset, that’s where most of the effort went.
If I continue working on this, I’d probably add saving trips, maybe user login, and the ability to share itineraries. But even as it is, this project taught me a lot about handling async data properly and thinking more about user experience instead of just making things work.
In the end, it’s a simple app on the surface, but there’s a lot going on underneath to make it feel smooth.
Top comments (0)