A flight search and booking app with no flight API and no backend. Airport and airline data comes from the OpenFlights public dataset — 5,518 airports and 80 major carriers. Flights are generated on demand for any route using that real data, so a search from LHR to JFK returns British Airways, American, and Virgin Atlantic with accurate flight times rather than random strings. The booking flow runs through three steps — passengers, extras, review — and ends at a confirmation screen.
How It Was Built
generateFlightsForRoute(origin, destination, date) seeds a pseudo-random number generator from the route string and date so the same search always returns the same results. It picks carriers that plausibly operate the route, spreads departure times across the day, calculates duration from great-circle distance, and assigns aircraft type based on range. The result looks real because the underlying data is real.
Search state — origin, destination, date, passengers, cabin class — maps directly to URL search params. TanStack Query reads those params as the query key, so the back button restores results, a shared link opens the right search, and the same search always hits the same cache entry.
The booking flow spans three routes. bookingStore (Zustand with sessionStorage persistence) holds the in-progress booking across steps. Each step writes to the store on submit. Navigating back pre-fills the form. On confirmation the store clears and only the booking ID is kept.
Page transitions use Framer Motion's AnimatePresence — a single fade and slide per navigation, nothing looping or auto-playing.
Architecture
Search:
SearchForm → pushes to /search?from=LHR&to=JFK&...
└─ useFlights(params) — TanStack Query
└─ generateFlightsForRoute()
└─ airports.json + airlines.json → Flight[]
Booking:
/passengers → bookingStore.setPassengers()
/extras → bookingStore.setExtras()
/review → bookingStore.confirm() → /confirmation/:id
State:
URL params → search query (source of truth)
Zustand → search form UI + in-progress booking (sessionStorage)
TanStack Query → flight data cache
Stack
| Tool | Version | Role |
|---|---|---|
| React | 19 | UI layer |
| TypeScript | 6 | Strict mode, noUncheckedIndexedAccess |
| Vite | 8 | Dev server + build |
| Tailwind CSS | v4 | Styling |
| shadcn/ui | New York / zinc | Accessible UI primitives |
| TanStack Query | v5 | Server state, caching |
| Zustand | v5 | Search state + booking state |
| React Hook Form | 7 | Multi-step form state |
| Zod | v4 | Schema validation + TypeScript types |
| React Router | v6 | Routing + URL-as-state |
| Framer Motion | latest | Page transitions |
| Lucide React | latest | Icons |