Malaysia · God Mode

Evidence review · 15 October 2026 · KL atlas research ↗

This is a public-data evidence twin: live observations, published models and dated reference geometry. It has no calibrated physics solver, complete asset registry or official operational mandate. New surface heat, soil moisture and rainfall browse layers are in 2D Layers; transport trip comparisons are in Economy. The 3D and 2D views retain one briefing shell.

Load the searchable source register, or download its dated JSON. Official discovery: data.gov.my, DBKL, NASA GIBS.

What the source review cannot establish

No exhaustive census of public data is possible from a catalogue search. DBKL ponds, pump houses and gazetted green areas need coordinate, licence and vintage checks before map ingestion. Building heights do not establish flood clearance. Hospital points do not establish capacity. A rainfall or wind overlay does not identify a flood or smoke source. Fine-looking pixels do not increase the underlying sensor resolution.

Malaysia God Mode — National situational awareness
Research notes · credibility review · 2 October 2026

A Public Data Atlas
of the Federation

13 states and 3 federal territories. 160 district records. 32.4 million people in Census 2020. Selected public signals on one map, with historical reference layers underneath. Coverage and age vary by feed. Built by Dr Non Arkaraprasertkul as a gift to depa (Digital Economy Promotion Agency of Thailand) and the ASEAN Smart Cities Network (ASCN) 2026.

Scale
0.6°–7.6° N · 99.4°–119.5° E
Coverage
13 states + 3 territories · 160 district records · Census 2020
Feeds
Runtime feeds + dated reference layers; availability varies
Stack
Static frontend · Cloudflare Pages Functions / Workers
Languages
EN · BM · 中文

01Dr Non Arkaraprasertkul

Most important thing first: this is a gift.

Dr Non is a Thai urbanist who works on city systems — flood, mobility, air, fire, water. He has shipped dashboards for Bangkok floods (FloodDash), Chiang Mai (CNX), and Greater Kuching under the ASCN. He also keeps two personal projects — nsp-prototype (a podcast + soccer-life essay under his own name) and pirchchat (Burma monitoring).

The Malaysia project extends three boards he has already shipped. Where FloodDash ends at a basin, CNX ends at a city, and the Greater Kuching IOC ends at a state, this one ends at the federation.

"A good dashboard tells you what the room is doing right now. A great dashboard tells you what the room cannot tell you. This one does both, in three languages."

— Dr Non Arkaraprasertkul, project notes, September 2026

02Historical display examples

Historical display examples recorded in the project notes for 25 September 2026. Original response archives are not attached, so these values are not independently reproducible measurements or a verified weekly aggregate. For current values and their age, open the dashboard.

512JPS river gauges reportingpublicinfobanjir.water.gov.my
5gauges at warning level or aboveJPS Public Infobanjir
1MET warning in forceapi.data.gov.my
452public-transport vehicles liveGTFS-Realtime · Prasarana + myBAS + KTMB
7,392vessels tracked around MalaysiaAxiom Overwatch
93fire hotspots in the last source windowNASA FIRMS VIIRS
45worst PM2.5 µg/m³ (Kuching)Open-Meteo · CAMS model
4.0775USD / MYR referenceBank Negara Malaysia

What the news has been

The press panel requests Google News in EN / BM / 中文 every 10 minutes. Headlines are linked to their publishers and retain publication dates. The earlier narrative of regional stories and GDP figures had no attached sources; it is withdrawn as evidence. Read the linked reporting for current news.

An optional Facebook relay is written but not deployed — see § 06 — but it is not connected to the dashboard press panel. The panel currently uses Google News. Credentialed relays require operator authorization and a rate-limit binding.

03Mathematics

Five small maths. Nothing exotic. The dashboard earns its keep by not lying when the maths is uncertain.

3.1 Great-circle distance

The Haversine formula describes great-circle distance between latitude/longitude points. The reach bake uses an approximate local kilometre projection instead; see §3.2.

a = sin²(Δφ / 2)
  + cos(φ₁) · cos(φ₂) · sin²(Δλ / 2)
c = 2 · atan2(√a, √(1−a))
d = R · c                R = 6,371 km

