# 🌍 earth-now.co β€” La planΓ¨te en direct / The planet, live

Live site CI 76 metrics 142 tests TypeScript strict Widget size pnpm + turborepo fr + en SSE real-time

**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. The 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. --- ## ✨ Core principle: a counter is a model, not a stream **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: ```typescript interface CounterModel { metricId: string; // e.g. "co2_emissions_ytd" anchorValue: number; // value at the anchor point anchorTime: string; // ISO 8601 UTC rateFn: RateFunction; // linear | piecewise | seasonal (Fourier) | spline (PCHIP) uncertainty?: { low: number; high: number }; // 90 % CI observedAt: string; // date of the last REAL observation sourceId: string; // key in the source registry modelVersion: string; // e.g. "seasonal-spline-v2" displayHints: { decimals: number; sigFigs?: number; unit: string; scale?: number }; } ``` The 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. ## πŸ“Š The 76 metrics | Domain | Count | Highlights | |---|---|---| | πŸ‘Ά Population | 24 | World population (hero), births/deaths/net growth, **human heartbeats (~9.7 B/s)**, top-10 countries + 6 continents ranked live | | πŸ’° Economy | 9 | **World GDP (~$3.7 M/s)**, military spending + its **school-meals juxtaposition**, cars, smartphones, cement, steel, e-waste, garments | | πŸ’§ Society | 9 | Extreme poverty, safe water, hunger, food waste, freshwater use, animals slaughtered, fish caught, **coffee cups (~26 k/s)**, food produced | | πŸ₯ Health | 7 | CVD/cancer/tobacco/malaria/child/road mortality (sober editorial rule), cigarettes smoked (~165 k/s) | | πŸ“± Tech | 6 | Emails (~4.35 M/s, day+week cycles), Google searches, data created (~6.3 k TB/s), data-center electricity | | ⚑ Energy | 5 | Electricity, renewable share, coal, oil, **solar installed while you read (~19 kW/s)** | | 🌑️ Climate | 4 | COβ‚‚ ppm (Keeling curve fit), temperature anomaly, **1.5 Β°C carbon budget counting down**, years remaining | | 🏭 Emissions | 3 | COβ‚‚ YTD / today / per second | | 🌳 Forest | 3 | Tree-cover loss YTD / today / football-pitch equivalent | | 🌊 Ocean | 2 | Sea level rise, Arctic sea ice (strong seasonal cycle) | | ⚑ Real-time | 2 | **USGS earthquakes (true event-driven, no interpolation)**, humans in space | | πŸš€ Space | 2 | Earth's orbital distance (deterministic astronomy), Earth Overshoot Day countdown | **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. ## πŸ§ͺ Statistical honesty β€” the product - **Level 0** linear ⟢ **Level 1** seasonal (Fourier/STL) ⟢ **Level 2** observation/forecast fusion (monotone PCHIP splines, Kalman blending, Holt-Winters nowcasting). - **PCHIP, never natural cubic splines** β€” a counter can mathematically never overshoot or tick backwards (property-tested with fast-check). - `sigFigs` caps displayed precision: world population to the unit is a lie; the ticker animates but tooltips show the honest capped value + 90 % CI. - Wide-uncertainty metrics (food waste Β±15 %, garments Β±30 %, AI-era estimates) **always** display their interval and an "estimate" label. - 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). - The `/methodology` page β€” and a per-metric method section on every `/metric/` page β€” is generated from the registry: source, license, cadence, model family + version, last observation, uncertainty. A product commitment, not an option. ## πŸ—‚οΈ Architecture ``` apps/ web/ # Next.js 14 (App Router) β€” dashboard, /metric/:id, /methodology, /embed api/ # Fastify β€” REST + SSE + SVG badges + RT pollers (USGS, Open Notify) ingest/ # Ingestion workers (USGS, NOAA COβ‚‚; BullMQ when Redis present) packages/ registry/ # Metric & source YAML + fixtures β€” the product source of truth models/ # PCHIP, Fourier LSQ, Holt-Winters, Kalman, guardrail validation (pure) counter/ # Shared runtime: value(model, t), formatting, windows (pure, isomorphic) widget/ # Embeddable widget.js β€” IIFE, zero deps, 3.2 KB gzip (15 KB budget) infra/ # Docker Compose, nginx, ngrok, reverse proxy, migrations, deploy scripts scripts/ # check-headers.ts β€” mandatory author-header lint (runs in pnpm lint) ``` `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. **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. ## πŸ–₯️ The frontend - **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). - **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. - **"Since you arrived"** session strip (births, deaths, COβ‚‚, forest, orbital km, solar installed) β€” the catalog's signature. - Live-ranked **top-10 countries** and **continents** with animated magnitude bars. - Year progress meter, pulsing live indicators (tier-driven, `prefers-reduced-motion` respected), fr/en from day one, thousands separators everywhere via `Intl.NumberFormat`. ## 🧰 Commands ```bash pnpm dev # whole monorepo (turbo) pnpm dev:web # frontend only pnpm test # all packages β€” 142 tests pnpm test:models # interpolators only (the critical ones) pnpm lint # includes the mandatory file-header check pnpm typecheck # strict TS across 10 packages pnpm ingest:run # force an ingestion locally (usgs_fdsn, noaa_gml_mlo) pnpm models:refit # re-fit + diff report with deployability verdicts pnpm deploy:m3u96b # deploy to production + mandatory health checks ``` ## βœ… Testing β€” non-negotiable - **Golden/recovery tests** for every interpolator (synthetic Keeling recovered to < 0.05 ppm; output changes without a `modelVersion` bump fail CI). - **Property-based tests** (fast-check): cumulative monotonicity, PCHIP no-overshoot, piecewise continuity, `value(anchorTime) === anchorValue`. - **Client/server consistency**: `counterValue` in jsdom vs a separate Node process β€” `Object.is`-identical results. - **Ingestion fixtures** including degraded cases (truncated NOAA file, malformed USGS GeoJSON). - Registry integration test: every declared metric must load, fit, and pass all guardrails β€” 0 blocked models is enforced. ## πŸš€ Deployment Production 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. ## πŸ“– Reference documents - [`CLAUDE.md`](./CLAUDE.md) β€” the full engineering contract (architecture principles, guardrails, conventions). - [`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+). ## πŸ‘€ Author | | | |---|---| | **Author** | Simon-Pierre Boucher | | **Contact** | [contact@spboucher.ai](mailto:contact@spboucher.ai) | | **Site** | [www.earth-now.co](https://www.earth-now.co) | Every 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. ## πŸ“„ License **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. ---

Chaque compteur est un modèle statistique documenté — jamais une extrapolation opaque.