Real-time flight tracking and turbulence visualization platform. A modern TypeScript full-stack application built with Express.js backend and React frontend.
- Real-time Flight Tracking: Live aircraft position, altitude, and telemetry data
- Turbulence Detection: Visual representation of turbulence zones
- Weather Integration: Real-time weather data overlay
- WebSocket Communication: Real-time updates via WebSocket protocol
- Responsive UI: Mobile-friendly interface with dark mode
- TypeScript: Fully typed codebase for production reliability
aerovox/
├── server/ # Node.js Express backend
│ ├── src/
│ │ ├── index.ts # Server entry point
│ │ ├── websocket.ts # WebSocket handler
│ │ └── services/
│ │ └── flightData.ts # Flight data service
│ ├── package.json
│ └── tsconfig.json
├── client/ # React TypeScript frontend
│ ├── src/
│ │ ├── main.tsx # React entry point
│ │ ├── App.tsx # Main app component
│ │ └── index.css # Styles
│ ├── index.html
│ ├── package.json
│ ├── vite.config.ts
│ └── tsconfig.json
├── package.json # Root workspace package
├── tsconfig.json # Root TypeScript config
├── .eslintrc.json # ESLint configuration
└── .prettierrc.json # Prettier configuration
- Runtime: Node.js 18+
- Framework: Express.js
- Language: TypeScript
- Real-time: WebSocket (ws library)
- HTTP Client: Axios
- Framework: React 18
- Language: TypeScript
- Build Tool: Vite
- Mapping: MapLibre GL (prepared)
- Styling: CSS3
- Package Manager: npm (workspaces)
- Linter: ESLint
- Formatter: Prettier
- Task Runner: Concurrently
- Node.js 18 or higher
- npm 8 or higher
npm installThis will install dependencies for both server and client packages.
npm run devThis starts:
- Backend server on
http://localhost:3000 - Frontend dev server on
http://localhost:5173
npm run build
npm startCreate server/.env:
NODE_ENV=development
PORT=3000
OPENSKY_USERNAME=
OPENSKY_PASSWORD=
DEBUG=false
LOG_LEVEL=infoSee server/.env.example for all options.
GET /health- Server health checkGET /api/flights- Get all active flightsGET /api/turbulence- Get turbulence zonesGET /api/weather- Get weather data
ws://localhost:3000/ws
Real-time flight updates broadcast every 5 seconds.
npm run type-check # TypeScript validation
npm run lint # ESLint check- Strict TypeScript: Fully typed codebase
- Modern React: Functional components & hooks
- Express Best Practices: Consistent error handling & logging
- Code Formatting: Prettier configured for consistency
The app is ready for OpenSky Network API integration:
- Register at https://opensky-network.org/
- Add credentials to
server/.env - Uncomment API call in
server/src/services/flightData.ts
- MapLibre GL interactive map
- Flight history storage
- Advanced turbulence modeling
- User authentication
- Cloud deployment
- Mobile app (React Native)
See LICENSE file
Open a GitHub issue for questions or bugs
Turbulence is driven by live OpenSky data, not a timer:
- The backend queries
/states/allfor a bounding box (default: YYZ / Great Lakes, set viaOPENSKY_*inbackend/.env) everyPOLL_INTERVALseconds. - It locks onto one aircraft by
icao24and re-finds that same airframe each poll, so itsvertical_ratesamples form a coherent time series. TurbulenceDetectorflags turbulence when that series oscillates (≥2 sign flips) with a spike aboveTURBULENCE_THRESHOLDm/s — i.e. the plane is bouncing up and down for real on the live feed.
OpenSky's anonymous feed refreshes about every 10s, so polling faster than that adds nothing. The TRIGGER TURBULENCE button stays available to force the sequence for a deterministic demo regardless of live conditions.
Airports come from the OurAirports public-domain CSV
(no key). On map load the frontend fetches the CSV, filters to scheduled-service
large/medium airports, and renders them as colored dots with IATA labels; click a dot
for a name/city popup. See frontend/src/components/AirportLayer.js.
IDLE → TURBULENCE_DETECTED → ANNOUNCING → AWAITING_CONFIRMATION → EXECUTING → STABILIZED → IDLE, with AWAITING_CONFIRMATION → TIMEOUT → IDLE if no confirmation
arrives within CONFIRMATION_TIMEOUT seconds.