Airport lookup and route weather strip. Pulls from aviationweather.gov with no API key. Decodes METAR/TAF client-side. Hosted at rockcampbell.com/airbrief via nginx proxy on rocklab.
118 lines
5.1 KiB
Markdown
118 lines
5.1 KiB
Markdown
# AirBrief — Project Status
|
||
*Last updated: June 16, 2026*
|
||
|
||
---
|
||
|
||
## What It Is
|
||
|
||
A static web app for business aviation situational awareness — specifically built for Airshare line pilots and flight control. Not a certified briefing replacement. Gives a fast, clean weather picture before the official brief happens.
|
||
|
||
**Live at:** rockcampbell.com/airbrief
|
||
|
||
**Target users:**
|
||
- Line pilot at KMKC with 2–4 legs today, needs a 90-second weather picture
|
||
- Flight control building the day's operation, wants to flag potential weather disruptions
|
||
|
||
---
|
||
|
||
## Current State (MVP Complete)
|
||
|
||
### Airport Lookup (single ICAO/IATA)
|
||
Type one airport ID → full detail view:
|
||
- Flight category badge (VFR / MVFR / IFR / LIFR), color coded
|
||
- Wind, visibility, ceiling, altimeter (inHg — Kollsman window value), temp/dewpoint
|
||
- Sky conditions (tagged)
|
||
- Present weather decoded to plain English
|
||
- METAR: plain-English paragraph + raw text
|
||
- TAF: plain-English per change group (Initial / From / Temporary / Becoming / Probability) + raw text
|
||
|
||
### Route Weather (multiple space-separated IDs)
|
||
Type `KMKC KSTL KDEN` → route view:
|
||
- Flight category strip: colored badges per airport with visibility and ceiling
|
||
- Per-airport detail cards: wind, vis, ceiling, altimeter, temp/dewpoint, plain-English summary, obs time
|
||
- Active hazard summary: SIGMETs and AIRMETs filtered to the route bounding box, sorted by severity (convective SIGMETs first)
|
||
|
||
---
|
||
|
||
## Tech Stack
|
||
|
||
| Layer | Choice | Notes |
|
||
|---|---|---|
|
||
| Frontend | Vanilla HTML/CSS/JS | Single file, no framework, no build step |
|
||
| Weather data | aviationweather.gov public API | No key, no cost, no rate limit |
|
||
| Hazard data | aviationweather.gov `/airsigmet` | Same API, returns SIGMETs + AIRMETs |
|
||
| METAR/TAF decode | Client-side JS | No third-party decoder — all done in-browser |
|
||
| Hosting | hugo-site nginx container on rocklab | Static file served directly from disk |
|
||
| CORS proxy | Nginx location `/airbrief-api/` | aviationweather.gov doesn't send CORS headers; nginx proxies server-side |
|
||
|
||
---
|
||
|
||
## File Locations
|
||
|
||
```
|
||
/home/rock/airbrief/
|
||
├── index.html ← entire app (single file)
|
||
└── PROJECT.md ← this file
|
||
```
|
||
|
||
**Nginx proxy config:** `/home/rock/docker/rockcampbell/nginx.conf`
|
||
- `/airbrief` → serves `/srv/airbrief/` (the airbrief directory)
|
||
- `/airbrief-api/` → proxies to `https://aviationweather.gov/api/data/`
|
||
|
||
**Docker volume mount:** `/home/rock/docker/rockcampbell/docker-compose.yml`
|
||
- `/home/rock/airbrief:/srv/airbrief:ro`
|
||
|
||
Changes to `index.html` go live immediately — no container restart needed.
|
||
|
||
---
|
||
|
||
## API Endpoints in Use
|
||
|
||
All routed through the local proxy at `/airbrief-api/`:
|
||
|
||
| Endpoint | Used for |
|
||
|---|---|
|
||
| `/metar?ids=KMKC&format=json&hours=2` | METAR for one or multiple airports (comma-separated) |
|
||
| `/taf?ids=KMKC&format=json` | TAF including structured `fcsts` array |
|
||
| `/airsigmet?format=json` | All active SIGMETs and AIRMETs |
|
||
|
||
**Key API field notes:**
|
||
- `fltCat` (capital C) — flight category; computed from ceiling/vis as fallback
|
||
- `altim` — in **hPa**, not inHg. Divide by 33.8639 to get the Kollsman window value
|
||
- `visib` — string, may return `"10+"` rather than a number
|
||
- `clouds[]` — array of `{cover, base, type}` objects; base in feet
|
||
|
||
---
|
||
|
||
## Hazard Filtering
|
||
|
||
When displaying route hazards, the app builds a bounding box from the lat/lon of all found airports (±3 degrees padding) and filters the SIGMET/AIRMET list to hazards whose coordinates overlap that box. Hazards with no coordinate data are included.
|
||
|
||
Sort order: convective SIGMETs → other SIGMETs → AIRMETs.
|
||
Color: red = convective SIGMET, orange = other SIGMET or severe turb/ice, yellow = AIRMET.
|
||
|
||
---
|
||
|
||
## v2 Backlog (do not build until David returns to this)
|
||
|
||
From the original project brief — in priority order:
|
||
|
||
1. **Winds Aloft by waypoint** — enter cruise altitude (FL350, FL410), get forecast winds and temps at each route waypoint. API: `/windtemp?format=json`
|
||
2. **Flight Category Map** — Leaflet.js map centered on the route, stations color-coded by flight category, route corridor overlay. Deferred because Turf.js route geometry math was saved for post-MVP.
|
||
3. **PIREPs near route** — pilot reports filtered to the route corridor. API: `/pirep?format=json`
|
||
4. **TFRs** — active temporary flight restrictions. API: `/tfr?format=json` (different response format from airsigmet)
|
||
5. **Multi-leg trip view** — full day's operation across multiple aircraft
|
||
6. **Saved routes / push alerts**
|
||
7. **Radar layer** on the map
|
||
8. **Mobile PWA** (offline-capable)
|
||
9. **Integration with Airshare/Horizon trip data**
|
||
|
||
---
|
||
|
||
## Known Notes / Gotchas
|
||
|
||
- The `airsigmet` endpoint returns ~2,000 records nationally. Bounding box filtering cuts this down significantly for regional routes. For very short routes the box is small; for cross-country the box is large and more hazards show.
|
||
- TAF not always available for smaller airports (returns empty array — handled gracefully).
|
||
- IATA identifiers (e.g., `MKC`) work in addition to ICAO (`KMKC`).
|
||
- Route input accepts space, comma, or slash as separators.
|
||
- The disclaimer is required on every page per the original brief.
|