Skip to content

About

FX-Net NextGen is a tactical meteorological workstation providing real-time AWIPS-style weather monitoring. Features multi-pane map syncing, live NWS/SPC alerts, GOES satellite, radar, and built-in edge proxies for real-time forecasting.

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Latest commit

Β 

History

217 Commits

Folders and files

Repository files navigation

FX-Net NextGen β€” Tactical Meteorological Workstation

Tactical Meteorological Workstation & Real-Time AWIPS Web Portal
Multi-pane radar, satellite, soundings and model guidance in the browser β€” no install, no local server.

Live application Deployed on Vercel Built with MapLibre GL JS


πŸ‘¨β€πŸ’» Overview & History

Developed by Rodney Cuevas, Meteorologist, FX-Net NextGen is a modern, lightning-fast web edition of NOAA’s legendary tactical field workstation.

In the late 1990s and 2000s, NOAA’s Forecast Systems Laboratory (FSL) engineered FX-Net as a lightweight client-server system allowing Incident Meteorologists (IMETs) at remote wildfires and field forecasters to access full AWIPS capabilities over low-bandwidth connections.

FX-Net NextGen brings that exact tactical philosophy into the modern cloud era. Engineered with MapLibre GL JS, serverless edge routing, and direct government NOAA/NWS API integrations, this workstation provides forecasters with instant, synchronized multi-pane meteorological data without heavy local server requirements.


⚑ Key Features