Real journeys by road or river are longer. The headline always says "straight line".

3.2 Reach analysis

The formula below is conceptual. scripts/bake/analysis.py actually queries a cKDTree using an approximate local kilometre projection (longitude × 111.32 × cos latitude; latitude × 110.57), not a road network or an exact geodesic solver. It uses a 0.01° population grid, about 1.1 km at the equator. Water exposure uses a separate 0.0025° grid, about 280 m. Meta HRSL is an estimated population surface; Census 2020 district totals provide historical context, not observed people in each cell.

For every ~1 km² cell where Meta HRSL says n people live:

for each facility f ∈
  {hospitals, clinics, schools}:
  km[c, f] = haversine(c, f)
  nearest[c] = argmin_f km[c, f]
  if km[c, nearest_hospital] > 20:
    people_>20km += n
total_>20km = Σ people_>20km

3.3 Freshness grading

Observation feeds carry the reading or reference-period time. Event lists carry the upstream source-check time. These meanings are labelled separately. Age against cadence decides status:

grade(f) =
  loading   if !f.fetched
  error     if f.error
  nokey     if error matches /no .*key/
  stale     if f.obs > now + 5m
  stale     if age > 4 · cadence
  delayed   if age > cadence
  live      otherwise

A 200 OK with yesterday's numbers is not "live".

3.4 Trilingual interpolation

Bahasa forecast strings are matched against a small phrase table in feeds.js and replaced with EN or 中文 equivalents. The original phrase always backs the rain-icon lookup, so the emoji never disagrees with the displayed text.

3.5 Air quality

PM2.5 for the board’s 21 cities comes from Open-Meteo CAMS model estimates in µg/m³. The concentration display uses legacy bands at 12 / 35 / 55 / 150 µg/m³; it is not a current EPA AQI calculation. DOE MyEQMS separately supplies observed Malaysian API/IPU station indices, checked with the shared three-hour currency rule. These signals have different scales and cannot be subtracted.

3.6 Reach map (visual)

PENINSULAR MALAYSIA each cell ≈ 1 km² · Meta HRSL 30 m → 20 km
Red squares = populated cells that sit outside the 20 km straight-line radius of any mapped hospital. Peninsular Malaysia, illustrative.

04Data pipeline & diagram

Every feed runs through the same shape: fetch → normalise → redraw → grade → notify. Polling lives in core.js → poll(id, fn). When the tab is hidden, polling pauses; when it returns, every feed whose last fetch is older than its interval re-runs.

fetch(url, { headers, signal: timeout(10s) })
   ↓
JSON.parse        → feed-specific normalise()
   ↓
D.{feed}          → layer redraw (Leaflet)
   ↓
mark(id, ok, newestObservationTime)
   ↓
grade(f)          → status: live | delayed | stale | error | nokey | loading
   ↓
regrade() → re-render verdict, KPIs, tab, status pill

Selected legacy feed cadences · source register above covers additional products

FeedEndpoint↻ok ≤
JPS river gaugespublicinfobanjir.water.gov.my120 s45 m
MET warningsapi.data.gov.my300 s15 m
MET forecastapi.data.gov.my30 m36 h
USGS + MET earthquakesearthquake.usgs.gov300 s60 m
GTFS-Realtime (Prasarana, myBAS, KTMB)developer.data.gov.my20 s5 m
Aircraft (adsb.lol / OpenSky)adsb.lol30 s5 m
AIS ships (Axiom Overwatch)axiomoverwatch.io300 s45 m
Airport arrivalsopensky-network.org1 h36 h
Open-Meteo air quality (CAMS)open-meteo.com600 s2 h
RainViewer radarrainviewer.com300 s30 m
NASA FIRMS fire hotspotsfirms.modaps.eosdis.nasa.gov30 m24 h
Blitzortung lightning (PocketWorld)pocketworld.org60 s5 m
Bank Negara ratesapikijangportal.bnm.gov.my30 m4 d
OpenDOSM CPIopen.dosm.gov.my6 h100 d
JAKIM e-Solat prayer timese-solat.gov.my1 h36 h
Google News (EN / BM / 中文)news.google.com10 m24 h
Facebook Page postsgraph.facebook.com——

