# Aeris Real-time 3D flight tracking — altitude-aware, visually stunning. Aeris renders live air traffic over the world's busiest airspaces on a premium dark-mode map. Flights are separated by altitude in true 3D: low altitudes glow cyan, high altitudes shift to gold. Select a city, and the camera glides to that airspace with spring-eased animation. [Live Demo](https://aeris.edbn.me) Screenshot 2026-02-15 112222 image ## Stack | Layer | Technology | | --------- | ---------------------------------------------------------------- | | Framework | Next.js 16 (App Router, Turbopack) | | Language | TypeScript | | Styling | Tailwind CSS v4 | | Map | MapLibre GL JS | | WebGL | Deck.gl 9 (ScenegraphLayer, IconLayer, PathLayer, MapboxOverlay) | | Animation | Motion (Framer Motion) | | Data | Airplanes.live / adsb.lol / OpenSky (3-tier fallback) | | Hosting | Vercel | ## Getting Started ```bash pnpm install cp .env.example .env.local pnpm dev ``` Open [http://localhost:3000](http://localhost:3000). ## Architecture ``` src/ ├── app/ │ ├── globals.css Tailwind config, theme vars │ ├── layout.tsx Root layout (Inter font) │ ├── page.tsx Entry — renders │ └── api/flights/route.ts adsb.lol reverse proxy (CORS workaround + rate limit) ├── components/ │ ├── flight-tracker.tsx Orchestrator — state, camera, layers, UI │ ├── map/ │ │ ├── map.tsx MapLibre GL wrapper with React context │ │ ├── flight-layers.tsx Deck.gl overlay — icons, trails, shadows, animation │ │ ├── aircraft-model-mapping.ts ADS-B category → 3D model key + bucketing │ │ └── aircraft-model-layers.ts Builds per-model ScenegraphLayers │ └── ui/ │ ├── altitude-legend.tsx │ ├── control-panel.tsx Tabbed dialog — search, map style, settings │ ├── flight-card.tsx Hover card with flight details │ ├── scroll-area.tsx Custom scrollbar │ ├── slider.tsx Orbit speed slider (Radix) │ └── status-bar.tsx Live status indicator ├── hooks/ │ ├── use-flights.ts Adaptive polling hook with credit-aware throttling │ ├── use-settings.tsx Settings context with localStorage persistence │ └── use-trail-history.ts Trail accumulation + Catmull-Rom smoothing └── lib/ ├── cities.ts Curated aviation hub presets ├── flight-api.ts Barrel re-export for the 3-tier flight client ├── flight-api-client.ts airplanes.live → adsb.lol → OpenSky fallback chain ├── flight-api-parsing.ts readsb JSON → FlightState normalization ├── flight-api-types.ts Shared types for ADS-B providers ├── flight-utils.ts Altitude→color, unit conversions ├── map-styles.ts Map style definitions ├── opensky.ts OpenSky API client + types (Tier 3 fallback) └── utils.ts cn() utility ``` ## Design - **Dark-first**: CARTO Dark Matter base map, theme-aware UI - **3D depth**: 55° pitch, altitude-based z-displacement via Deck.gl ## Aircraft Models Aeris renders 14 distinct aircraft silhouettes based on ADS-B emitter category and ICAO type code: | Model Key | Represents | Assignment | | --------------- | ------------------------------- | ---------------------------------------------- | | `narrowbody` | A320, B737 family | Category 3 (Small), 4 (Large), 5 (High vortex) | | `widebody-2eng` | A330, A350, B777, B787 | Category 6 (Heavy) | | `widebody-4eng` | A380, B747, A340 | — | | `a380` | Airbus A380 | Type codes A38x | | `b737` | Boeing 737 family | Type codes B73x, B3xM | | `regional-jet` | CRJ, E-Jets, Fokker | — | | `light-prop` | Cessna, Piper, Cirrus | Category 2 (Light), 12 (Ultralight) | | `turboprop` | ATR, Dash-8, Saab | — | | `helicopter` | All rotorcraft | Category 8 (Rotorcraft) | | `bizjet` | Gulfstream, Citation, Learjet | — | | `glider` | Sailplanes | Category 9 (Glider) | | `fighter` | Military fast-movers | Category 7 (High-perf) | | `drone` | UAVs | Category 14 (UAV) | | `generic` | Fallback for unknown categories | Category 0, 1, default | Models are optimised GLB files (no Draco compression — avoids external WASM decoder dependency) served from Cloudinary CDN (local backups in `public/models/aircraft/`). A second-tier mapping from ICAO type codes (A320, B738, etc.) refines the assignment when type data is available via the readsb feed. - **Smooth animation**: Catmull-Rom spline trails, per-frame interpolation between polls - **Glassmorphism**: `backdrop-blur-2xl`, `bg-black/60`, `border-white/[0.08]` - **Spring physics**: All UI transitions use spring easing - **Responsive**: Desktop sidebar dialog, mobile bottom-sheet with thumb-zone tab bar - **API efficiency**: Adaptive polling (30 s → 5 min) based on remaining credits, Page Visibility pause, grid-snapped cache - **Persistence**: Settings + map style in localStorage, `?city=IATA` URL deep links ## Environment Variables | Variable | Required | Description | | ------------------- | -------- | ------------------------------- | | `NEXT_PUBLIC_GA_ID` | No | Google Analytics measurement ID | No API keys are needed. Flight data comes from public ADS-B APIs with a built-in 3-tier fallback chain (airplanes.live → adsb.lol → OpenSky). ## License AGPL-3.0