Reverse-engineered from the shipped bundle

Threshold Globe

The animated backdrop on Cloudflare's login page isn't a flat "pixel world map" — it's a low-resolution 3D globe, rotated with real orthographic map projection math and rendered as a dithered grid of tiny squares. This page pulls apart the actual technique, traced from the component Cloudflare ships as ConnectGlobe.tsx.

0 cells - real world-110m coastlines, orthographic projection
1.0×
6
9fps
palette
— fps
78%
79%
50%
01–05

How it actually works

01

Project a real globe, but at almost no resolution

The component draws the world (a world-110m TopoJSON — the same file d3 examples use) with d3.geoOrthographic() — an actual rotating-sphere projection, not a flat map — but onto an offscreen canvas sized at width / cellSize. At a 6px cell, a 700px-wide globe is projected onto a canvas roughly 117px wide.

const grid = { w: Math.ceil(width / cell), h: Math.ceil(height / cell) };
const projection = d3.geoOrthographic()
  .translate([grid.w / 2, grid.h / 2])
  .scale(Math.min(grid.w, grid.h) * 0.47)
  .rotate([longitude, -12])
  .clipAngle(90); // hides the far side of the sphere
02

Read the tiny render back as land/ocean

Fill the projected landmass white, then read the offscreen canvas's ImageData. Each of those ~117×66 pixels becomes one cell's land coverage — its alpha channel, 0 for ocean, up to 1 for land.

const alpha = imageData[(cy * grid.w + cx) * 4 + 3] / 255;
03

Give every cell a fixed, position-only "difficulty"

A classic single-line pseudo-random hash — seeded only by the cell's x,y, never by time — assigns each cell a fixed number in [0,1). This is what makes some cells twinkle readily and others almost never: it's baked into their position, not re-rolled per frame.

function hash(x, y) {
  const n = Math.sin(x * 12.9898 + y * 78.233) * 43758.5453;
  return n - Math.floor(n);
}
04

Sweep a slow threshold wave over the grid

A cell is drawn only when its fixed hash falls under a threshold — and that threshold isn't constant. It's the sum of two sine waves running at different speeds along x and y, plus a floor that's much higher over land than ocean. As the wave rises and falls, it crosses different cells' hash values — that's the shimmer, with zero per-dot state to track.

function threshold(cx, cy, t, landAlpha) {
  const wave = (Math.sin(cx * 0.27 + t * 2e-4)
             + Math.sin(cy * 0.19 - t * 1.5e-4) + 2) / 4;
  return 0.05 + landAlpha * (0.42 + wave * 0.28);
}
// draw the cell only if hash(cx, cy) <= threshold(...)
05

Throttle hard, rotate slow, respect the OS setting

The whole thing redraws at roughly 9fps, not 60 — that chunkiness is deliberate, not a performance ceiling. Longitude advances linearly for a full rotation every 30 seconds. If prefers-reduced-motion is set, it renders exactly one frame and never schedules another.

const longitude = reducedMotion ? -18 : -18 + (elapsedMs / 30000) * 360;
if (!reducedMotion && now - lastFrame < 1000 / 9) { requestAnimationFrame(draw); return; }
*

Full render loop

Own reimplementation of the traced technique, using d3-geo for the projection and a real world-110m topology (the same one powering the demo above). This is what's actually running in the panel, with the constants exposed as the sliders.

threshold-globe.js~55 lines

    
†

Notes

Why so low-res

Projecting at full resolution and then downsampling would cost far more per frame than projecting straight onto a ~100px canvas. The cheap offscreen render is the optimization — the visible canvas just blows the result back up.

Why it doesn't look strobe-y

Because the hash is fixed per cell, the same dots tend to win at similar threshold levels frame to frame — the wave reveals and hides in coherent clusters instead of random static, which is what actually reads as "shimmer" rather than "noise."

Motion sensitivity

This demo checks prefers-reduced-motion exactly like the source: one static frame, globe frozen at a fixed longitude, no further animation loop.

🔍

Method: loaded Cloudflare's real login page, found the panel was a <canvas data-sentry-component="ConnectGlobe">, then fetched the shipped chunk that defines it and read the (minified, unminified-by-hand) source to pull out the actual constants — 30s rotation, 6px cells, 9fps throttle, the hash and threshold formulas. The code above is a clean, independent rewrite of that technique, not a copy of Cloudflare's source.