spb/earth-now Public License
earth-now.co — real-time planetary dashboard: live world metrics modeled, not streamed.
TypeScript 93%
Shell 2.3%
SQL 1.4%
JavaScript 1.3%
Dockerfile 1.2%
CSS 0.8%
1# 🌍 earth-now.co — La planète en direct / The planet, live23<p align="center">4 <a href="https://www.earth-now.co"><img src="https://img.shields.io/badge/live-www.earth--now.co-2a78d6?style=flat-square" alt="Live site"></a>5 <a href="https://github.com/spboucher-ai/earth-now/actions/workflows/ci.yml"><img src="https://github.com/spboucher-ai/earth-now/actions/workflows/ci.yml/badge.svg?branch=main" alt="CI"></a>6 <img src="https://img.shields.io/badge/metrics-76-1baf7a?style=flat-square" alt="76 metrics">7 <img src="https://img.shields.io/badge/tests-142%20passing-0ca30c?style=flat-square" alt="142 tests">8 <img src="https://img.shields.io/badge/TypeScript-strict-2a78d6?style=flat-square&logo=typescript&logoColor=white" alt="TypeScript strict">9 <img src="https://img.shields.io/badge/widget-3.2%20KB%20gzip-eda100?style=flat-square" alt="Widget size">10 <img src="https://img.shields.io/badge/monorepo-pnpm%20%2B%20turborepo-4a3aa7?style=flat-square" alt="pnpm + turborepo">11 <img src="https://img.shields.io/badge/i18n-fr%20%C2%B7%20en-e87ba4?style=flat-square" alt="fr + en">12 <img src="https://img.shields.io/badge/real--time-SSE%20%2B%20USGS-e34948?style=flat-square" alt="SSE real-time">13</p>1415**earth-now.co** is a real-time planetary dashboard — a robust successor to Worldometer. It displays live world metrics (population, births, CO₂, forest loss, energy, heartbeats, GDP…) that tick continuously on screen.1617The fundamental difference from every other live-counter site: **our counters are not opaque linear extrapolations**. Every metric is driven by a **documented statistical model** that interpolates between the latest real observations and forecasts from authoritative sources, with seasonality and uncertainty intervals. Every number on screen is traceable: source, license, observation date, model family, confidence interval — one click away, on every counter.1819---2021## ✨ Core principle: a counter is a model, not a stream2223**We never push one value per second over the network.** The server ships a `CounterModel`; every client animates the same pure function locally at 60 fps:2425```typescript26interface CounterModel {27 metricId: string; // e.g. "co2_emissions_ytd"28 anchorValue: number; // value at the anchor point29 anchorTime: string; // ISO 8601 UTC30 rateFn: RateFunction; // linear | piecewise | seasonal (Fourier) | spline (PCHIP)31 uncertainty?: { low: number; high: number }; // 90 % CI32 observedAt: string; // date of the last REAL observation33 sourceId: string; // key in the source registry34 modelVersion: string; // e.g. "seasonal-spline-v2"35 displayHints: { decimals: number; sigFigs?: number; unit: string; scale?: number };36}37```3839The dashboard, the embeddable widget and the server-rendered SVG badges all evaluate the **exact same function** — bit-identical values, verified by a cross-runtime test (jsdom vs a spawned Node process). SSE only pushes *new models* (new ingestion, new forecast, correction), never per-tick values.4041## 📊 The 76 metrics4243| Domain | Count | Highlights |44|---|---|---|45| 👶 Population | 24 | World population (hero), births/deaths/net growth, **human heartbeats (~9.7 B/s)**, top-10 countries + 6 continents ranked live |46| 💰 Economy | 9 | **World GDP (~$3.7 M/s)**, military spending + its **school-meals juxtaposition**, cars, smartphones, cement, steel, e-waste, garments |47| 💧 Society | 9 | Extreme poverty, safe water, hunger, food waste, freshwater use, animals slaughtered, fish caught, **coffee cups (~26 k/s)**, food produced |48| 🏥 Health | 7 | CVD/cancer/tobacco/malaria/child/road mortality (sober editorial rule), cigarettes smoked (~165 k/s) |49| 📱 Tech | 6 | Emails (~4.35 M/s, day+week cycles), Google searches, data created (~6.3 k TB/s), data-center electricity |50| ⚡ Energy | 5 | Electricity, renewable share, coal, oil, **solar installed while you read (~19 kW/s)** |51| 🌡️ Climate | 4 | CO₂ ppm (Keeling curve fit), temperature anomaly, **1.5 °C carbon budget counting down**, years remaining |52| 🏭 Emissions | 3 | CO₂ YTD / today / per second |53| 🌳 Forest | 3 | Tree-cover loss YTD / today / football-pitch equivalent |54| 🌊 Ocean | 2 | Sea level rise, Arctic sea ice (strong seasonal cycle) |55| ⚡ Real-time | 2 | **USGS earthquakes (true event-driven, no interpolation)**, humans in space |56| 🚀 Space | 2 | Earth's orbital distance (deterministic astronomy), Earth Overshoot Day countdown |5758**Model families in production:** `seasonal-ytd-v1` ×27 (Fourier day/week/year harmonics, Jan-1-UTC reset), `seasonal-spline-v2` ×23 (monotone PCHIP obs/forecast fusion), `derived` ×13 (exact server-side compositions), `linear-ytd-v1` ×8, `keeling-fusion-v1` ×2 (least-squares trend + annual harmonics), `static-rt-v1` ×2, `linear-stock-v1` ×1.5960## 🧪 Statistical honesty — the product6162- **Level 0** linear ⟶ **Level 1** seasonal (Fourier/STL) ⟶ **Level 2** observation/forecast fusion (monotone PCHIP splines, Kalman blending, Holt-Winters nowcasting).63- **PCHIP, never natural cubic splines** — a counter can mathematically never overshoot or tick backwards (property-tested with fast-check).64- `sigFigs` caps displayed precision: world population to the unit is a lie; the ticker animates but tooltips show the honest capped value + 90 % CI.65- Wide-uncertainty metrics (food waste ±15 %, garments ±30 %, AI-era estimates) **always** display their interval and an "estimate" label.66- Guardrails enforced at fit time: cumulative monotonicity, declared rate bounds, anchor identity, and an **anti-teleportation diff** that blocks deployment if a refit would visibly jump (clients smooth over 60 s instead).67- The `/methodology` page — and a per-metric method section on every `/metric/<id>` page — is generated from the registry: source, license, cadence, model family + version, last observation, uncertainty. A product commitment, not an option.6869## 🗂️ Architecture7071```72apps/73 web/ # Next.js 14 (App Router) — dashboard, /metric/:id, /methodology, /embed74 api/ # Fastify — REST + SSE + SVG badges + RT pollers (USGS, Open Notify)75 ingest/ # Ingestion workers (USGS, NOAA CO₂; BullMQ when Redis present)76packages/77 registry/ # Metric & source YAML + fixtures — the product source of truth78 models/ # PCHIP, Fourier LSQ, Holt-Winters, Kalman, guardrail validation (pure)79 counter/ # Shared runtime: value(model, t), formatting, windows (pure, isomorphic)80 widget/ # Embeddable widget.js — IIFE, zero deps, 3.2 KB gzip (15 KB budget)81infra/ # Docker Compose, nginx, ngrok, reverse proxy, migrations, deploy scripts82scripts/ # check-headers.ts — mandatory author-header lint (runs in pnpm lint)83```8485`packages/models` and `packages/counter` are **pure and deterministic**: no I/O, no implicit clock — time is always a parameter. That's what makes them testable and shareable client/server.8687**Data flow:** ingest ⟶ append-only observations ⟶ re-fit CounterModels ⟶ guardrail validation ⟶ SSE push ⟶ clients animate locally. Raw source payloads are archived with checksums so every model can be re-fitted from history.8889## 🖥️ The frontend9091- **Light-first token theme** (dark toggle), validated data-viz palette, overflow-proof ticking digits (`FitValue` measures and scales — a 17-digit heartbeat counter can't break the layout on any viewport).92- **Live-first information architecture**: a computed tier system (`secondsPerVisibleTick ≤ 2.5 s` ⟶ live grid, sorted fastest-first) decides what leads the page — not hand-picking.93- **"Since you arrived"** session strip (births, deaths, CO₂, forest, orbital km, solar installed) — the catalog's signature.94- Live-ranked **top-10 countries** and **continents** with animated magnitude bars.95- Year progress meter, pulsing live indicators (tier-driven, `prefers-reduced-motion` respected), fr/en from day one, thousands separators everywhere via `Intl.NumberFormat`.9697## 🧰 Commands9899```bash100pnpm dev # whole monorepo (turbo)101pnpm dev:web # frontend only102pnpm test # all packages — 142 tests103pnpm test:models # interpolators only (the critical ones)104pnpm lint # includes the mandatory file-header check105pnpm typecheck # strict TS across 10 packages106pnpm ingest:run <sourceId> # force an ingestion locally (usgs_fdsn, noaa_gml_mlo)107pnpm models:refit # re-fit + diff report with deployability verdicts108pnpm deploy:m3u96b # deploy to production + mandatory health checks109```110111## ✅ Testing — non-negotiable112113- **Golden/recovery tests** for every interpolator (synthetic Keeling recovered to < 0.05 ppm; output changes without a `modelVersion` bump fail CI).114- **Property-based tests** (fast-check): cumulative monotonicity, PCHIP no-overshoot, piecewise continuity, `value(anchorTime) === anchorValue`.115- **Client/server consistency**: `counterValue` in jsdom vs a separate Node process — `Object.is`-identical results.116- **Ingestion fixtures** including degraded cases (truncated NOAA file, malformed USGS GeoJSON).117- Registry integration test: every declared metric must load, fit, and pass all guardrails — 0 blocked models is enforced.118119## 🚀 Deployment120121Production is exposed at **https://www.earth-now.co** (reverse proxy → Next.js web + Fastify API). `pnpm deploy:m3u96b` performs rsync → install/build on the node → process restart → **mandatory health checks**: `GET /api/health` must return 200 and `/sse/health` must hold an SSE stream ≥ 10 s — the deploy is not "done" until both pass. A Docker Compose stack (TimescaleDB + Redis + nginx) ships in `infra/` for the DB-backed ingestion phase.122123## 📖 Reference documents124125- [`CLAUDE.md`](./CLAUDE.md) — the full engineering contract (architecture principles, guardrails, conventions).126- [`earth-now-metrics-catalog.md`](./earth-now-metrics-catalog.md) — the complete metric catalog by domain with model levels, sources and priorities (🥇 MVP · 🥈 V1 · 🥉 V2+).127128## 👤 Author129130| | |131|---|---|132| **Author** | Simon-Pierre Boucher |133| **Contact** | [contact@spboucher.ai](mailto:contact@spboucher.ai) |134| **Site** | [www.earth-now.co](https://www.earth-now.co) |135136Every source file in this repository carries the mandatory author header (enforced by `scripts/check-headers.ts` in CI). Data sources are credited in the UI, in API responses and on the methodology page — licenses are tracked per source in the registry, with `licenseNote` flags on anything requiring legal review before commercial launch.137138## 📄 License139140**All rights reserved** — this repository is source-available for reading and evaluation; commercial or production use requires written authorization (see [`LICENSE`](./LICENSE)). Third-party data remains under each source's own license, documented per metric in the registry.141142---143144<p align="center"><em>Chaque compteur est un modèle statistique documenté — jamais une extrapolation opaque.</em></p>145