Reference groups include baked reach analysis, Census 2020, HIES 2019 and the separate HIES 2024 snapshot, facilities and boundaries. Their vintages remain separate. The Facebook Page endpoint is separate from the UI and requires operator authorization and rate limiting when credentials are configured. It reads content only when both FACEBOOK_PAGE_ID and FACEBOOK_PAGE_ACCESS_TOKEN are set on the server; otherwise it returns an empty array.

Pipeline diagram (text + flow)

DATA PIPELINE → CYCLE EVERY FEED FETCH1-10s timeout NORMALISEfeed-specific DRAWLeaflet layers MARKobservation time GRADElive/delayed/stale RE-GRADEon interval RE-RENDERverdict & KPIs POLLING: one run per feed interval, auto‑paused when tab hidden, resume on focus CACHE: feed-specificSee adapter source contracts
Each feed loops independently through fetch, normalization, rendering and freshness grading. The text pipeline above gives the readable sequence on smaller screens.

Feed lifecycle state diagram (text representation)

STATES: loading → error/nokey → stale → delayed → live → (grace period) → stale

Transitions happen on fetch, observation, and interval. Each feed runs in parallel.

05Facebook integration

An optional server adapter exists in api/facebook.js but is not deployed: the Pages adapter does not route /api/facebook (it returns 404), and nothing on the board calls it. Re-enabling it means adding it back to the adapter's handler list. Its legacy Graph API version is v18.0, and compatibility must be verified before configuring it. The endpoint returns the most recent 20 posts from a configured page: message, created_time, permalink_url, full_picture, plus reaction, comment, and share counts.

Configuration is two environment variables on the Cloudflare Pages project:

FACEBOOK_PAGE_ID            = 123456789
FACEBOOK_PAGE_ACCESS_TOKEN  = EAAxxxxxx...

The token is a long-lived Page access token, generated from a Facebook App with pages_read_engagement + pages_show_list scopes. Without it the endpoint returns { posts: [], note: "..." } and the dashboard continues to use Google News alone.

The front-end uses Google News independently. A successful configured Facebook response has a five-minute cache; this page does not establish that credentials, permissions or the legacy API version currently work.

Example wire shape

GET /api/facebook

200 OK
{
  "source": "Facebook Graph API",
  "configured": true,
  "posts": [
    {
      "id": "123_456",
      "message": "Today at 14:32 MYT...",
      "time": "2026-09-25T06:32:00+0000",
      "url": "https://facebook.com/...",
      "image": "https://scontent...",
      "reactions": 432,
      "comments": 41,
      "shares": 18
    }
  ]
}

Failure mode

If authorized access is allowed but the token has expired or the page is unpublished, the relay returns 424 (Failed Dependency) with error set. The press tab uses Google News independently.

06Safety & limitations

"This board is decision support, not an official warning."

The dashboard never claims it can establish that an area is safe. If Coverage is incomplete appears, the headline is honest about what it does not know. A red banner names the feed that has gone stale and the time since it last answered.

What the dashboard does not claim

  • Hospital locations are reference data. They do not confirm opening hours, available beds, or an accessible route.
  • Reach distances are straight line. Real journeys by road or river are longer.
  • Census 2020 and HIES 2019 are historical.
  • CAMS air quality is modelled. DOE API/IPU is observed at stations; neither establishes conditions at every address.
  • Ship "declared destinations" are what the ship transmits, not where it actually goes.
  • Rain radar is 10-minute frames.
  • Lightning shows the last 15 minutes of strikes that crossed Malaysia's bounding box.
  • The optional Facebook adapter requests public Page posts and aggregate reaction/comment counts, not DMs or comment bodies. It is not a current dashboard source.

What it does claim

  • If a river gauge reads DANGER within the last 45 minutes, that is the operator-reported category for that station.
  • If a MET warning is in valid_to ≥ now, it is the current authoritative text from MET Malaysia.
  • If the verdict says Not enough data, coverage is incomplete or a reading cannot be used; upstream failure and dashboard defects are both possible.

