Compare commits

..

10 Commits

Author SHA1 Message Date
a246765884 Added basic height filtering. 2026-03-31 16:03:17 -05:00
kew
498504b73b Refactor UI components for improved theming, better flight trace logic and weather data (RainViewer radar tiles and METAR reports) (#17)
* Refactor UI components for improved theming and accessibility

- Updated color schemes in `fpv-hud.tsx`, `hero-banner.tsx`, `keyboard-shortcuts-help.tsx`, `mobile-flight-toast.tsx`, `provider-panel.tsx`, `scroll-area.tsx`, and `slider.tsx` to utilize foreground and background variables for better dark mode support.
- Enhanced visual consistency by replacing hardcoded colors with theme variables across various components.
- Adjusted text and background colors for improved readability and accessibility.
- Fixed minor issues with key bindings in `keyboard-shortcuts-help.tsx`.
- Optimized flight data handling in `use-trail-history.ts` and `trail-cleanup.ts` for better performance and accuracy.
- Implemented outlier filtering in trail history to reduce GPS glitches.

* feat: enhance aircraft appearance and flight trail rendering with improved safety checks and visual effects

* feat: implement last flight leg trimming and nearest airport search functionality

* feat: Enhance flight data parsing and handling

- Added optionalFinite helper function to ensure only finite numbers are processed in flight data.
- Extended FlightState type to include avionics data (ias, tas, mach, roll, trackRate, magHeading) and navigation intent (navAltitudeMcp, navAltitudeFms, navHeading, navQnh, navModes).
- Updated parseRawAircraft function to utilize optionalFinite for avionics and navigation data.
- Adjusted removeSpikePoints function to increase cosThreshold from -0.17 to -0.05 for better spike removal.
- Increased MAX_WINDOW in removePathLoops function from 120 to 300 to allow for larger path loops.
- Integrated loop cleaning in stitchHistoricalTrail function to ensure cleaner paths and altitudes.

* feat: add AtcSpectrum component for audio visualization and useAirportBoard hook for flight data management
2026-03-30 00:21:36 +05:30
0e2ba9fc13 feat: enhance metadata, add robots and sitemap routes, and implement custom 404 and OpenGraph images 2026-03-25 16:41:45 +05:30
56b12afebe Expand static ATC feed database to 635 airports across all continents (#18)
* Initial plan

* Expand ATC feeds to 635 airports covering all continents with verified LiveATC mount points

Co-authored-by: kewonit <108450560+kewonit@users.noreply.github.com>
Agent-Logs-Url: https://github.com/kewonit/aeris/sessions/c2de9c60-f25b-4569-ac24-a5fa35514f32

* Fix KYKM App/Dep typo in channel description

Co-authored-by: kewonit <108450560+kewonit@users.noreply.github.com>
Agent-Logs-Url: https://github.com/kewonit/aeris/sessions/c2de9c60-f25b-4569-ac24-a5fa35514f32

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: kewonit <108450560+kewonit@users.noreply.github.com>
2026-03-24 17:55:57 +05:30
kew
eb1103f63f feat: 3D aircraft model overhaul and multi-source flight data proxy (Resolves #15) (#16)
* Refactor aircraft photo and hero banner components to reset loading state on photo change

- Updated Lightbox component to reset image loading state when navigating between photos.
- Modified HeroBanner component to reset loading state when the photo changes.

Clean up control panel search logic

- Removed unnecessary hasResults variable in SearchContent component.

Implement flight API client with fallback mechanism

- Added flight-api-client to handle fetching flight data from multiple sources (airplanes.live, adsb.lol, OpenSky).
- Introduced flight-api-parsing module to convert raw API responses into standardized FlightState objects.
- Created flight-api-types for shared types between API responses.

Refactor useFlights hook to utilize new flight API client

- Updated useFlights hook to fetch flights using the new flight API client.
- Removed credit management logic as it is no longer applicable with the new API structure.

Fix useFlightMonitors to fetch flight data by hex address

- Changed useFlightMonitors to use fetchFlightByHex instead of fetchFlightByIcao24.

Update geo utility function for better readability

- Refactored splitAtAntimeridian function to improve variable naming and clarity.

Enhance OpenSky types with additional fields

- Added typeCode and registration fields to FlightState type for better integration with readsb data.

* fix: correct 6 files that diverged during rebase (iata code, globe mode ref, terrain attribution, cache eviction, opensky parsing)

* fix: improve keyboard shortcuts help focus trapping

feat: add showAirspace option to MapAttribution component

fix: clear hideTimer on ScrollArea cleanup

refactor: change pendingFpvRef to MutableRefObject in useFlightMonitors

fix: handle sessionStorage availability in useFlightTrack

refactor: increase POLL_INTERVAL_MS in useFlights for better performance

fix: optimize keyboard shortcuts dialog check

refactor: optimize useMergedTrails by caching selected flight position

feat: extend Settings type with airspace options

refactor: improve airline logo normalization functions

refactor: enhance flight API client with serialized rate limiting

refactor: optimize registration country lookup with pre-built maps

refactor: enhance logo cache management with size limits

feat: update map attribution to include airspace option

fix: validate rawState in parseStateRow function

refactor: improve utility functions with clamp implementation

* feat: add ATC lookup functionality and GPU memory monitoring

- Implemented ATC lookup functions in `atc-lookup.ts` for converting IATA to ICAO codes, finding nearby ATC feeds, and looking up ATC feeds by code.
- Introduced `atc-types.ts` to define types and priorities for ATC feeds.
- Added GPU memory monitoring in `gpu-memory-monitor.ts` to track WebGL resource allocations and provide memory reports.
- Enhanced trail stitching logic in `trail-stitching.ts` by adding a function to clear the splined track cache and optimizing altitude checks.

* feat: enhance flight data handling and improve API resilience

- Implemented a maximum empty response streak guard in useFlights to prevent data loss during transient API failures.
- Added immediate fetch on network reconnect in useFlights to ensure timely data retrieval.
- Updated useMergedTrails to include timestamps for trail points.
- Removed smoothAnimations setting from useSettings as it is no longer needed.
- Enhanced useTrailHistory to preserve last-known trails during empty flight responses and added dynamic jump detection for tab resume scenarios.
- Improved flight API client with a circuit breaker mechanism to handle provider failures and prevent excessive retries.
- Updated flight API parsing to reject non-JSON responses from OpenSky and other providers.
- Enhanced trail smoothing and stitching logic to ensure better continuity at junctions between historical and live data.

* feat: migrate aircraft models to Cloudinary CDN and update mapping logic

* fix: adjust UI component styles and improve trail smoothing parameters

* fix: adjust base aircraft size for improved rendering

* feat: update changelog with recent enhancements and modify data source attribution

* fix: update model optimization details and remove Draco compression dependency

* feat: update changelog with recent code review fixes and fallback provider adjustments
2026-03-23 01:25:11 +05:30
kew
147b69b944 feat(map): enhance globe projection handling and improve altitude color representation (#14)
* feat(map): enhance globe projection handling and improve altitude color representation

- Implemented elevation-aware pixel projection for globe mode in `projectLngLatElevationPixelDelta`.
- Refactored north-up animation in `CameraController` to use `setBearing` for smoother transitions.
- Added native GeoJSON support for globe zoom in `FlightLayers`, including dynamic opacity adjustments based on zoom levels.
- Introduced globe-specific pitch and projection settings in `Map` component, ensuring consistent rendering.
- Enhanced UI control panel with a visual separator for better organization.
- Minor formatting adjustments in `altitudeToColor` function for improved readability.

* feat(map): refactor elevation-aware projection handling for improved accuracy

* feat(map): add dark terrain profile support and enhance map styling

* feat: implement trail stitching for merging historical and live flight data

- Added a new module `trail-stitching.ts` to handle the merging of sparse historical track data with high-frequency live trail data.
- Introduced constants for thresholds and parameters to improve code readability and maintainability.
- Implemented a main function `stitchHistoricalTrail` that processes flight tracks, applies smoothing, and merges live tail data.
- Included utility functions for spherical interpolation and cubic easing for altitude transitions.
- Ensured the final path is cleaned of spikes and sharp corners for a smoother representation.

* feat: add centripetal Catmull-Rom spline interpolation for 3D flight trails

- Implemented `catmullRomSpline3D` function to interpolate waypoints into a smooth 3D path.
- Added helper functions for segment density calculation, safe linear interpolation, and endpoint reflection.
- Included support for variable tension based on heading changes to enhance smoothness.
- Introduced utility functions for linear interpolation between elevated points.

* feat(map): enhance layer visibility handling for flight and selection layers

* feat: enhance control panel with new tabs and settings

- Added "Changelog" and "About" tabs to the control panel.
- Introduced new icons for the added tabs using lucide-react.
- Updated the styling of the control panel buttons and dialog.
- Improved accessibility with aria-labels for buttons.

feat: integrate hero banner in flight card

- Added a HeroBanner component to display aircraft photos in the FlightCard.
- Implemented loading and error states for the photo display.
- Enhanced the layout and styling of the FlightCard for better user experience.

fix: update keyboard shortcuts for search functionality

- Added shortcut "⌘K" to open search from anywhere in the application.
- Adjusted keyboard shortcut handling to prevent conflicts with input fields.

fix: optimize flight tracking cache management

- Introduced a maximum cache size for flight tracking to prevent memory growth.
- Implemented a cache eviction strategy for stale entries.

feat: add great-circle utilities for geographical calculations

- Implemented functions for calculating haversine distance, great-circle interpolation, and densifying paths.
- Added functionality to handle antimeridian crossings in geographical paths.

refactor: streamline map styles and terrain handling

- Consolidated terrain DEM source for both terrain mesh and hillshade.
- Adjusted hillshade layer properties for better performance and visual fidelity.

fix: improve bounding box calculations for flight queries

- Enhanced longitude calculations to account for converging meridians at higher latitudes.
- Ensured bounding box calculations are accurate across different latitudes.

* feat(map): refine globe mode functionality and update trail settings
2026-03-11 00:54:51 +05:30
kew
3a10da0486 feat: implement full flight history tracking and enhance trail rendering (#11)
* feat: implement full flight history tracking and enhance trail rendering

* feat: enhance flight tracking logic and improve path handling

* feat: implement airline logo caching and error handling in flight components

* feat: enhance flight tracking logic to improve waypoint handling and connection logic

* feat: refactor longitude handling and improve flight tracking logic

* feat: improve longitude handling and enhance airline logo failure tracking
2026-02-22 18:40:52 +05:30
kew
a08f1c7250 feat: add first person view (FPV) functionality and HUD (#9)
* feat: add first person view (FPV) functionality and HUD

- Updated FlightCard component to include FPV toggle button and state management.
- Introduced FpvHud component for displaying flight data in FPV mode.
- Enhanced useFlights hook to support FPV bounding box logic for fetching flights.
- Added keyboard shortcuts for toggling FPV mode.
- Updated settings to include FPV-related configurations (pitch, chase distance).
- Implemented major airports caching for improved performance.
- Added fetchFlightByIcao24 function for single aircraft state retrieval.

* Refactor CameraController and ControlPanel components; enhance flight search functionality

- Simplified CameraController by removing unused refs and effects, and centralized map interaction management.
- Updated ControlPanel to support flight lookup with new props and integrated flight search results.
- Enhanced SearchContent to include flight matching logic and improved user feedback for flight searches.
- Introduced caching for flight callsign lookups in OpenSky API integration to optimize performance.
- Removed unnecessary settings related to FPV pitch and free camera mode from use-settings hook.

* feat: enhance FPV functionality and improve flight data handling

- Added `projectLngLatElevationPixelDelta` function to calculate pixel deltas based on longitude, latitude, and elevation.
- Updated `CameraController` to utilize new FPV parameters and improve camera behavior during flight.
- Enhanced flight data handling in `FlightLayers` to ensure proper tracking and display of flight information.
- Improved UI components for better user experience, including adjustments to the FPV HUD and flight card.
- Added error handling for image loading in the control panel.
- Refactored altitude and speed calculations to ensure they handle non-finite values gracefully.
- Adjusted map attribution behavior for better responsiveness on different screen sizes.
2026-02-21 12:31:17 +05:30
kew
e262bd730d fix: add OpenStreetMap and data source attribution across all map styles (#8)
Resolves #7 — missing OpenStreetMap attribution.

- Add custom MapAttribution component (expanded by default on desktop,
  collapsed on mobile with outside-click-to-close)
- Add proper attribution strings to all raster tile sources (OSM, CARTO,
  Esri, OpenTopoMap, Mapzen)
- Add getAttributions() helper that returns correct credits per style
- Include OpenSky Network as flight data source attribution
- Include MapLibre as rendering engine attribution
- Replace hidden built-in MapLibre attribution with themed custom UI
2026-02-17 22:22:15 +05:30
kew
bf99d4843f Feat/airline logos opensky refresh (#6)
* feat: keyboard shortcuts, click-to-select, pulse/glow, smooth orbit resume

* feat: add camera controls and enhance keyboard shortcuts help; improve flight card accessibility

* feat: enhance flight layers and keyboard shortcuts; improve airline data structure

* feat: expand airline logos and refresh flight/OpenSky mapping

* feat: import expanded airport dataset

* perf: reduce trail recomputation and soften airport dots

* perf: speed up 9k airport search with index + cache

* docs: add community standards and contribution templates

* docs: enforce issue templates via config

* chore: ignore only .github/agents

* fix: improve airport visibility and stable map marker
2026-02-17 21:50:39 +05:30
412 changed files with 40951 additions and 2894 deletions

27
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,27 @@
---
name: Bug report
about: Report a reproducible problem
labels: bug
---
## Summary
Describe the issue clearly.
## Steps to Reproduce
1.
2.
3.
## Expected Behavior
What should happen.
## Actual Behavior
What happened instead.
## Environment
- OS:
- Browser/Version:
- Commit/Branch:
## Additional Context
Logs, screenshots, or other details.

2
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,2 @@
blank_issues_enabled: false
contact_links: []

View File

@ -0,0 +1,21 @@
---
name: Feature request
about: Propose an enhancement
labels: enhancement
---
## Problem
What problem should this solve?
## Proposal
Describe the proposed solution.
## Scope
What is in scope and out of scope?
## Acceptance Criteria
- [ ]
- [ ]
## Additional Context
Related links, references, or constraints.

15
.github/SECURITY.md vendored Normal file
View File

@ -0,0 +1,15 @@
# Security Policy
## Supported Versions
The `main` branch is the supported baseline for security fixes.
## Reporting a Vulnerability
Please do not disclose vulnerabilities publicly.
Report security issues privately to the maintainers with:
- A clear description of the issue
- Steps to reproduce
- Impact assessment
- Any suggested mitigation
We will acknowledge valid reports and provide status updates during triage and remediation.

15
.github/pull_request_template.md vendored Normal file
View File

@ -0,0 +1,15 @@
## Summary
Describe what changed and why.
## Changes
-
## Validation
- [ ] Relevant checks pass
- [ ] Manual verification completed
## Related
Issue/Task:
## Notes
Any deployment, migration, or follow-up notes.

19
.gitignore vendored
View File

@ -19,7 +19,7 @@
# production
/build
.github
.github/agents
# misc
.DS_Store
@ -44,3 +44,20 @@ next-env.d.ts
# local documentation
docs.txt
ROADMAP.local.md
# heap snapshots & analysis artifacts
*.heapsnapshot
scripts/heap-analysis/output/
scripts/heap-analysis/__pycache__/
# internal planning docs (not for public release)
docs/internal/
# heap analysis tooling & output
scripts/
scripts/heap-analysis/
# editor settings
.vscode/
.idea/

65
CLAUDE.md Normal file
View File

@ -0,0 +1,65 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Commands
```bash
npm run dev # Start dev server (Turbopack)
npm run build # Production build
npm run start # Start production server
npm run lint # ESLint (flat config, ESLint 9)
```
No test framework is configured.
## Architecture
Aeris is a **Next.js 16 App Router** application for real-time 3D flight tracking, built with React 19, TypeScript (strict), and Tailwind CSS v4. Deployed on Vercel.
### Rendering stack
- **MapLibre GL JS** renders the base map (CARTO Dark Matter tiles)
- **Deck.gl 9** overlays WebGL layers on top: IconLayer (aircraft), PathLayer (trails), ScenegraphLayer (14 3D GLB models served from Cloudinary CDN)
- Altitude drives both z-displacement (`Math.max(altitude * 5, 200)` meters) and color (11-stop RGB gradient)
- **Motion** (Framer Motion v12) handles UI animations with spring physics
### Data flow
Flight data uses a **3-tier fallback with circuit breaker**:
1. **adsb.lol** — proxied through `/api/flights` (primary)
2. **OpenSky Network** — direct browser fetch (CORS-enabled)
3. **Airplanes.live** — override only
Polling is adaptive: 10s normally, backs off to 5 min on rate limits. Pauses when tab is hidden (Page Visibility API).
### Key source layout
- `src/app/api/` — 8 proxy routes (flights, ATC audio, weather/METAR, aircraft photos, airspace tiles, radar tiles). All external API calls go through these proxies for CORS and SSRF protection.
- `src/components/flight-tracker.tsx` — Main orchestrator: manages state, camera modes, layers, and UI composition.
- `src/components/map/` — MapLibre context, Deck.gl layer builders, camera controllers (orbit/FPV/globe), animation helpers with Catmull-Rom spline smoothing.
- `src/components/ui/` — UI panels (control panel, flight card, ATC panel, FPV HUD, etc.). Uses Radix UI primitives, cmdk for search, Sonner for toasts.
- `src/hooks/` — Data fetching hooks (`use-flights`, `use-flight-track`, `use-trail-history`), settings context with localStorage persistence, ATC stream management.
- `src/lib/` — API clients, trail processing (cleanup, stitching, spline interpolation), large static datasets (airports 1.3MB, ATC feeds 200KB, airline logos), GPU memory monitoring.
### State management
React hooks + context only. Settings persist to localStorage via `use-settings.tsx`. URL params enable deep linking (`?city=IATA`, `?fpv=ICAO24`). SSR hydration uses `useSyncExternalStore`.
### Trail system
Per-aircraft trail history with 100-point accumulation buffer, Catmull-Rom spline smoothing, and grid-snapped deduplication. Configurable distance (12100 points) and thickness (0.58 px).
## Style conventions
- Conventional commits: `feat:`, `fix:`, `refactor:`, etc.
- Path alias: `@/*` maps to `./src/*`
- OKLCH color system via CSS custom properties in `globals.css`
- Dark-first design with `next-themes`
- No server-side secrets required; env vars are optional (`NEXT_PUBLIC_GA_ID`)
## Build notes
- `next.config.ts` transpiles Deck.gl and Luma.gl packages
- CSP headers and aggressive caching on `/models` (immutable, 1-year max-age)
- License: AGPL-3.0

21
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,21 @@
# Code of Conduct
## Our Commitment
We are committed to a respectful, inclusive, and constructive environment for everyone participating in this project.
## Expected Behavior
- Be respectful and professional.
- Provide constructive feedback.
- Focus on technical discussion and project goals.
- Assume good intent and communicate clearly.
## Unacceptable Behavior
- Harassment, discrimination, or personal attacks.
- Threatening, abusive, or disruptive conduct.
- Sharing private information without consent.
## Reporting
Report concerns to the maintainers through private repository contact channels. Reports will be reviewed promptly and handled confidentially where possible.
## Enforcement
Maintainers may remove, edit, or reject contributions and interactions that violate this Code of Conduct.

21
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,21 @@
# Contributing
## Workflow
1. Create a branch from `main`.
2. Make focused, minimal changes.
3. Run relevant checks locally.
4. Open a pull request with clear context.
## Pull Request Expectations
- Keep PRs scoped to one topic.
- Include a short summary of what changed and why.
- Reference related issues when applicable.
- Update docs when behavior changes.
## Code Quality
- Follow existing project style and conventions.
- Avoid unrelated refactors.
- Prefer clear, maintainable implementations.
## Commit Messages
Use concise, descriptive commit messages (for example: `feat: add airport search index`).

View File

@ -6,33 +6,28 @@ Aeris renders live air traffic over the world's busiest airspaces on a premium d
[Live Demo](https://aeris.edbn.me)
<img width="2559" height="1380" alt="Screenshot 2026-02-15 112222" src="https://github.com/user-attachments/assets/9d1f50ed-be4e-4ef5-95ac-257e9129f8c8" />
<img width="2555" height="1387" alt="image" src="https://github.com/user-attachments/assets/a1d2f673-dfdc-4c82-8ee2-7629d91ad94b" />
## Stack
| Layer | Technology |
| --------- | ----------------------------------------------- |
| Framework | Next.js 16 (App Router, Turbopack) |
| Language | TypeScript |
| Styling | Tailwind CSS v4 |
| Map | MapLibre GL JS |
| WebGL | Deck.gl 9 (IconLayer, PathLayer, MapboxOverlay) |
| Animation | Motion (Framer Motion) |
| Data | OpenSky Network API |
| Hosting | Vercel |
| 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
# Optionally add OpenSky credentials — see .env.example
pnpm dev
```
@ -46,12 +41,14 @@ src/
│ ├── globals.css Tailwind config, theme vars
│ ├── layout.tsx Root layout (Inter font)
│ ├── page.tsx Entry — renders <FlightTracker />
│ └── api/flights/route.ts OpenSky proxy with rate limiting + auth
│ └── 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
│ │ ── 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
@ -65,9 +62,13 @@ src/
│ └── 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
├── opensky.ts OpenSky API client + types (Tier 3 fallback)
└── utils.ts cn() utility
```
@ -75,6 +76,30 @@ src/
- **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
@ -84,15 +109,11 @@ src/
## Environment Variables
| Variable | Required | Description |
| ----------------------- | -------- | ------------------------------- |
| `OPENSKY_CLIENT_ID` | No | OAuth2 client ID (recommended) |
| `OPENSKY_CLIENT_SECRET` | No | OAuth2 client secret |
| `OPENSKY_USERNAME` | No | Basic auth username (legacy) |
| `OPENSKY_PASSWORD` | No | Basic auth password (legacy) |
| `NEXT_PUBLIC_GA_ID` | No | Google Analytics measurement ID |
| Variable | Required | Description |
| ------------------- | -------- | ------------------------------- |
| `NEXT_PUBLIC_GA_ID` | No | Google Analytics measurement ID |
Without credentials, anonymous access is used (~10 requests/minute).
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

92
docs/3D-MODELS.md Normal file
View File

@ -0,0 +1,92 @@
# 3D Aircraft Models
## Overview
Aeris uses 14 distinct 3D aircraft silhouettes to represent different aircraft types on the globe. Models are assigned based on ICAO type code (when available) or ADS-B emitter category.
Two iconic aircraft types — the **Airbus A380** and **Boeing 737** — have dedicated models for visual distinction. All other aircraft are mapped to generic silhouette categories.
## Model Inventory
| File | Size (KB) | Description | Source |
| ------------------- | --------: | ------------------------------------------ | -------------- |
| `b737.glb` | 156.1 | Boeing 737 family (incl. MAX) | fr24-3d-models |
| `bizjet.glb` | 452.8 | Business jets (Gulfstream, Citation, etc.) | FlightAirMap |
| `drone.glb` | 131.0 | Unmanned aerial vehicles | FlightAirMap |
| `fighter.glb` | 58.2 | Military high-performance aircraft | FlightAirMap |
| `generic.glb` | 401.8 | Default fallback (A320 silhouette) | FlightAirMap |
| `glider.glb` | 68.1 | Gliders and sailplanes | FlightAirMap |
| `helicopter.glb` | 270.8 | Rotorcraft | FlightAirMap |
| `light-prop.glb` | 131.0 | Light GA props (Cessna, Piper, etc.) | FlightAirMap |
| `narrowbody.glb` | 401.8 | Narrow-body jets (A320, other non-737) | FlightAirMap |
| `regional-jet.glb` | 127.0 | Regional jets (CRJ, Embraer E-Jets) | FlightAirMap |
| `turboprop.glb` | 86.4 | Turboprops (ATR, Dash-8) | FlightAirMap |
| `widebody-2eng.glb` | 149.3 | Wide-body twin-engine (777, 787, A330) | FlightAirMap |
| `widebody-4eng.glb` | 241.8 | Wide-body four-engine (A340, A380) | FlightAirMap |
### Totals
| Metric | Value |
| --------------------------------- | -------------------: |
| **Aircraft models** | 13 files |
| **Aircraft total** | 2,676.1 KB (2.61 MB) |
| **Legacy model** (`airplane.glb`) | 1,295.2 KB (1.26 MB) |
| **All GLB files** | 3,971.3 KB (3.88 MB) |
## Optimization Pipeline
All models are optimized for web delivery using `@gltf-transform/cli`:
1. **Texture stripping** — Materials set to neutral unlit gray
2. **Mesh simplification** — Triangle count reduced to ~30% of original
3. **B737 format conversion** — Converted from glTF 1.0 → 2.0 via `gltf-pipeline`
> Note: Draco compression is **not** used for these models, to avoid
> introducing an external WASM decoder dependency.
> See `public/models/aircraft/NOTICE.md` for details.
## Model Assignment
### Priority: TypeCode → Category
When an aircraft's ICAO type code is available (from readsb providers), it takes priority over the generic ADS-B category mapping.
**Dedicated model types:**
| Aircraft Type | TypeCode Pattern | Model Key |
| ---------------- | --------------------- | --------- |
| Airbus A380 | `A38x` | `a380` |
| Boeing 737 (all) | `B73x`, `B37M``B39M` | `b737` |
**Category-based fallback (DO-260B):**
| ADS-B Category | Weight Class | Model Key |
| -------------- | ---------------------- | --------------- |
| 2 | Light (<15,500 lbs) | `light-prop` |
| 3 | Small (15,50075,000) | `narrowbody` |
| 4 | Large (75,000300,000) | `narrowbody` |
| 5 | High vortex (B757) | `narrowbody` |
| 6 | Heavy (>300,000 lbs) | `widebody-2eng` |
| 7 | High performance | `fighter` |
| 8 | Rotorcraft | `helicopter` |
| 9 | Glider/sailplane | `glider` |
| 12 | Ultralight | `light-prop` |
| 14 | UAV | `drone` |
| Other | Unknown | `generic` |
## Performance
- Models are **lazy-loaded**: only fetched when an aircraft of that type first appears in data
- The 6 most common model types are **prefetched** via `<link rel="prefetch">` on page load
- Empty ScenegraphLayers are kept alive with stable empty arrays to avoid shader recompilation
- deck.gl caches models by URL, so the `a380` key (which maps to `widebody-4eng.glb`) shares the cache entry
## Licensing
All models are licensed under **GPL v2**, compatible with the project's AGPL v3 license.
- **FlightAirMap-3dmodels**: https://github.com/Ysurac/FlightAirMap-3dmodels
- **fr24-3d-models**: https://github.com/Flightradar24/fr24-3d-models
- Original sources: [FlightGear FGMEMBERS](https://github.com/FGMEMBERS)
See [public/models/aircraft/NOTICE.md](../public/models/aircraft/NOTICE.md) for full attribution.

View File

@ -1,5 +1,29 @@
import type { NextConfig } from "next";
const isDev = process.env.NODE_ENV === "development";
// Content Security Policy — allows only the external resources Aeris actually uses.
// https://nextjs.org/docs/app/guides/content-security-policy
//
// NOTE: planespotters.net, adsbdb.com, airport-data.com, and jetapi.dev are
// server-side only (accessed via /api/aircraft-photos proxy route). CSP does
// not apply to server-side fetches, so they are not listed in connect-src.
const cspHeader = `
default-src 'self';
script-src 'self' 'unsafe-inline' https://www.googletagmanager.com${isDev ? " 'unsafe-eval'" : ""};
style-src 'self' 'unsafe-inline';
img-src 'self' blob: data: https: ;
font-src 'self';
connect-src 'self' data: https://opensky-network.org https://*.basemaps.cartocdn.com https://basemaps.cartocdn.com https://server.arcgisonline.com https://s3.amazonaws.com https://tile.opentopomap.org https://www.google-analytics.com https://www.googletagmanager.com https://api.github.com https://api.airplanes.live https://api.adsb.lol https://res.cloudinary.com https://api.rainviewer.com;
worker-src 'self' blob:;
child-src blob:;
object-src 'none';
base-uri 'self';
form-action 'self';
frame-ancestors 'none';
upgrade-insecure-requests;
`;
const nextConfig: NextConfig = {
transpilePackages: [
"@deck.gl/core",
@ -25,9 +49,23 @@ const nextConfig: NextConfig = {
{
source: "/(.*)",
headers: [
{
key: "Content-Security-Policy",
value: cspHeader.replace(/\s{2,}/g, " ").trim(),
},
{
key: "Strict-Transport-Security",
value: "max-age=63072000; includeSubDomains; preload",
},
{ key: "X-Content-Type-Options", value: "nosniff" },
{ key: "X-Frame-Options", value: "DENY" },
{ key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
{ key: "X-DNS-Prefetch-Control", value: "on" },
{
key: "Permissions-Policy",
value:
"camera=(), microphone=(), geolocation=(self), interest-cohort=()",
},
],
},
{

8759
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -12,11 +12,11 @@
"lint": "eslint"
},
"dependencies": {
"@deck.gl/core": "^9.2.7",
"@deck.gl/core": "^9.2.11",
"@deck.gl/geo-layers": "^9.2.7",
"@deck.gl/layers": "^9.2.7",
"@deck.gl/mapbox": "^9.2.7",
"@deck.gl/mesh-layers": "^9.2.7",
"@deck.gl/layers": "^9.2.11",
"@deck.gl/mapbox": "^9.2.11",
"@deck.gl/mesh-layers": "^9.2.11",
"@deck.gl/react": "^9.2.7",
"@loaders.gl/core": "^4.3.4",
"@loaders.gl/gltf": "^4.3.4",
@ -24,13 +24,15 @@
"@luma.gl/webgl": "^9.2.6",
"@radix-ui/react-slider": "^1.3.6",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"lucide-react": "^0.564.0",
"maplibre-gl": "^5.18.0",
"motion": "^12.34.0",
"next": "16.1.6",
"next": "16.2.1",
"next-themes": "^0.4.6",
"react": "19.2.3",
"react-dom": "19.2.3",
"react": "19.2.4",
"react-dom": "19.2.4",
"sonner": "^2.0.7",
"tailwind-merge": "^3.4.0"
},
"devDependencies": {
@ -39,7 +41,7 @@
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
"eslint-config-next": "16.1.6",
"eslint-config-next": "16.2.0",
"tailwindcss": "^4",
"typescript": "^5"
}

720
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

BIN
public/aeris-hero.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -0,0 +1 @@
<svg fill="#02458D" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Aeroflot</title><path d="M9.066 12.725c-.056-.135-.097-.272-.143-.406l-6.675.406 1.35.693zm.909 1.247c-.057-.042-.115-.1-.17-.15a1.822 1.822 0 0 1-.287-.318l-3.333.67 1.419.509zm2.64-.286c.16-.025.4-.122.588-.268l-.968-2.032 1.005-.51-.848-.782c-.602.292-1.206.58-1.809.868l.43 1.025.694-.33zm1.65-4.241c.387.5.655 1.081.782 1.7h-.61a3.884 3.884 0 0 0-.172-.57c-.41-1.142-1.25-1.956-2.216-2.633-.127-.078-.241-.164-.37-.238.129.044.243.086.37.136.88.372 1.662.885 2.216 1.605m.185 6.517c-.225.114-.455.22-.682.33l-.565-1.193c-.37.139-.76.215-1.154.226-.424.02-.847-.04-1.249-.176l-.483 1.143c-.157.014-.374 0-.512-.106a.378.378 0 0 1-.169-.224c.204-.356.389-.723.579-1.087-.127-.088-.24-.152-.355-.27l.344-.437c.582.38 1.22.585 1.845.585.627.022 1.25-.192 1.832-.628.19.055.385.119.541.18-.058.046-.1.087-.157.136-.114.12-.213.242-.398.346.188.395.387.784.583 1.175zm7.785-3.431L24 11.343h-9.55c0 .422-.06.784-.185 1.1-.369 1.005-1.291 1.487-2.216 1.469-.908-.027-1.834-.524-2.244-1.441a2.745 2.745 0 0 1-.229-1.128H0l1.75 1.188 7.316-.404c.138.553.397 1.037.74 1.395a3.065 3.065 0 0 0 2.243 1.01 2.79 2.79 0 0 0 2.216-.992c.312-.362.554-.826.694-1.385zm-.48.194l-1.352.663L15 12.725a9.5 9.5 0 0 0 .129-.406zm-3.907 1.462l-1.48.52a357.77 357.77 0 0 1-2.286-.735c.069-.06.125-.117.183-.196.085-.074.157-.176.242-.254zm.711-.09l1.177-.575-4.86-.614c-.043.164-.171.298-.256.432zm-13.116 0l-1.179-.542 4.885-.635c.09.152.171.286.27.42Z"/></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 683 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

View File

@ -0,0 +1 @@
<svg fill="#F01428" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Air Canada</title><path d="M12.394 16.958c0-.789.338-.902 1.127-.451a54.235 54.235 0 0 0 2.704 1.465c0-.45.451-.789 1.24-.564.789.226 1.577.338 1.577.338s-.45-1.014-.676-1.464c-.338-.789 0-1.24.338-1.352 0 0-.45-.338-.789-.564-.676-.45-.563-1.014.113-1.24.902-.45 2.141-.9 2.141-.9-.338-.226-.789-.79-.338-1.578.45-.676 1.24-1.69 1.24-1.69H18.93c-.79 0-1.015-.676-1.015-1.127 0 0-1.239.901-2.14 1.465-.79.563-1.465 0-1.352-.902a37 37 0 0 0 .338-2.93c-.451.451-1.24.339-1.69-.337-.564-1.127-1.127-2.48-1.127-2.48S11.38 4 10.817 5.128c-.338.676-1.127.788-1.578.45a37 37 0 0 0 .338 2.93c.113.789-.563 1.352-1.352.789-.901-.564-2.253-1.465-2.253-1.465 0 .45-.226 1.014-1.014 1.127H2.817s.789 1.014 1.24 1.69c.45.676 0 1.352-.339 1.577 0 0 1.127.564 2.141.902.676.338.902.788.113 1.24-.226.225-.789.563-.789.563.45.112.789.563.45 1.352-.225.45-.675 1.464-.675 1.464s.788-.225 1.577-.338c.789-.225 1.127.226 1.24.564 0 0 1.352-.789 2.704-1.465.676-.45 1.127-.225 1.127.45v1.916c0 1.127-.226 2.254-.564 2.93-5.07-.564-9.352-4.62-9.352-10.028 0-5.521 4.62-10.029 10.366-10.029 5.747 0 10.367 4.508 10.367 10.029 0 5.183-4.057 9.464-9.24 10.028v1.352C19.268 22.592 24 17.746 24 11.775 24 5.352 18.592.282 11.944.282 5.408.282 0 5.352 0 11.662c0 5.521 4.169 10.14 9.69 11.155.902.225 1.465.338 2.028.901.564-1.126.676-3.38.676-4.62Z"/></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1 @@
<svg fill="#E30E17" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Air China</title><path d="M6.75 23.377c3.431.96 7.361-1.449 7.361-5.442v-4.713c0-1.377 1.147-3.19 3.212-3.19 2.17 0 3.201 1.949 3.201 3.19 0 .792-.313 2.377-1.804 2.377-1.188 0-1.95-1.21-1.574-2.2-.083.333.093.657.449.657.343 0 .532-.324.468-.73 0-.083-.104-.834-.939-.834-.698 0-.927.636-.927.948v4.193c0 4.483-4.88 7.798-9.447 5.744M3.508 19.99s2.303 2.336 5.338.573c2.012-1.167 2.075-3.598 2.075-3.598v-5.431s-.084-2.722 2.366-4.672c1.711-1.345 3.296-1.252 4.39-1.387 2.806-.344 4.057-2.116 4.057-2.116.031.302-.272 3.555-3.785 4.483-.72.188-4.578-.187-4.578 4.275v5.38c0 1.126-.27 3.118-2.377 4.526-2.169 1.439-5.683 1.21-7.486-2.033M1.047 8.759H3.85c0-.5.428-1.471 1.523-1.471.427 0 .5.095 1.052-.02.72-.24 1.043-.657 1.19-.99 0 0 .28 1.187-.845 1.813-.637.345-1.616.074-1.616.074s-.792-.115-.897.593c.449 0 1.147.449 1.147 1.22v6.528c0 .469.375.96.949.96a.95.95 0 0 0 .949-.96v-4.578c0-6.757 5.255-9.56 8.31-9.79 2.533-.188 4.244.04 7.34-2.138 0 0-.97 3.796-5.358 4.703-.804.166-3.224-.115-5.497 2.252-1.803 1.877-1.99 3.608-1.99 5.891v4.035c0 1.762-1.419 3.545-3.587 3.545-2.096 0-3.566-1.668-3.566-3.545v-6.85c0-.563-.406-1.074-1.054-1.074h-.854Z"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 953 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1 @@
<svg fill="#002157" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Air France</title><path d="M13.776 3.9L5.184 16.332C4.051 17.969 2.208 19.548 0 19.721v.379h9.552c2.544 0 4.397-1.656 5.616-3.48L24 3.9Z"/></svg>

After

Width:  |  Height:  |  Size: 238 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1 @@
<svg fill="#DA0E29" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Air India</title><path d="M8.483.001C6.247.043 4.102 1.018 2.092 2.898c.141-.065-.545.44-1.637 1.676.013.006-.009.017-.013.025 0 0 .014.037.14-.064.75-.61 3.198-2.893 9.86.101a276.52 276.52 0 0 0 6.42 2.78s1.027 3.236 2.207 6.637c2.398 6.89-.087 9.135-.76 9.82-.102.114-.064.127-.064.127a16.746 16.746 0 0 0 2.385-2.08c1.624-1.637 2.588-3.428 2.855-5.344.254-1.878-.203-3.5-.584-4.566-.266-.75-.481-1.346-.672-1.88-.862-2.423-1.028-2.867-1.625-5.29l-.203-.8c-.023-.003.009-.016.014-.025l-.787-.254c-2.386-.774-2.804-.964-5.165-2.017-.52-.229-1.103-.496-1.826-.813-.85-.368-2.146-.875-3.707-.926a8.027 8.027 0 0 0-.447-.004Z"/></svg>

After

Width:  |  Height:  |  Size: 725 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 872 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1 @@
<svg fill="#0E203F" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Air Serbia</title><path d="m16.667 3.754-1.148.002-.455.169s-.25.062-.416.482l-.343 1.079s-.094.358-.118.903c-.018.546-.008.019-.008.019s-.026.81-.119 1.055l-.184.643c-.27.634-.546.945-.551.955l-1.032 1.193v.005l-.292.327-.287-.327.006-.006-.639-.725-.086-.104h-.004l-.32-.362c-.003-.01-.294-.343-.566-1.01l-.172-.588c-.093-.245-.12-1.055-.12-1.055s.011.527-.01-.019a4.555 4.555 0 0 0-.113-.903l-.346-1.079c-.169-.42-.415-.483-.415-.483l-.453-.168-1.15-.002-.184.268c-.205.193-.258.116-.531.158-.217.03-.294.043-.473.181-.231.188-.264.434-.264.434v.465l.014.319.262-.325c.443-.018 1.06.252 1.06.252l-.074.182c-.064.144-.063.268-.063.268s-.032.526-.095.84c-.018.092-.03.245-.085.398-.091.268-.564.793-.67.913l-.594.638c-.454-.366-1.24-.853-2.244-.891C2.312 7.81 1.275 8.27.3 9.223L0 9.521l.225.352c.034.055.833 1.292 2.274 1.57.93.181 1.946-.102 2.908-.791l-.703-.793c-.713.515-1.36.686-1.998.565-.598-.114-1.057-.487-1.325-.773.649-.526 1.303-.786 1.95-.76 1.137.041 1.942.932 1.947.94l1.685 1.948.69-.797-1.292-1.49 1.512-1.881.614-.768c.144.761.834 2.071 1.128 2.527l-1.677 1.948-.67.78-.008.01-.006.01-.713.826c-.373.394-1.675 1.679-3.203 2.497 0 0 .48.329 1.107.323.377-.008.813-.14 1.225-.533.17-.158.42-.385.667-.615 0 0-.114.274.155.781.212.386.573.62 1.073.636.777.03 1.333-.375 1.718-.845l-.554-.61s-.5.714-1.114.278c-.225-.212-.206-.57-.206-.57s-.01-.12.109-.373c.417-.705 1.56-2.19 2.236-3.058l.521-.66.747.858.002-.004.291.338-.002.006.02.018-1.303 1.61.59.667L12 12.182v.005l.004-.005 1.685 1.871.7.787.247.26.175.192c.382.42.914.767 1.627.741.5-.017.864-.25 1.075-.636.271-.506.156-.781.156-.781.247.23.493.457.665.615 1.107 1.05 2.331.21 2.331.21-1.523-.818-2.825-2.103-3.195-2.496l-.408-.47-.852.95c.41.565.394.861.394.861s.011.36-.212.571c-.607.441-1.149-.318-1.149-.318l-1.692-2.052-.005-.012-.873-1.07.017-.017.644-.742h-.004l.39-.45.173.214 1.105 1.492.778-.919-1.267-1.475-.001.003-.122-.14c.296-.457.983-1.767 1.126-2.528l.617.768 1.51 1.881-.31.358-1.268 1.468-1.1 1.26-.325.384.688.794.54-.632v.003l.064-.068.82-.947.48-.556 1.495-1.726c.008-.007.805-.898 1.947-.939.652-.026 1.302.234 1.949.76-.269.286-.724.659-1.322.773-.64.12-1.294-.056-2.008-.566l-.686.788c.962.69 1.966.978 2.902.798 1.435-.28 2.233-1.516 2.269-1.57L24 9.52l-.297-.298c-.978-.952-2.017-1.413-3.088-1.368l.001-.001c-.851.032-1.542.384-2.012.716l-.052.037c-.004.001-.012.012-.013.012-.062.046-.124.085-.173.126l-.743-.8c-.176-.213-.453-.557-.521-.75-.057-.154-.071-.307-.084-.399a8.035 8.035 0 0 1-.099-.84s0-.124-.058-.268l-.073-.182s.618-.27 1.054-.252l.27.325.004-.319v-.465s-.028-.247-.265-.434c-.178-.138-.256-.15-.47-.18-.275-.042-.32.034-.525-.159zm-7.648 8.8-.633.84.718.836.84.992 1.074 1.239.692-.794-1.37-1.573-.684-.798zm4.374 1.841-.966 1.12-1.115 1.284c-1.118 1.04-1.204 1.43-1.204 1.43-.467 1.174.15 2.017.15 2.017.089-.733.713-1.444.935-1.72l.433-.496v-.002l1.534-1.775.91-1.046zm-.41 2.709-.706.83.08.094-.002.002.43.496c.225.276.845.987.937 1.72 0 0 .613-.843.15-2.018 0 0-.07-.313-.888-1.124z"/></svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@ -0,0 +1 @@
<svg fill="#172B54" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Air Transat</title><path d="M17.611 0c-2.931.916-5.68 3.434-8.474 6.137C5.564 6.32 1.672 7.74 1.26 7.969c4.122 2.152 5.129 3.115 5.129 3.115s-1.374 3.938-1.649 6.457c.916-2.244 2.702-5.312 3.801-6.777-1.511-1.237-4.35-2.565-4.35-2.565s2.244-.962 6.733-1.191c0 0 1.878-3.619 6.687-7.008zm-2.244 3.344c-.412.87-1.146 2.793-1.283 4.213 3.16.229 5.312.963 5.312.963s-3.205 1.19-4.992 2.609c.32.779 1.055 3.07 1.467 4.855-.687-.64-2.748-2.336-4.26-3.252C9.596 13.511 4.1 18.962 1.031 24c1.328-1.374 5.267-5.817 10.58-9.023 1.1.64 6.137 3.939 6.137 3.939s-1.1-5.862-1.512-7.236c1.558-1.054 4.214-2.52 6.733-3.3-3.527-1.419-7.832-1.784-7.832-1.784s-.09-1.1.23-3.252z"/></svg>

After

Width:  |  Height:  |  Size: 761 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1 @@
<svg fill="#FF0000" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>AirAsia</title><path d="M11.54 14.49c-1.278 0-2.264-.998-2.264-2.276 0-1.252.98-2.27 2.264-2.27 1.232 0 2.238 1.018 2.238 2.27 0 1.278-1.005 2.277-2.239 2.277zm3.074-7.854l-.214.998c-.59-1.18-2.348-1.297-3.295-1.297-2.952 0-5.527 2.841-5.527 6.746 0 3.14 1.875 5.111 4.23 5.111 1.316 0 2.432-.304 3.353-1.4l-.24 1.102h3.711l1.692-11.26c-1.238-.001-2.482.01-3.71 0zM12 0c6.63 0 12 5.37 12 12s-5.37 12-12 12S0 18.63 0 12 5.37 0 12 0Z"/></svg>

After

Width:  |  Height:  |  Size: 533 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -0,0 +1 @@
<svg fill="#0078D2" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>American Airlines</title><path d="M0 .244h3.264c1.377 0 1.942.563 2.499 1.116.637.58 2.57 3.196 6.657 8.303H7.997c-1.809 0-2.38-.308-3.08-1.375zm10.424 17.072l-2.427-4.013c-.292-.455-.372-.854-.372-1.318 0-.51.217-.79 1.053-1.233.973-.466 2.933-.67 4.954-.67 3.283 0 4.07 1.055 4.405 2.192 0 0-.464-.185-1.554-.185-3.459 0-6.223 1.68-6.223 4.221 0 .534.164 1.006.164 1.006zm4.936-3.417c-2.547.089-5.032 1.869-4.936 3.416l2.7 4.486c.836 1.344 2.215 1.955 3.932 1.955H24l-8.13-9.852a5.55 5.55 0 0 0-.51-.005Z"/></svg>

After

Width:  |  Height:  |  Size: 608 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1 @@
<svg fill="#FF0000" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>avianca</title><path d="M3.813 0s-2.326 2.052-2.51 6.367c-.205 4.716 2.324 9.47 10.654 10.076.026.005.055.005.08.008C7.806 11.534 4.955 5.241 3.812 0zm8.224 16.451a30.654 30.654 0 0 0 2.2 2.303H5.282c.12.278.53.472 1.463.527 5.59.332 6.38 4.719 14.381 4.719.702 0 1.14-.042 1.582-.125-3.16-.972-6-2.8-8.47-5.121h2.21c.917 0 1.325.076 1.58.191-.392-1.218-1.631-2.168-5.992-2.494z"/></svg>

After

Width:  |  Height:  |  Size: 480 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -0,0 +1 @@
<svg fill="#2E5C99" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>British Airways</title><path d="M23.489 13.252c-.25.212-.605.444-1.241.767-1.347.72-2.198.983-2.198.983s-1.617-.234-4.207-1.007c0 0 1.306-.378 1.93-.581a40.11 40.11 0 0 0 1.958-.681c1.055-.396 1.73-.761 2.18-1.088.03-.022.058-.046.085-.068 0 0 .32.036.593.113.294.083.604.245.786.386.191.147.28.308.308.358a.681.681 0 0 1 .071.226s.014.085-.003.177a.579.579 0 0 1-.147.313zM24 12.196a.662.662 0 0 0-.08-.157 1.348 1.348 0 0 0-.197-.23 1.685 1.685 0 0 0-.227-.178c-.354-.232-.81-.362-1.215-.416-.627-.083-1.342-.07-1.411-.07-.23-.005-1.722.007-2.105.015-1.702.034-3.787.039-4.333.038-5.636.027-8.089-.094-10.82-.642C1.289 10.094 0 9.658 0 9.658c2.05-.073 14.004-.568 16.186-.627 1.427-.04 2.44-.048 3.253 0 .413.023.802.058 1.287.14a6.2 6.2 0 0 1 1.064.286c.486.18.893.442 1.096.707 0 0 .06.06.14.17.093.126.197.282.234.34.294.447.434.73.484.828.052.102.1.209.145.315.044.104.063.166.076.21.02.064.03.125.035.17Z"/></svg>

After

Width:  |  Height:  |  Size: 1013 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Some files were not shown because too many files have changed in this diff Show More