Build a Flight Tracker with MyRadar Weather
Build a flight tracker on a MyRadar weather map: enter a flight number, follow the flight over radar and weather overlays, and show its route, progress and landing time.
Oct 13, 2026 · Shell · HTML · TypeScript

In this walkthrough you'll build a flight tracker on a MyRadar weather map: enter a flight number
and follow the flight live over radar and lightning. It covers only the calls that matter. For a
fuller app to run and read, see the flight tracker sample,
web-demo, which the
quickstart below starts from the command line.
You'll need: Node.js 20.19 or newer, a MyRadar API key and a Mapbox access token (see Requirements).
Quickstart (command line)#
To see the finished sample running before you build your own, these commands
clone it, install it, write your keys to .env.local and start the dev server.
You need Node.js 20.19 or later; replace
your-myradar-api-key and pk.your-mapbox-token.
export MYRADAR_API_KEY=your-myradar-api-key
export MAPBOX_TOKEN=pk.your-mapbox-token
git clone https://github.com/MyRadar/MyRadar-SDK-Samples.git
cd MyRadar-SDK-Samples/web-demo
npm install
printf 'VITE_MYRADAR_API_KEY=%s\nVITE_MAPBOX_TOKEN=%s\n' "$MYRADAR_API_KEY" "$MAPBOX_TOKEN" > .env.local
npm run devThen open http://localhost:5173.
.env.local is git-ignored. Restart npm run dev after changing it.
1. Set up the project#
Create a Vite and TypeScript project with mapbox-gl and the two MyRadar packages:
npm create vite@latest flight-tracker -- --template vanilla-ts --no-interactive
cd flight-tracker
npm install @myradar/mapbox @myradar/controls mapbox-glPut your keys in .env.local (git-ignored by Vite's template):
VITE_MYRADAR_API_KEY=your-myradar-api-key
VITE_MAPBOX_TOKEN=pk.your-mapbox-tokenIn index.html, replace <div id="app"></div> with a search form, the map and a card for the
flight:
<form id="search"><input name="q" placeholder="Flight number, e.g. UA 1" /><button>Track</button></form>
<div id="map" style="height: 600px"></div>
<div id="flight"></div>
<div id="layers"></div>
<div id="timeline"></div>Then replace src/main.ts with the imports and your keys; the steps below add to it:
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
import { HurricanesLayer, LightningLayer, RadarLayer, firstSymbolLayerId, showFlight, type FlightInfo, type FlightLayer } from '@myradar/mapbox';
import { LayerControl, TimeSlider, weatherLayerItems } from '@myradar/controls';
mapboxgl.accessToken = import.meta.env.VITE_MAPBOX_TOKEN;
const apiKey = import.meta.env.VITE_MYRADAR_API_KEY;Run npm run dev and keep it running while you build.
2. Show live radar#
Add a RadarLayer under the map's labels, so place names stay readable:
const map = new mapboxgl.Map({ container: 'map', style: 'mapbox://styles/mapbox/dark-v11', center: [-93.5, 41.5], zoom: 5, projection: 'mercator' });
const radar = new RadarLayer({ apiKey });
map.on('style.load', () => map.addLayer(radar, firstSymbolLayerId(map)));
3. Add weather overlays and controls#
Replace the style.load handler with one that adds the overlays too; attachRadar keeps
lightning in step with the loop. LayerControl and TimeSlider from @myradar/controls give
each layer a switch and the loop a play button and scrubber:
const lightning = new LightningLayer({ apiKey });
const hurricanes = new HurricanesLayer({ apiKey });
lightning.attachRadar(radar);
map.on('style.load', () => {
const labels = firstSymbolLayerId(map);
map.addLayer(radar, labels);
hurricanes.addTo(map, { beforeId: labels });
lightning.addTo(map, { beforeId: labels });
});
new LayerControl({ items: weatherLayerItems({ radar, hurricanes, lightning }), theme: 'light', panel: false }).addTo('#layers');
new TimeSlider({ radar, theme: 'light', panel: false }).addTo('#timeline');Watches and warnings (WarningsLayer) and wind (WindLayer) work the same way.

4. Show a flight#
One call shows a flight. showFlight looks the flight up through the MyRadar API gateway with
your key, draws it above the weather, centers the map on the aircraft with the whole trip in view, and updates it every minute until it
lands:
const form = document.querySelector<HTMLFormElement>('#search')!;
const card = document.getElementById('flight')!;
let flight: FlightLayer | null = null;
form.addEventListener('submit', (e) => {
e.preventDefault();
const query = new FormData(form).get('q')!.toString().trim();
flight?.remove(); // one flight at a time
flight = showFlight(map, query, { apiKey });
flight.on('data', ({ flight }) => renderCard(flight));
flight.on('error', ({ error }) => (card.textContent = `Couldn't show ${query}: ${error.message}`));
});It accepts a flight number (UA 1, AA 1643) or a callsign (UAL1). When a number has several
departures, it shows the one in the air, otherwise the latest landing, otherwise the next one
scheduled. The map shows the planned route, the track flown, the route ahead, both airports and
the aircraft; over oceans the aircraft is drawn hollow while its position is an estimate.
Options turn parts off, for example { apiKey, plannedRoute: false }, or draw your own aircraft
image, nose up: { apiKey, aircraftIcon: planeUrl, aircraftIconSize: 64 }.

5. Fill in the flight card#
Each data event carries a FlightInfo, so the card needs no calculations of its own:
function renderCard(f: FlightInfo): void {
const lands = (f.actualArrival ?? f.estimatedArrival)?.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' }) ?? '—';
const altitude = f.airborne && f.position?.altitudeFt ? ` · ${f.position.altitudeFt.toLocaleString()} ft` : '';
const progress = f.landed ? 100 : Math.round((f.progress ?? 0) * 100);
card.textContent = `${f.ident}: ${f.origin?.city} to ${f.destination?.city} · ${f.status} · ${progress}% of the way · lands ${lands}${altitude}`;
}FlightInfo also has the scheduled and actual times, the aircraft type and registration, and
the position's speed and heading for a fuller card. Write the details with textContent, never
as HTML. That's the complete app: enter UA 1 and press Track.
6. Ship it#
npm run build writes a static site to dist/. No proxy is needed: weather and flights both come
from the MyRadar API gateway, which allows calls from any website. Both keys end up in the
browser bundle, so restrict the Mapbox token to your domains and use a MyRadar key issued for
this site, and keep the MyRadar and Mapbox credits visible in the map's attribution line.