07Action queue and join logic

The question: a board that lists 1,306 gauges, 5 warnings, 293 fires and 8 KPIs has given the reader homework, not help. Nobody under a flood warning needs more numbers. They need the three places to look first, in order, with the reason attached to each.

So the briefing tab now carries an action queue. Cards still summarise one feed each; the queue joins feeds. Five joins, recomputed on every poll, each gated by the same 45-minute freshness rule as the verdict:

  1. Flood action queue. Every elevated, current gauge is scored by converging evidence — its JPS category, its trend word, rain at the station today, rain in the state forecast, a MET warning naming the state, and how many people live on low ground in its district. Top five, worst first.
  2. Climb memory. The flood loader keeps the previous poll's water levels, so a gauge climbing ≥ 0.3 m/h earns urgency even before JPS moves its category. Rise rate is measured, not guessed.
  3. Evacuation-hard zones. Districts far from help (≥ 20% of people over 20 km from a hospital, or ≥ 15 km average) while a hazard is live in their state. If this floods, help is far — that district needs local review of access and official evacuation instructions.
  4. Silent zones. Districts with ≥ 5,000 people on low ground and no live gauge watching them. The unknown, quantified, in the gaps card.
  5. Rain on high rivers. Rain falling now (capital-city precipitation ≥ 2 mm/h) onto a state whose gauges are already elevated. The model publishes a 15-minute total, so the test runs on its hourly equivalent; the board prints the total and names the window.

The scoring, in full

score = category      DANGER 100 · WARNING 60 · ALERT 30
      + rising trend              +25
      + climbing ≥ 0.3 m/h        +15
      + rain at the station       +10
      + rain in state forecast    +10
      + MET warning in state      +15
      + low-ground people nearby  +min(20, pop / 2000)

A receding DANGER keeps its category but gains no rise bonus, and carries the line falling, but still above the line — verify before standing down. Stale, disabled, invalid and UNKNOWN readings never enter the queue; they stay grey on the map.

What the queue refuses

It never claims a gauge crossed a threshold — one poll cannot see motion, only climb memory across polls can. It never forecasts an address: a nearby gauge is not a flood forecast for your street. And a silent district is reported as unknown, never as safe.

Worked example: the morning of 27 September 2026

At 11:00 MYT the relay held 1,306 stations with 503 current readings (newest 12 minutes old). Five MET warnings were in force — strong winds and rough seas naming Kelantan, Pahang, Perak, Terengganu, Sabah and Sarawak, plus thunderstorms over Kelantan, Sabah, Sarawak and Labuan. The queue ranked:

#GaugeEvidence
1Sg. Bidor di Changkat Jong, Hilir Perak — DANGER 3.92 m against a 3.5 m linerising · 1 mm at station · MET warning in Perak · 38,278 on low ground nearby
2Sg. Bernam di Jambatan SKC, Hulu Selangor — DANGER 19.21 m against 19.1 mreceding · reading 42 min old · verify before standing down
3Sg. Luit di Kg. Subuh, Maran, Pahang — WARNING, steadyMET warning in Pahang
4Sg. Galas di Limau Kasturi, Gua Musang, Kelantan — ALERT, receding25 mm at station · MET warning in Kelantan

Hilir Perak holds 141,959 people (Census 2020), 38,278 of them on low ground by rivers — and 0% live over 20 km from a hospital. So the morning's answer was specific: the danger in Perak was exposure, not distance to care. A different district with the same gauge would have ranked an evacuation-hard zone alongside it. That distinction — what kind of danger, not just where — is the whole point of the joins.

"Raw data tells you what the room is doing. Joins tell you what to do about it. If an insight cannot change someone's next hour, it does not belong on this board."

— Dr Non Arkaraprasertkul, insight-layer notes, September 2026

Method and authorship

Project notes, September 2026. The worked example is historical and its raw response archive is not supplied. Formulations are implemented in public/js/insights.js, rendered trilingually in the briefing tab, and held to account by tests/insights.test.mjs — nine tests covering ranking, evidence convergence, climb memory, zone logic, Bahasa forecast parsing, and trilingual copy coverage.

