Skip to content
Status: Live

Typhoon Replay

Replay any typhoon that hit the Philippines or Japan since 1940, hour by hour, from the best track and ERA5 reanalysis.

Typhoon Replay's home page: a map of the Philippines and the South China Sea with the 2013 track of Typhoon Haiyan (Yolanda) as a dotted line, a blue ERA5 wind field around the storm centre, and a play button and timeline below; beside it, the heading “Replay any typhoon, hour by hour” and a storm search box, in its light theme.Typhoon Replay's home page: a map of the Philippines and the South China Sea with the 2013 track of Typhoon Haiyan (Yolanda) as a dotted line, a blue ERA5 wind field around the storm centre, and a play button and timeline below; beside it, the heading “Replay any typhoon, hour by hour” and a storm search box, in its dark theme.
Haiyan (Yolanda), 2013, approaching the Philippines. Captured from the live site.

Problem

The history of a typhoon is split across two very different datasets. Best tracks give the centre position and intensity every few hours. Reanalysis gives the wind and rain over the whole region, every hour, but as terabytes of gridded data. Most public tools show one or the other, or only recent seasons, and none answer “which storms hit my town, and how hard?” for both the Philippines and Japan.

Approach

  • Tracks: IBTrACS v04r01, Western Pacific basin: about 3,000 storms since 1940. PAGASA local names (Yolanda, Odette) are not in IBTrACS, so a sourced name crosswalk joins them.
  • Fields: ERA5 hourly reanalysis (about 28 km grid, from 1940), read from the public cloud copies without an account. ERA5 is CC BY 4.0: contains modified Copernicus Climate Change Service information.
  • Pipeline: scheduled GitHub Actions jobs cut a storm-following window for each hour and compress wind, gust, pressure and rain into small WebP frames per storm: lossy sheets for drawing the hourly animation, and lossless sheets every third hour that keep exact values for the readouts. The same jobs build per-municipality exposure tables as partitioned Parquet.
  • Replay: a static web app animates the frames on a MapLibre map with the best track, drawing the field and wind particles in a custom WebGL2 layer, in English and Japanese. The timeline table is the text alternative to the map.
  • One contract, four backends: the dynamic parts (search, compare, exposure queries) are specified once in OpenAPI and implemented four times, in Java (Spring Boot), Node, Rust and Go. Each backend passes the same contract tests and can be swapped in behind the same front end.
  • Honesty about the data: reanalysis smooths the eyewall of intense typhoons, so the replay labels the field as “reanalysis context” and shows the best-track intensity beside it.

Architecture

Standard pattern: a static-first single-page app over a contract-first API. Customisations: one origin and four engines, so a same-origin proxy routes /api/{java,node,rust,go}/ to four interchangeable backends that share one PostGIS database; the heavy data is precomputed by scheduled jobs and read straight from a Hugging Face dataset, so the replay itself needs no backend.

  1. 01 · Sources

    • IBTrACS best tracks (NOAA NCEI)
    • ERA5 hourly reanalysis (public buckets)
    • PAGASA name crosswalk
  2. 02 · Pipeline

    • GitHub Actions matrix
    • Storm-following windows, hourly
    • WebP frames, data-quality tests
  3. 03 · Artefacts

    • WebP frames per storm (Hugging Face dataset)
    • Exposure tables (Parquet)
    • Storm index (JSON)
  4. 04 · Serving

    • Static replay on Cloudflare Pages
    • OpenAPI contract
    • Java · Node · Rust · Go backends
Typhoon Replay data flow. Dashed boxes are external open datasets; the outlined box is what visitors use.

Where it stands

Live at typhoon.krtmtthw.dev, in English and Japanese. 51 storms are fully replayable, with their ERA5 fields; the rest of the 2,058-storm catalogue is being backfilled.

The Java backend (Spring Boot) is live, implements the shared contract and is tested against it; the “Under the hood” page in the app shows it at work. Next: the Go, Node and Rust backends, against the same contract tests.

Known limitation: ERA5 understates the winds in the cores of intense typhoons, which is why the field is labelled as reanalysis and the official best-track intensity is always shown beside it.