Real-time flight booking app with interactive seat selection, multi-passenger booking, rescheduling, and PWA support.
Built with Next.js 16, Supabase, Zustand, Tailwind CSS, and Shadcn UI.
- Search & Book — Search flights by route, select seats on an interactive color-coded cabin map
- Multi-Passenger — Book up to 9 passengers in a single transaction
- Real-Time Seats — Supabase Realtime syncs seat availability across sessions; optimistic UI with rollback
- Reschedule & Cancel — Change flights or cancel bookings; enforced 2-hour cancellation window via DB trigger
- PWA — Service worker, offline fallback page, install-to-home-screen prompt
- 3D Globe — Interactive globe showing flight routes (react-globe.gl)
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router, Turbopack) |
| Language | TypeScript (strict) |
| Styling | Tailwind CSS 4 + Shadcn UI |
| Database | Supabase (PostgreSQL) |
| Auth | Supabase SSR |
| State | Zustand (persisted) |
| PWA | Service Worker + Manifest |
- Node.js >= 20
- A Supabase project (free tier works)
git clone <repo-url>
cd flight-app
npm installCreate a Supabase project at supabase.com, then copy the .env.example:
cp .env.exampleFill in .env.local:
NEXT_PUBLIC_SUPABASE_URL=https://<your-project>.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=<your-anon-key>
SUPABASE_PASSWORD=<your-db-password>Run all 3 migration files in order in the Supabase SQL editor (SQL Editor > New Query):
| Order | File |
|---|---|
| 1 | supabase/migrations/20260522_initial_schema.sql |
| 2 | supabase/migrations/20260523_fix_reschedule_atomicity.sql |
| 3 | supabase/migrations/20260523_schema_qualify_functions.sql |
This creates:
flights,seats,bookings,passengers,reschedulestables- Row-Level Security policies
book_seat,cancel_booking,reschedule_bookingRPC functions (atomic transactions)enforce_cancellation_windowtrigger (blocks cancel/reschedule within 2h of departure)
Run supabase/seed.sql in the SQL editor to populate:
- A test user account
- ~4,416 flights across 4 Indian domestic routes, 4 departure slots per day (06:00, 12:00, 18:00, 22:00 UTC)
- ~530K seats with per-aircraft-type row counts (A320neo=28 rows, B737-800=30 rows, A321=35 rows)
- Flight numbers formatted as
FL-{ORIGIN}-{DESTINATION}-{3-digit-seq}(e.g.FL-DEL-BOM-001)
Note: The seed generates flights from May 23 to July 30, 2026. Date pickers in the app are constrained to this range automatically.
npm run devOpen http://localhost:3000.
| Field | Value |
|---|---|---|
| Email | ritamjunior26@gmail.com |
| Password | 12345678 |
The database seed creates
test@example.com/password123. The accountritamjunior26@gmail.comis used for production testing — sign up through the app or create it manually in Supabase Auth.
| Step | What to do |
|---|---|
| 1 | Sign in with the test account |
| 2 | Select Origin and Destination from the dropdown (DEL, BOM, CCU) |
| 3 | Pick a Date between May 23 – July 30, 2026 and set the number of passengers (1–9) |
| 4 | Click Search Flights — a list of up to 4 flights appears with different aircraft types and prices |
| 5 | Select a flight to open the seat map |
| 6 | Click one or more available seats on the color-coded cabin map (purple = first, sky = business, stone = economy). Selected seats turn green |
| 7 | Click Continue and fill in passenger details (name, passport, nationality, date of birth) for each seat |
| 8 | Review the booking summary and click Pay (mock payment — any card works) |
| 9 | The confirmation screen shows each ticket's PNR code, seat assignment, and price breakdown |
| From | To | Route |
|---|---|---|
| DEL | BOM | Delhi → Mumbai |
| BOM | DEL | Mumbai → Delhi |
| DEL | CCU | Delhi → Kolkata |
| CCU | DEL | Kolkata → Delhi |
| Slot | Departure (UTC) | Aircraft | Rows | Seats | Base Fare |
|---|---|---|---|---|---|
| M | 06:00 | Airbus A320neo | 28 | 168 | $80–$230 |
| A | 12:00 | Boeing 737-800 | 30 | 180 | $80–$230 |
| E | 18:00 | Airbus A321 | 35 | 210 | $80–$230 |
| N | 22:00 | Airbus A320neo | 28 | 168 | $80–$230 |
Slot letters appear in flight numbers: FL-DEL-BOM-001, FL-DEL-BOM-002, etc. (sequenced per route).
- Go to My Bookings from the navbar
- Click Reschedule or Cancel on any confirmed booking
- Rescheduling opens a dialog to pick a new flight, seat, and review the price breakdown (includes $50 reschedule fee)
- Cancellation prompts a confirmation dialog
Both actions are blocked if the original flight departs within 2 hours (enforced by a DB trigger).
src/
├── app/ # Routes and Server Actions
│ ├── (auth)/signin, signup
│ ├── actions/bookingActions.ts # Server Actions (booking, reschedule, cancel)
│ ├── bookings/ # My Bookings page
│ └── offline/ # PWA offline fallback
├── components/
│ ├── flights/ # Search form, flight list, 3D globe
│ ├── seats/ # Seat map with class zones
│ ├── checkout/ # Passenger details, payment, confirmation dialog
│ ├── shared/ # Navbar, reschedule dialog, confirm dialog, PWA
│ └── marketing/ # Landing page for unauthenticated users
├── lib/
│ ├── supabase/ # Client, server, middleware, queries, booking
│ └── services/ # Business logic (booking, payment)
├── store/ # Zustand stores (flightStore, userStore)
└── types/ # TypeScript interfaces
- Modular Monolith — Code is organized by business domain (
flights,seats,checkout, etc.) with strict boundaries - Action-Outcome — Components never mutate the database; Server Actions handle all writes
- Atomic Bookings —
book_seatRPC usesSELECT ... FOR UPDATEto prevent double-booking - State — Zustand stores manage the multi-step booking flow; passenger passport numbers are redacted on persist