πŸ—ΊοΈ Multi-Pane Workspace

  • 1 / 2 / 4 / 8-Pane Layouts: Split the view into independent map panes, each with its own products, radar site, and animation state.

  • Product Filter: A search box above the sidebar filters all ~145 products by name or category, auto-opening matching groups β€” no scrolling through 19 collapsed categories to find a product.

  • Workspace Tabs & Autosave: Save multiple labeled workspaces (double-click to rename, e.g. "Gulf Coast", "Severe Setup"). The whole workspace autosaves every 15 seconds and on close β€” every pane's map view, radar/satellite imagery, and overlay products (warnings, outlooks, obs, aviation…) come back exactly as you left them on reload, and the NWS Warnings state/WFO filter is remembered too. A Settings Export/Import (under ANALYSIS TOOLS) writes all saved settings β€” workspaces, procedures, filters, preferences β€” to a JSON file for backup or moving between browsers/machines.

  • Master Sync & Looping: Lock all panes to a master view to compare radar, satellite, surface fronts, and severe outlooks over the exact same region β€” with synchronized time loops that wait for every pane to preload before rolling.

  • Time-Matched Loops (AWIPS-style): Products publish at different cadences β€” radar every 5 minutes, GIBS satellite every 10, dual-pol on its own volume-scan schedule. Rather than stepping each stream by position, the loop builds a master timeline and shows every product the frame that was actually valid at that time, so a coarse stream holds instead of racing ahead. Where a stream's newest frame lags real time (satellite typically runs 30–40 minutes behind), it holds on that frame and the per-pane label reports the true valid time.

  • Keyboard Loop Control: Space play/pause Β· ←/β†’ step frames Β· Home/End oldest/newest Β· Esc stop Β· 1–8 select a pane. Arrow keys are only claimed while a loop is running, so they otherwise pan the map. Loop MODE (Forward or Rock) and DWELL (extra hold on the newest frame) are in the bottom toolbar.

  • Per-Pane Legend & Data Health: A live legend stack timestamps every active product (imagery valid time or last fetch), and a collapsible Data Health monitor groups every feed by category with red/amber/green status dots.

  • Shareable displays β€” Copy Link to This Display puts a link on the clipboard that opens your exact display (site, layers, view, every visible pane) on a colleague's screen. Nothing is stored server-side; the bundle lives in the URL fragment.

  • National mosaic is MRMS (1 km, 2-minute, quality-controlled, NCEP palette) and national loops up to 2 h step at that cadence; Level II super-res CC and ZDR (0.25 km Γ— 0.5Β°) are decoded from NOAA's public volume archive by the same function that serves Level III.

  • Loop frames are fetched once β€” a frame is a fixed moment in time, so its tiles are never re-requested when the server's cache lifetime runs out (NCEP 2 min, nowCOAST 4 min), and a failed request is retried twice before giving up. Re-requesting every frame on that timer is what used to blank loops whenever a NOAA server had a bad minute.

  • Loops cut clean β€” frame flips carry no paint transition (MapLibre's default 300 ms cross-fade is off), parked frames cost the GPU nothing, ticks are clock-scheduled, and an optional BLEND dissolve is there for those who want it.

  • Every floating panel maximizes (β€’ or double-click its title), a product that fails to load says so on its own row, and the header shows local time beside Z.

🚨 Real-Time Weather Alerts & Vector Watches

  • National Watchdog: Polls official NWS feeds every 15 seconds for rapid convective updates. A live scrolling ticker surfaces new Tornado, Severe Thunderstorm, and Flash Flood warnings.
  • High-Fidelity Watch Vectors: Integrates NOAA's REST MapServer feature service to draw county-precise polygon boundaries for Severe Thunderstorm and Tornado watches, with Impact-Based-Warning (IBW) pulse styling for Considerable/Catastrophic tags.
  • Universal Point Query: Click anywhere inside an alert to query the NWS active-alerts database and render color-coded, stacked HTML bulletins with full precautionary actions.
  • AlertViz Notifications: New Tornado, Severe Thunderstorm, and Flash Flood Warnings raise a corner toast (with an optional alert tone) so you don't have to watch the ticker. The toasts honor the Warnings state/WFO filter β€” nationwide when unfiltered, or only your selected state/office when narrowed. Warnings and Advisories/Statements are independent toggles.

πŸ“‘ Full Radar Suite

  • National Reflectivity (MRMS): Seamless CONUS base-reflectivity mosaic.
  • Single-Site Products (NCEP): Per-site Reflectivity, Base Velocity, Hydrometeor Classification, Storm Total Precip, and One-Hour Precip pinned to the latest volume scan.
  • Dual-Pol, Velocity & Storm Tracks (NODD Level III): A dependency-free, stdlib-only decoder (api/radar-l3.py, validated byte-for-byte against MetPy) renders Correlation Coefficient (CC), Differential Reflectivity (ZDR), Specific Differential Phase (KDP), and Storm Relative Velocity β€” the last derived on the fly from the super-resolution base velocity (0.25 km / 0.5Β° / 256-level) for ~8Γ— the detail of the legacy product-56 image. Products step through the lowest four elevation tilts, georeferenced as transparent PNG overlays with AWIPS-style color tables. Includes Storm Tracks (STI) with forecast positions, Meso/TVS markers (MDA) colored by strength rank, and VAD Wind Profiles (winds aloft + hodograph).
  • Storm Attributes (SCIT, national): Every NEXRAD's current storm-cell table in one pull (~700 cells across 60+ radars, 5-minute refresh) from IEM's geojson/nexrad_attr.py. Where the per-site STI answers what is this storm doing, this answers where should I be looking β€” and adds attributes the single-site table lacks: max hail size, POSH/probability of hail, VIL, and height of maximum reflectivity. Cells are colored and sized on the severe-hail ladder (1.00" severe per NWS, 2.00" significant severe per SPC), ringed white for a flagged mesocyclone, marked β–Ό for a TVS, and trailed by a 30-minute projected-position vector. Runs entirely client-side β€” no proxy function.

πŸ›°οΈ Satellite & Lightning

  • GOES-East & GOES-West, organized by sector: A per-panel SECTOR selector picks the satellite and scan area together β€” GOES-East (CONUS, Full Disk, Puerto Rico / Caribbean, Mesoscale 1 & 2) and GOES-West (PACUS, Full Disk, Hawaii, Alaska, Mesoscale 1 & 2). Eleven sectors, all 16 ABI channels on each, so the eastern Pacific can sit beside the Atlantic in a multi-pane layout.
  • One-minute mesoscale floaters: The fastest imagery GOES produces, repositioned by NWS/NHC over active hurricanes, severe outbreaks and fires. Because they roam, FX-Net derives each sector's true footprint at runtime from the imagery's world file and PNG header via an inverse geostationary projection, and zooms straight to it.
  • Sector-matched refresh: Mesoscale re-pulls every minute, CONUS/PACUS every 5, full disk every 10 β€” the rate the ABI actually scans. Each panel's legend carries the bird, the sector and that sector's exact image valid time.
  • Loopable NASA GIBS products (GeoColor, Clean IR, Red Visible, Air Mass, Dust, Fire Temp) for both birds, with smooth time-looping driven by real published frame times and full-disk coverage including the southern hemisphere.
  • Lightning: Near-real-time strike density (NLDN via nowCOAST).

πŸ“ˆ Model Guidance & MOS

  • Forecast soundings: the Skew-T panel takes an observed RAOB or a model forecast sounding from HRRR (3 km, hourly, to 48 h) or GFS (to 5 days), stepped by forecast hour and cached so scrubbing is free. The full parameter suite β€” three-parcel CAPE/CIN, effective-layer kinematics, composites and thermodynamics β€” is computed identically for both, so the balloon and the model can be compared directly at the same site. Forecast soundings are not limited to the ~57 balloon sites β€” a model has a profile at every grid point, so the location box takes any airport id (KMEM, KGPT), ZIP, city, or lat,lon, and blank uses the active pane's centre. Resolution is cheapest-first: the RAOB table, then the in-memory ASOS set, then IEM station metadata, then geocoding.
  • Model Comparison: GFS (NCEP), HRRR (NCEP 3 km), ECMWF IFS, CMC GEM (ECCC), ICON (DWD) and ECMWF AIFS β€” ECMWF's operational AI model β€” plotted together at a point for temperature, dewpoint, wind, precip or MSLP out to 7 days. The shaded band is the inter-model spread envelope, with mean and worst-case disagreement called out, because model agreement is the confidence signal rather than any single deterministic run. AIFS draws dashed so it reads apart from the physics runs. Each legend entry carries the cycle that trace came from (read from Open-Meteo's per-model meta.json, which the forecast response itself does not expose), so an hourly HRRR run is never silently compared against a six-hour-old IFS. A cycle more than three intervals stale is shown as run ? rather than printed β€” upstream metadata can freeze while the model keeps delivering, and a wrong run time is worse than none. Hovering the chart drops a crosshair readout β€” every model's value at that forecast hour plus the spread, snapped to the hour rather than interpolated, with an em dash where a model has run out of range. The panel maximizes to fill the window and re-draws on resize.
  • MOS Guidance: MDL station bulletins in their issued layout β€” parameters down the left, forecast projections across. GFS MOS (MAV), GFS Extended (MEX), LAMP (hourly-updating, usually the freshest guidance available), and NBM Short/Extended. NAM MOS is gone: NCEP ended it on 2026-11-03 12 UTC. Nearest resolves the closest ASOS to the panel centre from the loaded METAR set. There is no standalone HRRR MOS β€” LAMP is the HRRR-based station guidance, since MDL melds HRRR into its ceiling, visibility and conditional CIG/VIS elements. Its 1-hour convection and lightning rows (CP1/CC1, LP1/LC1 β€” probability and N/L/M/H potential out to 25 h) are shown alongside the aviation elements.
  • Deliberately point-based, never gridded. There is no free CORS-open gridded source for these models (NOAA IDP-GIS publishes no model layers; Unidata's THREDDS serves GFS but sends no CORS header), and browser-side GRIB decoding is precisely the AWIPS ingest burden this app avoids. A coarse-grid contour approach was built and measured first β€” it rate-limited at roughly 30 map draws per day. Point guidance costs about a thousandth of that. Both panels fetch only when opened: no polling, no map layers, no background traffic.

πŸ”₯ Severe, Fire & Hydro Guidance

  • Storm Prediction Center (SPC): Day 1–3 Convective Outlooks (categorical), Day 4–8 Severe Outlook, Day 1–2 probabilistic Tornado/Wind/Hail with significant-severe hatching, Fire Weather Outlooks Day 1–8, Mesoscale Discussions (MCDs), Local Storm Reports (LSRs), and an SPC Mesoanalysis viewer β€” the full SPC catalog (~150 parameters across 10 categories: surface, upper-air analyses from 925–300 mb with frontogenesis and jet dynamics, thermodynamics, wind shear, composite indices, multi-parameter fields, heavy rain, winter weather, fire weather, and classic/beta indices) over 11 selectable sectors. Splits into 1, 2 or 4 panes, each with its own parameter, all locked to the same sector and valid time so a comparison is of the fields rather than the clock; layout, parameters and sector persist. Panes are sized by whichever axis runs out first so none is ever clipped, and in a multi-pane layout clicking a chart enlarges it (click again to return) β€” on a 1280Γ—800 screen that is 412 px β†’ 864 px.
  • ProbSevere (CIMSS): Machine-learning storm objects colored by severe/hail/wind/tornado probability, refreshed every ~2 minutes; click a cell for the model's readout.
  • Weather Prediction Center (WPC): Surface isobars, high/low centers, coded fronts, QPF, Excessive Rainfall Outlooks (ERO), and Mesoscale Precipitation Discussions (MPDs).
    • The coded surface bulletin (codsus) is decoded in-browser into cold/warm/stationary/occluded fronts with drawn pips, troughs, and H/L centers with central pressure. Its VALID MMDDHHZ stamp β€” month, day and analysis hour, not day/hour/minute β€” drives freshness, so the legend and Data Health show when WPC cut the analysis rather than when the app last polled. The isobar file carries no time in its body, so it is aged against Last-Modified instead. Both poll every 10 minutes: the analysis is 3-hourly but lands 1–1.5 h after valid time, so its arrival is not predictable from the clock.
  • NHC-Style Discussion Popups: Click any SPC/fire-weather/tropical area to open the official text discussion for that hazard in an in-app browser.
  • Fire & Smoke / Air Quality: HMS smoke plumes, FIRMS active-fire detections, and AQI.
  • Rivers, Drought & Climate: USGS/NWS river-gauge stages, US Drought Monitor, and CPC climate outlooks.

πŸŒ€ Tropical β€” NHC, Recon & Model Guidance

The whole tropical section follows one active storm: picking a system in either storm dropdown switches guidance, trends, diagnostics, advisories, and recon together.

  • Active Storms & Cones with automatic source failover: The forecast cone, track, and coastal watches/warnings normally come from NOAA's tropical GIS service β€” which can stall for many hours (observed ~22 h behind on Jul 21 2026, still showing TD Two #5 when NHC had Bertha at #8A). Every refresh cross-checks that feed's advisory numbers against NHC's authoritative storm index; when it's behind or unreachable, FX-Net fails over to NHC's own advisory KMZ graphics (CORS-open, regenerated on intermediate advisories too), badges the source NHC DIRECT, and reverts automatically once NOAA catches up. Watch/warning segments are colored by hazard (TS Watch, TS Warning, Hurricane Watch, Hurricane Warning), and the observed past track is drawn as on NHC's cone graphic.
  • Wind Threat: NHC's 5-day chance of 34/50/64-kt winds as a map, with click-anywhere chances queried live from NOAA (not read off the generalized shapes, which are cut from 1–2 MB to ~100 KB at ~3 km, finer than the 5 km grid they're contoured from); arrival time of tropical-storm-force winds (most likely and earliest reasonable); the wind field now and at each forecast time; and the past wind swath.
  • Storm Surge: NHC's Potential Storm Surge Flooding map and Peak Storm Surge, which exist only while surge watches/warnings are up. Their badges are probed every 15 minutes with a one-line attribute query even when the layers are off, so they double as an "is the surge map out?" indicator, and the tiles re-key only when the product actually changes. The SLOSH Surge Risk maps (Category 1–5 maximum-of-maximums) are always available as reference.
  • Tide Gauges: all ~230 NOAA CO-OPS coastal gauges coloured by observed minus predicted water level (the surge / wind setup), ringed at NWS minor/moderate/major flood levels. The national inundation dashboard's two bulk files (latest obs/pred, and flood levels/peaks/next high tide, all relative to MHHW) come through vercel.json pass-through rewrites since they send no CORS header; positions and time zones come once per session from the CORS-open CO-OPS metadata API. Those files stamp each gauge in its own local clock (LST/LDT), converted with a US-DST rule, and a gauge with no reading carries its prediction time, so it is treated as offline rather than fresh. Click a gauge for a 4-day observed-vs-predicted chart with flood lines, read straight from the CO-OPS data API.
  • Sea-Surface Temperature: NASA GIBS GHRSST MUR daily SST and anomaly. One zoom-0 probe tile reads GIBS's CORS-exposed layer-time-actual header, which pins the tiles to the real analysis date and dates the key. The cursor readout decodes the paletted zoom-7 tile under the cursor through GIBS's own colormap XML, so it is exact to the 0.15 Β°C class and is not sampled from the blended canvas.
  • Official Text Products, per storm: Public Advisory (TCP), Forecast Discussion (TCD), Forecast/Advisory (TCM), and Wind Speed Probabilities (PWS), resolved through the storm's rotating AWIPS bin.
  • Hurricane Hunters (Recon): Live HDOB flight observations plotted along the aircraft track, the daily TCPOD flight schedule, and Vortex Data Messages. Flights are matched to storms by proximity (the HDOB storm field is often a CYCLONE placeholder), and an IN AIR badge shows solid green when aircraft are working your selected storm, dimmed when they're up elsewhere.
  • Model Guidance (Spaghetti): Live ATCF a-deck tracks β€” Early Cycle, Late Cycle, and GEFS ensemble members β€” plus dedicated AI/ML sub-tabs (GraphCast ensemble mean, the only AI track model NHC currently distributes publicly; neural-net intensity consensus; and the wider AI suite wired for when it reaches public decks). Each aid plots from the most recent cycle that actually holds a track, not simply its newest cycle β€” a model whose latest run is a single hour-zero stub falls back rather than disappearing, which is routine once a tracker starts losing a weak system. Anything drawn from an older run is stamped with its lag (GDMI ✦ -18h) against the newest cycle in the deck. ATCF's previous-run interpolations (the ?2 aids) fill in only where their 6-hour counterpart is missing, so they never double a line. An empty tab says which cause it is β€” the aid is not in NHC's public deck, or it is there but carrying no track.
  • ECMWF tracks direct from ECMWF open data: AIFS (ECMWF's AI model) in the Late Cycle AI view, plus 51-member AIFS ENS and IFS ENS spaghetti views, none of which are in NHC's public a-deck. ECMWF publishes them as BUFR (WMO template 3 16 082, one message per storm, members as compressed subsets). A general BUFR library takes ~25 s for an ensemble file, so api/_ecmwf_tracks.py decodes just that template with the standard library: it reads each message's header, skips every other storm and decodes the one asked for in ~0.03 s. It matched pybufrkit on every value of 2,882 tracks. Output is a-deck text with its own tech IDs (AIFS, AF00–AF50/AFMN, XE00–XE50/XEMN; member 51 is ECMWF's control, 52 the deterministic run), so the existing a-deck parser, run labels and popups handle it unchanged. Tracks Β© ECMWF, CC BY 4.0.
  • Intensity Guidance & Trends: Early/Late cycle intensity charts, Storm Trends (observed intensity history from best track plus recon fixes), and Forecast History β€” every past advisory's official forecast track overlaid on the storm's actual traveled path. Each run has its own color and label; the key lets you isolate, pin or play through the runs, and Trend marks where each run put the center at one valid time, with the shift from run to run.
  • Environment / RI (SHIPS): SHIPS environmental diagnostics folded together with CIRA rapid-intensification and decapitation guidance.
  • Tropical Weather Outlooks: Atlantic and East Pacific TWO areas and discussion text, with NHC's X on existing disturbances (colored by 2-day chance) and the development-motion arrow.

