commit 1658eda4800df186ffc67942ce0d69afee6a717e Author: Dave Campbell Date: Tue Jun 16 14:31:40 2026 +0000 Initial commit: AirBrief MVP 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. diff --git a/PROJECT.md b/PROJECT.md new file mode 100644 index 0000000..7f837b5 --- /dev/null +++ b/PROJECT.md @@ -0,0 +1,118 @@ +# 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. diff --git a/index.html b/index.html new file mode 100644 index 0000000..a0d4299 --- /dev/null +++ b/index.html @@ -0,0 +1,809 @@ + + + + + + AirBrief + + + +
+ +
+ +
Aviation Weather · Situational Awareness
+
+ +
+ + +
+ +
+ +
+
VFR >3SM & >3000'
+
MVFR 1–3SM or 1000–3000'
+
IFR <1SM or <1000'
+
LIFR <½SM or <500'
+
+ +
+ This tool is for situational awareness only and does not constitute an official preflight weather briefing. + Pilots must obtain an official briefing before flight per FAA regulations. +
+ +
+ + +