Custour
An AI travel planner that turns a sentence about your trip into a full itinerary — with real flights, hotels and places attached.
- Role
- Frontend and delivery
- Organisation
- Custour
- Period
- 2026 — active development
- Live
- custour.ai
- Stack
- Next.js
- TypeScript
- NextAuth v5
- TanStack Query
- Stripe
- SERP API
- n8n
- Google Maps
- Tailwind
- GitHub Actions
- pm2
- Vitest
Short explanation
Custour turns a sentence about a trip into a complete itinerary. You describe where you want to go, when, and with whom; the AI returns a multi-day plan with flights, hotels, activities and places attached — and then you edit it, because no generated plan survives contact with an actual traveller.
- Chat-first planning: natural language in, a full itinerary out.
- Real inventory behind the plan — flights and hotels come from live search, not from the model's imagination.
- Editable itineraries: add, remove and reorder everything after generation.
- Google Maps for routing and place context across the plan.
- Three subscription tiers, metered by an AI token allowance.
Why it exists
Planning a multi-day trip means holding flights, hotels, activities and routing in your head at once across a dozen browser tabs. The tools that exist either search one category well or generate itineraries that dissolve the moment you check whether the flights are real.
The bet is that those two halves belong together: generation is only useful if what it generates is bookable.
Tech stack, and why
Next.js and TypeScript on the client. This repository is deliberately frontend-only — it consumes a REST API it doesn't own, which meant the interesting problems were about boundaries rather than about the database.
NextAuth v5 for authentication, with Google OAuth and credentials. The session JWT is injected into axios interceptors, so every outbound call carries auth without each service module remembering to add it, and a proxy middleware guards the private routes at the edge rather than inside each page.
TanStack Query owns all server state. With an AI response that streams and a token balance that changes as you use it, cache invalidation is most of the actual work.
Stripe for subscriptions, n8n as the webhook layer in front of the AI, SERP API for flight and hotel search, and Google Maps through two libraries because the newer one doesn't cover everything the older one does yet.
Features
Chat to itinerary
The whole product in one interaction.
A session starts with destination, dates, travellers and origin, and becomes a conversation. Each chat in the sidebar is a trip plan — the history is the product, not a log of it.
Chat interface generating a multi-day itinerary
Real flight and hotel search
SERP API results, not generated text that looks like results.
This is the line between a demo and a product. A generated plan that names a flight which doesn't exist is worse than no plan, because it costs the user the time to find out.
Flight and hotel results attached to an itinerary day
AI token metering
Free, Premium and Ultra, tracked server-side.
Generation costs money per call, so usage is an allowance rather than a flat subscription. Balances are tracked on the server and surfaced in the profile — never trusted from the client, for obvious reasons.
Token balance and plan state in the account view
Maps and routing
Places in an itinerary are places on a map.
Itinerary places rendered on Google Maps
Delivery pipeline
Four GitHub Actions workflows, split by intent. Two run on pull requests into dev and beta and do nothing but build — a gate, so a branch that doesn't compile can't merge. Two run on push to those branches and deploy.
Deployment isn't push-to-Vercel. The workflow opens an SSH session to the server, pulls, clears the build directory, reinstalls, rebuilds and restarts the process under pm2. That's more moving parts than a managed platform, and it's also the reason I know what each of those steps is for.
Two environments
dev and beta, each with its own branch and its own box.
Branch-per-environment keeps the promotion path obvious: what's on beta is what was on dev, and nothing reaches either without passing its build gate first.
GitHub Actions workflow runs across dev and beta
The part that was actually hard
Owning the frontend of an API you don't control. Every shape change upstream is a change you find out about at runtime, so the service layer is 11 separate modules with their own types rather than one shared client — when something moves, the blast radius is one file.
The other one is streaming. An AI response that arrives progressively fights with a cache that wants to know when a query is done. Getting the itinerary to feel like it's being written, while still landing in a cache entry the rest of the app can read, took more iterations than the generation itself.