08Reach analysis (detailed)

The reach analysis is a static feed — it never changes on the interval. It identifies historical population estimates far from mapped services. It does not establish travel time, hospital capacity or personal safety.

Reach calculation details

Inputs are Meta HRSL population estimates aggregated to the baked grid and Overture facility reference locations. Census 2020 supplies the historical district comparison; it does not supply population per HRSL cell. The implemented nearest-service calculations cover hospitals, clinics and schools.

for each HRSL cell c:
  for each facility f in [hospitals, clinics, schools]:
    km[c, f] = haversine(c, f)
  nearest[c] = argmin_f km[c, f]
  if km[c, nearest_hospital] > 20:
    people_>20km += population(c)
total_>20km = Σ people_>20km

Real travel by road or river is longer than straight line. The headline says straight line because it is the fastest estimate and conservative (if even the straight line is too long, road travel is definitely too long). That conservativism is the whole point of the metric.

Visualization: the reach map

Conceptual reach analysis Population grid → nearest hospital Straight-line distance, not a route
Conceptual sequence, not a data map. Reach calculations use 0.01° aggregate cells and flag estimated populations more than 20 km from a mapped hospital; they do not use native 30 m measurements or establish a usable route.

Reach analysis metrics

  • People within 20 km: Σ population(c) for all cells where the nearest hospital ≤20 km
  • People beyond 20 km: Σ population(c) for all cells where the nearest hospital >20 km
  • Percent beyond 20 km: total_beyond / total_population × 100
  • Average distance to nearest hospital: Σ population(c) × km[c, nearest[c]] / Σ population(c) (population-weighted)
  • District reach score: no composite score is calculated; distance and population exposure remain separate

Applications in evacuation planning

The briefing flags districts with a hospital-distance gap when a current hazard names their state. This is a review priority, not an evacuation order or route assessment. Straight-line distance does not establish whether a hospital can be reached during a flood.

Data sources validation

  • HRSL grid cells: no road-density validation study is supplied; the former R² claim is unsupported.
  • Facility locations: Overture reference records; the tests check plausible counts and the Semporna location correction, not a complete official-register audit.
  • Population totals: tests require the national baked-grid total to fall within 3% of Census 2020. That reconciliation does not validate each cell or census tract.

Limitations

  • Static data ignores seasonal migration (students, workers)
  • Road network distances not calculated (approximate local kilometre projection)
  • Facility accessibility (road condition, traffic, language) not considered
  • Weather-dependent routes not factored

09Monitoring, alerts and notifications

The dashboard does not act on alerts; it displays them for human decision-making.

Alert channels

Alert triggers

Alert appears when:

Alert escalation

When an alert appears, the following additional visualizations activate:

Current categories require current readings; MET notices expire by their validity window. Missing or aged readings produce a coverage gap, not an all-clear.

10Credits & acknowledgments

English

Built by Dr Non Arkaraprasertkul as a gift to depa (Digital Economy Promotion Agency of Thailand) and the ASEAN Smart Cities Network (ASCN) 2026. Fonts: Jost by indestructible type*; Noto Sans SC. Independent demonstration. Not an official product of the Government of Malaysia.

Bahasa

Dibina oleh Dr Non Arkaraprasertkul sebagai hadiah kepada depa (Agensi Galakan Ekonomi Digital Thailand) dan Rangkaian Bandar Pintar ASEAN (ASCN) 2026. Fon: Jost oleh indestructible type*; Noto Sans SC. Demonstrasi bebas. Bukan produk rasmi Kerajaan Malaysia.

中文

由 Dr Non Arkaraprasertkul 制作,作为赠予泰国 depa(数字经济促进局)及 东盟智慧城市网络 (ASCN) 2026 的礼物。字体:Jost(indestructible type*);Noto Sans SC。独立演示项目,并非马来西亚政府官方产品。

Data attribution

License

Application code: MIT. Fonts: OFL (Jost, Noto Sans SC). Data layers retain product-specific licences and attribution. Public access alone does not establish a redistribution licence; consult the source register and provider terms. The Malaysia state outline comes from DOSM's data-open repository. This repository is private.

— end —