Inspiration
Group trips die in the group chat. Someone dumps a list of cities, budgets don’t match, dates slip, and nobody wants to be the person who picks. We built Tripflow so a group can go from “we should go somewhere” to a shared plan without creating accounts or bouncing between fifteen tabs.
How it works
- Start a trip. Name it, pick a rough date window, a trip length, a max budget and a vibe. You get an invite link.
- Send the link. Friends open it in their browser. They only give a first name, with no sign-up and no password.
- Everyone answers. Home airport, their own budget (kept private), dates they can do, passport and hard nos, and what they want from the trip.
- Check the vibe. A live summary shows who has answered, the group's budget range, the dates that work for everyone, and what people want. It also nudges anyone who hasn't answered.
- Rank 'em. AI suggests places that fit the group's airports, dates and budgets. Tap a place to see its price and why it fits, drag to reorder, or suggest your own place and let AI price it. Lock in your ranking.
- It's happening. When everyone has locked in, the group's top pick becomes the plan. Everyone says "I'm in", votes on where to stay, and gets an AI-drafted itinerary they can edit and add to their calendar.
How we built it
- Next.js 16, React 19, and TypeScript for the app, hosted on Vercel
- Tailwind CSS v4 for a mobile-first Ticket Stack UI
- Upstash Redis so trip state, rankings, and lock-in persist across devices
- Google Gemini (
@google/genai) to propose destinations and draft itineraries from the group’s constraints - dnd-kit for rank-the-tickets drag and drop
- Private device tokens for auth, so a public member id in the URL is not enough to act as someone else
Challenges we ran into
Persisting a shared trip turned out to be harder than drawing the screens. Early on, trips could vanish after a Redis parse error, and rankings would not stick through a reload until we stored rank order and lock-in atomically.
Gemini was in the project before it was actually on: production stored the key under one name and the app read another, so every trip fell back to the same sample destinations and never wrote an itinerary. We taught the app to accept either name so destinations and plans generate for real.
On phones, dragging a ticket followed the finger sideways off the stack. We locked drag to the ranking column, kept the grab point under your finger, and left an open ticket open while you reorder it.
What we learned
A group product has to feel safe and fast on one phone screen. That meant no login wall, a ranking UI that does not jump out from under your thumb, and AI that only appears when it is actually wired up — not a silent fallback to the same five cities.
We also learned to treat estimates as estimates, persistence as a feature, and “it works on my preview” as incomplete until a full trip survives reload, another teammate’s phone, and the production env vars.
What’s next
Richer live pricing, clearer group presence while people are ranking, and a tighter invite so sending the link feels as polished as the tickets.
Built With
- cursor
- dnd-kit
- gemini
- google-cloud
- grokbot
- nextjs
- react
- redis
- tailwind
- typescript
- upstash
- vercel
- zod