SPB Git

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%
ZIP
NameLast commitUpdated
.github CI: run on Node 22 — jsdom 30 (undici 8) needs markAsUncloneable yesterday
apps earth-now.co v0.1 — real-time planetary dashboard yesterday
infra earth-now.co v0.1 — real-time planetary dashboard yesterday
packages earth-now.co v0.1 — real-time planetary dashboard yesterday
scripts earth-now.co v0.1 — real-time planetary dashboard yesterday
.env.example earth-now.co v0.1 — real-time planetary dashboard yesterday
.gitignore earth-now.co v0.1 — real-time planetary dashboard yesterday
CLAUDE.md earth-now.co v0.1 — real-time planetary dashboard yesterday
earth-now-metrics-catalog.md earth-now.co v0.1 — real-time planetary dashboard yesterday
LICENSE Add CI workflow (header lint + typecheck + tests + build) and license yesterday
package.json earth-now.co v0.1 — real-time planetary dashboard yesterday
pnpm-lock.yaml earth-now.co v0.1 — real-time planetary dashboard yesterday
pnpm-workspace.yaml earth-now.co v0.1 — real-time planetary dashboard yesterday
README.md README: pin CI badge to main branch (busts stale Camo cache) yesterday
tsconfig.base.json earth-now.co v0.1 — real-time planetary dashboard yesterday
turbo.json earth-now.co v0.1 — real-time planetary dashboard yesterday
README.md

# 🌍 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:

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/<id> 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

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 <sourceId>    # 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 — the full engineering contract (architecture principles, guardrails, conventions).
  • 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
Site 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). 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.