Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

✈ Flight Tracker

A personal flight price tracker that compares flights from multiple sources, visualizes routes on an interactive map, and sends price change digests to your email.

Features

  • Multi-source comparison: Amadeus (2,000 free searches/month) + Google Flights via SerpAPI
  • Source toggle: Enable/disable individual data sources; results filter client-side without re-fetching
  • Interactive map: Great-circle flight paths rendered with deck.gl + MapLibre GL (free, no API key)
  • Price tracking: Save searches for daily automated price monitoring (runs at 06:00 UTC)
  • Email digest: On-demand or scheduled full price snapshot with change indicators (▼ green / ▲ red)
  • Airport autocomplete: Instant search across 4,500+ airports (OurAirports CC0 dataset)

Tech Stack

Layer Choice
Frontend React + Vite + TypeScript
State Zustand + TanStack Query
Map MapLibre GL JS + deck.gl ArcLayer
Styling Tailwind CSS + Headless UI
Backend FastAPI + Uvicorn (Python 3.11+)
Database SQLite + SQLAlchemy 2.0
Scheduler APScheduler (in-process)
Email Gmail SMTP (smtplib)
Flight APIs Amadeus SDK + SerpAPI

Quick Start

Prerequisites

  • Python 3.11+
  • Node.js 20+

1. Backend Setup

cd backend

# Create and activate virtual environment
python3 -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt

# Configure API keys
cp .env.example .env
# Edit .env and fill in your API keys (see API Keys section below)

# Download airport dataset (one-time, ~5MB)
curl -o app/data/airports.csv https://davidmegginson.github.io/ourairports-data/airports.csv

# Start the backend
uvicorn app.main:app --reload --port 8000

Backend is now running at http://localhost:8000 Interactive API docs at http://localhost:8000/docs

2. Frontend Setup

cd frontend

# Install dependencies
npm install

# Configure API base URL
cp .env.example .env
# VITE_API_BASE_URL is already set to http://localhost:8000 via Vite proxy

# Start frontend dev server
npm run dev

Frontend is now running at http://localhost:5173

API Keys

Amadeus (Primary — Free Tier)

  1. Sign up at https://developers.amadeus.com
  2. Create a new app to get API_KEY and API_SECRET
  3. Free tier: 2,000 flight searches/month
  4. Use AMADEUS_HOSTNAME=test for sandbox (test data), production for real pricing

SerpAPI — Google Flights (Secondary — Paid)

  1. Sign up at https://serpapi.com
  2. Copy your API key
  3. Cost: ~$0.0075 per search (10 searches/day ≈ $2.25/month)

Gmail App Password (for email digests)

  1. Enable 2-factor authentication on your Google account
  2. Go to https://myaccount.google.com/apppasswords
  3. Create a new app password for "Mail"
  4. Copy the 16-character password into GMAIL_APP_PASSWORD

Skyscanner

Skyscanner requires a commercial partner agreement and is not available for personal projects. It appears as a disabled option in the UI with an explanatory tooltip.

Usage

Search Flights

  1. Type an airport name or IATA code in the Origin/Destination fields
  2. Select dates and cabin class
  3. Choose which data sources to query
  4. Click Search Flights

Results appear in a sortable list (by price, duration, stops, departure time). Flight routes render as colored arcs on the map:

  • Blue arcs: Amadeus results
  • Green arcs: Google Flights / SerpAPI results

Hovering a flight card highlights the corresponding arc on the map, and vice versa.

Track Price Changes

Click "Track price" on any flight result to save that route for daily monitoring. Saved searches appear in the left sidebar.

The backend checks all saved searches daily at 06:00 UTC and records the lowest price from each source.

Email Digest

Click "Send Digest Now" in the sidebar, enter your email address, and the backend will send an HTML table showing:

  • All tracked routes with current prices per source
  • Price changes since the last check (▼ green = price dropped, ▲ red = price rose)

Project Structure

flight-tracker/
├── backend/
│   ├── app/
│   │   ├── main.py              # FastAPI app + APScheduler startup
│   │   ├── config.py            # Settings from .env
│   │   ├── database.py          # SQLAlchemy + SQLite
│   │   ├── models/              # ORM models (SavedSearch, PriceSnapshot)
│   │   ├── schemas/             # Pydantic models (NormalizedFlight, etc.)
│   │   ├── api/                 # REST endpoints (flights, airports, searches, email)
│   │   ├── services/            # Business logic (Amadeus, SerpAPI, aggregator, email)
│   │   └── data/airports.csv   # OurAirports dataset (download separately)
│   ├── requirements.txt
│   └── .env.example
│
└── frontend/
    ├── src/
    │   ├── App.tsx              # Main layout
    │   ├── api/                 # TanStack Query hooks
    │   ├── store/               # Zustand store (sources, hover state)
    │   ├── components/
    │   │   ├── search/          # SearchForm, AirportCombobox, SourceToggle
    │   │   ├── results/         # ResultsPanel, FlightCard
    │   │   ├── map/             # FlightMap (MapLibre + deck.gl)
    │   │   ├── saved/           # SavedSearches, price history
    │   │   └── email/           # DigestTrigger
    │   └── utils/               # formatters, map helpers
    ├── package.json
    └── .env.example

Notes

  • The SQLite database (flight_tracker.db) is created automatically in the backend/ directory
  • Source toggle preferences are persisted to localStorage and survive page reloads
  • The Amadeus sandbox returns test data (not real prices); switch to AMADEUS_HOSTNAME=production for live data
  • Kayak is not supported due to aggressive anti-bot measures and ToS restrictions

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages