Sam Poplett

This page plays by itself. Scroll to take over.

Back to the seven projects

Every dot has a receipt

How I built a live globe of open data that says how it knows. Provenance is live, and its code is open.

Sam Poplett provenance-online.com github.com/011-sam-110/Provenance

92 stars and 15 forks on GitHub on 8 October 2026.

A comic panel: the astronaut stands beside a large globe covered with dots. A thread runs from each dot to a paper tag. The astronaut reads a long paper receipt from a small printer.

The problem

Governments and agencies publish live data for free. A road authority publishes its camera pictures. A geological survey publishes each earthquake as a record.

The data is public, and most of it comes in formats that few people can read. An earthquake arrives as a block of JSON: a magnitude, a place name, a time as one long number and a set of coordinates.

Map products add a second problem. They rarely say where a point came from.

One rule

I set one rule for the build. The map shows nothing that the source did not send.

When a source fails, its layer shows an empty set or its last good data. It does not show invented data.

The rule has a cost that a visitor can see. A layer can be blank. On 14 September 2026 the satellite layer returned 0, and the README says so.

The file lib/sources/registry.ts The last good cameras of each feed.

The Provenance console: a dark world map covered in clustered dots of cameras and events.
The console at /app, world view.

What I built

The centre is one MapLibre globe that flattens into a map as you zoom. Each source has one adapter and one entry in a registry.

Camera pictures and video reach the browser through a closed proxy. The proxy has a list of allowed hosts, and a new source is one new rule.

Analysts get a console at the address /app, with widgets, presets and layouts that they can share as a link.

The file lib/proxy/allowlist.ts The list of allowed hosts.

The Provenance landing page. A dark globe with teal cable lines and coloured dots sits behind the headline 'You already paid for this.'
The landing page.

A card on every layer

Every layer carries a card. The card names the publisher, the method, a confidence class and a limitation. The limitation says what the layer cannot tell you.

The card is a rule in the code. A unit test fails the build when a layer has no limitation, and also when a limitation is 40 characters or shorter.

The file tests/unit/signals-explain.test.ts The test that fails the build.

A dark page headed 'Every dot has a receipt.' A block of raw earthquake JSON from the United States Geological Survey points with an arrow to a panel.
A raw earthquake record beside the pin that it becomes.

A count that would not hold still

On 18 August 2026 I read the camera count four times, 70 seconds apart. The answers were 12,866, 13,066, 13,266 and 12,866.

The cause was the hosting. Each serverless instance kept its own copy of the camera cache, and each request reached a different instance.

I moved production to one Node process. On 14 September 2026 three reads 75 seconds apart returned the same 20,011.

The file deploy/provenance.service The one process.

What is open

The README states the open issues with their date. On 14 September 2026 the satellite layer was at 0, and the aircraft layer was a capped sample of 3,000.

Each figure on this page is from the day beside it. The README holds the newest check.

The file README.md The production check, with its date.

A camera page titled 'A406 Billet Upass E'. A road camera still sits above a table of source, location, coordinates, status and refresh time.
One camera page. The still is from TfL Open Data.

The figures, each with its date

  • provenance-online.com answered with status 200. I read the status code only.
  • 92 stars and 15 forks on GitHub.
  • 405 unit test files at commit e1efc15.
  • The test tool listed 4,264 unit tests in 403 files. The count lists the suite. It does not run it.
  • Production returned 20,011 cameras, 19,827 of them online. 16 of 17 feeds answered.
  • The satellite layer returned 0. The README calls the cause not diagnosed yet.