airbrief/PROJECT.md
Dave Campbell 1658eda480 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.
2026-06-16 14:31:40 +00:00

5.1 KiB
Raw Blame History

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 24 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.