🌐 Observations, Soundings & Tools

  • Aviation Weather (AWC): SIGMETs/AIRMETs, Graphical AIRMETs (G-AIRMET) hazard areas, Pilot Reports (PIREPs), Center Weather Advisories (CWA), and Terminal Forecasts (TAF) plotted by prevailing flight category (VFR/MVFR/IFR/LIFR) β€” click any for detail.

  • Surface & Marine Observations, Forecast Grids: Real-time METAR plotting (temperature, dew point, pressure, wind barbs) with a six-field objective surface analysis, NDBC marine buoys (~700 coastal/offshore stations), plus the NDFD surface-temperature forecast grid.

    • Analysed fields: isobars (2 mb), isotherms (2Β°F), isodrosotherms (2Β°F), relative humidity (10%), isotachs (5 kt) and apparent temperature (4Β°F), all contoured in-browser from the live METAR set and refreshed on the observation cycle.
    • Isobars use true MSLP only and never reconstruct it from the altimeter setting. The two reduce to sea level through the standard and the observed atmosphere respectively, and differ by ~2.9 mb on average β€” more than the contour interval β€” reaching 20 mb over high terrain. Stations omit MSLP exactly where the reduction stops being meaningful, so that omission is honoured rather than papered over.
    • Observations older than 90 minutes are excluded (the feed serves each station's last report, which for an offline site can be days stale), quality control judges each ob against its neighbours' median rather than the national spread so genuine extremes survive, and contours terminate where the observations do instead of being extrapolated over open ocean.
  • Interactive Skew-T (NSHARP-lite): A full radiosonde sounding for the site nearest the pane β€” high-resolution BUFR profile (thousands of levels) with standard-RAOB fallback, a lifted surface parcel with shaded CAPE on a real skew-T/log-P grid, wind barbs, and a 0–10 km hodograph. All thermodynamics run in-browser (~4 ms, no network calls):

    • Three parcels side by side β€” surface (SB), lowest-100 hPa mixed-layer (ML) and most-unstable (MU) β€” each with CAPE, CIN, LCL, LFC, EL and LI, all virtual-temperature corrected. MU is what finds elevated instability that a surface parcel reports as zero.
    • Effective-layer kinematics β€” the effective inflow layer (Thompson et al. 2007: parcels with CAPE β‰₯ 100 J/kg and CIN β‰₯ βˆ’250 J/kg), effective SRH, effective bulk shear, and Bunkers right-mover storm motion, with fixed 0–1/0–3 km SRH and 0–1/0–6 km shear shown alongside.
    • Composites β€” significant tornado (STP) and supercell (SCP), both on the effective layer.
    • Thermodynamics β€” PWAT, DCAPE, 0–3 km and 700–500 mb lapse rates, freezing and βˆ’20 Β°C levels, and wet-bulb zero by Normand's construction.

    The kinematics are verified against analytic cases: a semicircle hodograph returns Ο€RΒ² exactly, a straight-line hodograph with storm motion on the line returns 0, and Bunkers deviates exactly 7.5 m/s.

  • Solar Tools: Day/Night terminator with a click-anywhere solar calculator (sunrise/sunset, twilight, solar noon, day length, declination).

  • Analysis Tools: Distance/bearing measure, site range rings, and a storm-motion/ETA tool.

  • Procedures: Save the current multi-pane display β€” layout, per-pane view, imagery, and overlays β€” as a named bundle and reload it in one click.

  • NWS Text Products: A Text Browser for any WFO or national center (with product history), and a Forecast Meteogram charting the NWS hourly forecast for any point.

  • Built-in Documentation: A full-screen User Guide with table of contents and live search, plus a What's New changelog in the sidebar that surfaces each release once.


πŸš€ Cloud Deployment (Vercel)

This project is configured for instant cloud hosting on Vercel with no managed backend:

  • Edge Rewrites (vercel.json): Bypass strict CORS on government servers by proxying NOAA/NWS/Aviation Weather Center endpoints at the global edge.
  • Serverless Python (api/) β€” two function bundles, not one per feed. Vercel builds a separate bundle for every file in api/ and its Python runtime installs the root requirements.txt into all of them with no tree-shaking, so eight stdlib-only feeds were each carrying ~45 MB of numpy and Pillow they never imported. Everything except the radar decoder now routes through a single entrypoint:
    • proxy.py β€” the only entrypoint for the eight dependency-free feeds. vercel.json rewrites each public path to /api/proxy?__fn=<feed>, so the URLs the frontend calls are unchanged, and the feed modules beside it (_adeck.py, _raob.py, …) keep their own parsing, caching and error handling. A leading underscore is how Vercel is told a file in api/ is a helper rather than a route. Feeds are imported lazily, so a cold start loads only the one being asked for.
    • radar-l3.py β€” the one function that genuinely needs numpy and Pillow, so it stays in its own bundle with its own 2 GB memory ceiling. Decodes NEXRAD Level III (NODD) dual-pol, storm-relative velocity, storm tracks & VAD to georeferenced PNGs/GeoJSON (stdlib + numpy/Pillow only; no MetPy).
    • _adeck.py β€” the tropical workhorse. Proxies ATCF decks and NHC indexes that send no CORS headers: a-deck model guidance (?id=), the run-to-run official forecast history (?fcst=), best track (?btk=), SHIPS (?ships=), CIRA RI guidance (?rip=), the active-storm index with AWIPS bins (?nhc=/?list=), and the NHC advisory-graphics KMZ fetch-and-unzip backstop (?gis=).
    • _raob.py β€” fetches the high-resolution BUFR radiosonde profile (University of Wyoming) with a decoded-RAOB fallback for the interactive Skew-T.
    • _spc_fire_wx.py, _wpc_ero.py β€” convert SPC/WPC KMZ products to GeoJSON on the fly (stdlib KML parser with XXE guards).
    • _wpc_mpd.py β€” builds the active WPC MPDs as GeoJSON from IEM's zipped-shapefile archive (stdlib shapefile/DBF reader).
    • _probsevere.py β€” locates and serves the newest CIMSS ProbSevere storm-object GeoJSON.
    • _drought_monitor.py, _gibs_times.py β€” drought GeoJSON and live satellite frame-time discovery. USDM ships ~268k points at 14 decimal places (28 MB); the function rounds to 4 (~11 m, well under a pixel at the zooms this is drawn at), drops the three properties the client never reads, and returns ~5 MB.
  • Edge-proxied feeds β€” SIGMET/AIRMET, G-AIRMET, PIREP, TAF, CWA, METAR, NDBC, WPC isobars/fronts, and the NHC Tropical Weather Outlooks are pass-through vercel.json rewrites rather than functions, adding the CORS headers those government servers omit while staying under Vercel Hobby's 12-function ceiling.

πŸ”’ Hardening

  • Strict Content-Security-Policy β€” script-src 'self' and nothing else: no 'unsafe-inline', no CDN origins. Every script the page runs is served from its own origin (MapLibre, Lucide and the Speed Insights client are vendored and pinned), so an injected inline handler arriving through a malformed or compromised upstream feed cannot execute and no third-party origin can be tricked into supplying code. The policy is mirrored byte-for-byte in server.py so violations surface in local development rather than first appearing in production.
  • Feed text is never markup. A single esc() helper wraps every value that reaches innerHTML β€” alert text, LSR remarks, gauge and storm names, product labels, the diagnostic log β€” and feed-supplied links render only when they are genuine https URLs.
  • Keyboard-operable product browser. Every product row is a real button to assistive technology (role, tabindex, aria-pressed, visible focus), every category is a real heading that doubles as its group toggle, every form control is named, and the app honours prefers-reduced-motion. Press ? for the shortcut sheet.
  • Polite in the background. Refresh timers pause while the browser tab is hidden and catch up in one pass when it is shown again.
  • Vendored dependencies β€” MapLibre GL JS (5.24.0) and Lucide are pinned and self-hosted (vendor/), so a CDN outage or a mutated @latest release can neither break nor tamper with the app.
  • Feed text is escaped everywhere it reaches a popup or panel; upstream data is never trusted as markup.
  • Every network call has a deadline, so a hung government endpoint can't leave requests pending indefinitely or stack repeats behind itself; fast pollers are additionally guarded against overlapping themselves.
  • Proxies validate their inputs β€” storm IDs, station codes, radar products and satellite layers are pattern-matched or allow-listed and numeric parameters clamped before they reach a URL. Upstream failures are logged server-side and returned to the browser generically, so internal URLs and paths never appear in a client response. Every function answers HEAD, so uptime monitors see the API as up.
  • Nothing ships that the page doesn't use. .vercelignore keeps the dev server, tests, CI config and README out of the deployment.
  • A commit is checked before it can deploy. A GitHub Action syntax-checks every script and Vercel function and runs the unit tests on each push (.github/workflows/ci.yml).

πŸ’» Local Development

To run the workstation locally on your macOS or Linux machine with full functionality:

# 1. Clone the repository
git clone https://github.com/Cuevman81/FX-Net-NextGen.git
cd FX-Net-NextGen

# 2. Install the two binary dependencies the Level III radar decoder needs
pip3 install -r requirements.txt

# 3. Start the local Python proxy server (Port 8888)
python3 server.py

Open your browser and navigate to http://localhost:8888.

server.py mirrors the production routing β€” it runs the same api/*.py handlers, applies the same vercel.json pass-through proxies, and sends the same Content-Security-Policy β€” so what works locally is what deploys. Everything except the Level III and Level II radar products (all served by api/radar-l3.py) works without the two dependencies above; the rest of the app is stdlib-only.

πŸ§ͺ Tests

node --test tests/*.test.js

No dependencies β€” Node's built-in runner. The suites read the functions they exercise straight out of app.js (see tests/_load.js), so they test the shipped code rather than a copy of it: tropical-guidance cycle selection and fallback (adeck.test.js), the hidden-tab poller pause (visibility-pause.test.js), feed-text escaping plus the https-only link guard (escape.test.js), the shareable-display-link codec (share-link.test.js), the severe-hail ladder (hail-ladder.test.js), loop-frame fetch-once and retry (loop-frames.test.js), the storm-surge issue/re-tile/withdraw cycle plus the outlook arrow geometry (nhc-impacts.test.js), tide-gauge clock conversion, flood categories and the SST colormap readout (tides-ocean.test.js), NHC forecast-history run colors, interpolated trend positions and run-to-run shifts (fcst-history.test.js), the recon vortex-fix decoder, Storm Trends' recon-aware refresh and the center-fix map layer (storm-trends.test.js), which wind and surge layers draw for the selected storm (storm-scope.test.js), the MOS text-size steps (mos-font.test.js), zone-outline simplification and the unchanged-cycle check behind the warning watchdog (warnings-watchdog.test.js); the ECMWF BUFR decoder runs as Python unittest against real fixtures (tests/test_ecmwf_tracks.py). The same suite runs in CI on every push.


πŸ“„ Legal & Disclaimer

Terminology, data feeds, and acronyms (AWIPS, FX-Net, WPC, SPC, NHC, METAR) are public domain properties of the United States Government (NOAA / National Weather Service) pursuant to 17 U.S.C. Β§ 105.

Released under the MIT License.

Designed and maintained as an independent professional forecasting tool by Rodney Cuevas.

About

FX-Net NextGen is a tactical meteorological workstation providing real-time AWIPS-style weather monitoring. Features multi-pane map syncing, live NWS/SPC alerts, GOES satellite, radar, and built-in edge proxies for real-time forecasting.

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages