Air and maritime situational awareness for isolated networks.
An operator console built to defence and security constraints: thousands of aircraft and vessel tracks on one picture, the freshness of every signal at a glance, alerts that state their evidence. It runs on the site's own network, on modest hardware.
Work in progress · synthetic data: no real aircraft or vessel is shown.

Dense, moving, partly reliable.
An operator on a long watch reads a situation that never stops changing. Three things decide whether what matters is caught in time.
Signal quality at a glance
A position from four minutes ago must never pass for a current one. Every track shows whether its signal is live, stale or lost, by its shape as well as its colour.
Alerts that earn attention
Each alert states why it fired, with its evidence. A condition must hold before it raises, so it does not flap, and a burst of similar alerts arrives as one line.
Review after the fact
When something happened, the team replays it: what was on screen, when, and what the console said about it.
Where it has to run.
The sites this console is designed for impose four constraints. Every technical choice answers one of them.
Isolated networks
Sites run on networks with no route to the internet. Map, fonts, icons and data install with the console, which talks to its own server only.
Sovereignty and security
Data stays on the site's machines. Every third-party package is a recorded decision with its licence and size, so the code to audit stays short and known.
Limited hardware
Consoles run on the machines a site already has. The picture holds thousands of moving tracks within one 60 Hz frame on a laptop GPU, measured against a budget.
Interoperability
The console sits among existing tools. It uses the formats the field knows: PMTiles for the basemap, GeoJSON for zones and exports, AIS and ADS-B as sources.
Built and running.
Screens of the running console, on 5,000 synthetic tracks over France and the Channel.



Weighed, chosen, and why.
Each key decision, with the alternatives, the choice and the constraint it answers. Each has a written record with the measurements behind it.
- 01
Drawing the map and the tracks
- Weighed
- MapLibre GL · OpenLayers · a dedicated WebGL2 renderer
- Chosen
- A dedicated WebGL2 renderer over a standard PMTiles basemap, kept after measuring both libraries against it.
- Because
- Limited hardware: at 20,000 tracks it keeps a 16.7 ms frame (p95), against 33.4 ms and 700 ms for the libraries' documented paths, and weighs 12 KB against 186 to 290 KB.
- 02
Basemap and data formats
- Weighed
- A tile server · raster tiles · project-specific files
- Chosen
- One PMTiles archive for the basemap; GeoJSON for zones, scenarios and exports; CSV for the alert log.
- Because
- One file to install on an isolated site, and formats that GDAL, QGIS and the site's own tools already read.
- 03
Getting tracks to the screen
- Weighed
- REST polling · Server-Sent Events · WebSocket with JSON
- Chosen
- One compressed WebSocket carrying compact binary records, decoded in a background worker.
- Because
- Limited hardware and links: a 5,000-track update is 160 KB against 1.9 MB as JSON, and decoding stays off the interface's thread.
- 04
Raising alerts
- Weighed
- Learned anomaly scores · explicit rules
- Chosen
- Deterministic rules — loss of signal, abnormal speed, abrupt course change, loitering, zone entry — each alert carrying its evidence.
- Because
- An operator must understand and trust why an alert fired, and an after-action review must get the same alerts from the same data.
- 05
Third-party code
- Weighed
- The usual package graph · a reviewed, recorded set
- Chosen
- Each package is a recorded decision, with its licence, size and reason, checked before every deploy.
- Because
- Sovereignty and security: a short, known list is what a site's security team can review.
- 06
Running on an isolated site
- Weighed
- A hosted service · containers pulled at install · one self-contained bundle
- Chosen
- Everything ships with the console and stays on its own origin, held there by a content-security policy; one installable image is next.
- Because
- Isolated networks: the site installs one artefact, and the console works the moment it starts.
Numbers from the build.
Every figure comes from the production build and is held by a test.
- Frame time
- 16.8 ms p955,000 moving tracks while panning and zooming: one 60 Hz frame.
- Main thread
- < 50 ms per task20,000 tracks updated every second: decoding stays in a worker.
- Update size
- 160 KBA 5,000-track update in binary records, against 1.9 MB as JSON.
- Alert rules
- 3.8 msAll five rules on 20,000 tracks, per update. Budget 4 ms.
- Alert quality
- ≥ 0.95 precision · recallAgainst the ground truth the scenario generator logs, on both scripted scenarios.
- Filters
- 0.5 msKind, source, signal, speed and altitude on 20,000 tracks, per frame.
Apple M1 · production build · Chromium · measured 2026-11-02
Built, in progress, next.
Built in the open, ticket by ticket, each decision written down as it is taken.
Built
- Live picture5,000 synthetic aircraft and vessels with live, stale and lost signals, on an offline basemap.
- Track detail and filtersEvery field of a track; filters by kind, source, signal, speed and altitude.
- AlertsFive rules with their evidence, a queue grouped by severity, acknowledgement, watched zones.
- Standard formatsPMTiles basemap read by the format authors' own readers; GeoJSON zones, scenarios and exports; CSV alert log.
In progress
- Zone drawingDraw and edit a watched zone on the map, with the mouse or the keyboard.
Next
- Real sourcesOpen AIS feeds (Finland, Norway) and ADS-B, through one adapter interface.
- ReplayRecorded sessions on the timeline, framed so they are never taken for live.
- Air-gapped bundleOne image, verified by running the test suite with networking switched off.
See it run,
on the Channel scenario.
Within three minutes: a ship swerves, a boat runs at 35 kn, a ferry goes dark inside a watched separation scheme.