1. readsWikipedia's most-read pages
  2. becomespageviews → mass (placement + weight); day-over-day → polarity
  3. writes--w--cat
  4. you seethe lead earns its slot; risers run warm, fallers cool, new entries gray

No canvas is drawn here — the field is invisible; these variables are its only output. Without it you would build: an editor reordering the page every morning.

Data honesty

Data source
Real Wikimedia pageviews API — en.wikipedia most-read pages with a day-over-day trend, CC0.
Snapshot
Committed snapshot in src/data/examples/, stamped snapshotAt on refresh via scripts/snapshot-examples.mjs — the build never fetches, so it is deterministic.
Live refresh
Upgrades to live in the browser: a polite poll (wireLiveChip) that skips hidden tabs and retires after failures. The committed snapshot is the SSR baseline and the no-JS truth.
Not claimed
The field reads pageviews as mass and the day-over-day change as polarity. It does not judge newsworthiness — it reflects attention already spent, not what deserves it.

Fundamental · invisible fields · newsroom

Attention, measured — not claimed.

A trending list asserts importance; a pageview count records it. These are the articles English Wikipedia readers actually read on November 1, 2026 — the Wikimedia pageviews API's most-read ranking, run as a field and laid out like a front page. Pageviews become gravitational mass, and mass buys column inches: the most-read article takes the lead slot, the next six fill the deck, the rest settle into the index — with heavier type, darker ink, a stronger left rule the more the world read.

The day-over-day change polarizes each body: rising attention warms, falling attention cools, and the magnitude sets the intensity — a 3% drift barely registers, a 200% surge burns. Articles that weren't in the prior day's list at all read as new, in neutral gray — no fake direction. The placement is fixed — a front page is set in type — but the ink is alive: the engine writes its live local density back as --d, so holding a story makes the field gather around it, and the index item nearest the center of your view sharpens as you scroll. Toggle the field off and the ink flattens and the live channels go dark: the placement stays (it is the day's ranking), but the field's weighting lets go.

Field
Color by
Data snapshot · November 1, 2026

size & placement = pageviews — the most-read story leads the page · color = the day-over-day move — warm rising, cool falling, gray new

  1. 05 Patrick Stewart 205,436 views ▼ 54.4%
  2. 06 .xxx 197,312 views ▼ 33.4%
  3. 07 Tung Tung Tung Sahur 192,363 views new
  4. 08 Nidhi Razdan 187,499 views ▼ 38.3%
  5. 09 Gabby Williams 180,204 views new
  6. 10 Inde Navarrette 142,063 views ▲ 281.8%
  1. 11 Heidi Klum 141,812 views ▲ 844.0%
  2. 12 Ciara Mageean 138,465 views new
  3. 13 Elizabeth Holmes 135,985 views ▼ 9.9%
  4. 14 Deaths in 2026 135,321 views ▲ 4.3%
  5. 15 Abdul El-Sayed 134,093 views ▲ 39.6%
  6. 16 Jailer 2 115,995 views ▲ 2.1%
  7. 17 Ansel Adams 113,390 views ▼ 8.2%
  8. 18 Kimi Antonelli 103,995 views ▲ 927.1%
  9. 19 Sanjay Gupta (director) 98,434 views ▼ 41.6%
  10. 20 Halloween 96,152 views ▼ 52.6%
  11. 21 Omar Abdullah 95,665 views ▼ 37.6%
  12. 22 You Can See Everything 94,892 views ▲ 3.7%
  13. 23 2026 United States elections 94,454 views ▲ 32.9%
  14. 24 Natalie Nakase 92,084 views new
  15. 25 Obsession (2025 film) 91,786 views ▲ 31.3%
  16. 26 Matthew Perry 90,662 views ▲ 3.8%
  17. 27 Clayface (film) 83,109 views ▲ 4.9%
  18. 28 Maya Jama 79,188 views ▼ 12.6%
  19. 29 Chris Murphy 78,612 views new
  20. 30 Golden State Valkyries 78,369 views new
  21. 31 Neelesh Misra 73,362 views ▼ 34.6%
  22. 32 Day of the Dead 72,853 views ▲ 89.5%
  23. 33 Wildwood (film) 70,974 views ▲ 8.7%

How it's built

Every article is an ordinary <li> with its raw counts in data attributes. Fundamental reads them, runs an invisible field over the front page, and the type carries the measurement — pageviews as weight and placement, the day's swing as color. No canvas, no chart library. Four channels do the work: --w is the server-computed weight, --cat the lens color, --d the engine's live local density (hold a story and the field gathers), and --field-attention the pattern's eased attention metric, which sharpens the index item nearest the viewport center. Placement is fixed; only the ink is alive. In the browser the page also checks for a newer edition — once per visit, on purpose: the pageviews API publishes each finished day exactly once, so a polling loop would be theater. If a newer day exists, the front page is rebuilt from it — same shaping rules, same markup, same field — and the dateline moves.

1 — each article is a field body

HTML
<li
  data-body="attract"
  data-strength="1.87"
  data-feedback
  data-hot
  data-views="291972"
  data-prior="303010"
  style="--w: 0.920; --cat: hsl(212 38% 59%);"
>
  <!-- rank · title · views -->
</li>
  • data-strength — gravitational mass from log-normalized pageviews
  • data-views / data-prior — the raw counts the lens reads
  • --cat — the polarity color the CSS mixes in
  • data-hot — the engine's live density (--d) gathers toward 1 while held

2 — CSS reads the field's output

CSS
.nw-row {
  /* --w = log-normalized views (0..1).
     --d = the engine's LIVE local density —
     data-hot gathers it toward 1 on hold. */
  --live: var(--d, 0);
  opacity: calc(0.58 + var(--w) * 0.42);
  border-left: 3px solid
    color-mix(in srgb,
      var(--cat) calc(18% + var(--w) * 82%),
      var(--line));
}
/* the index item nearest the viewport
   center sharpens — the pattern's eased
   attention metric, written per record */
.nw-index-item .nw-title {
  letter-spacing: calc(-0.01em
    + var(--field-attention, 0) * 0.01em);
}

Weight, ink, font heft, and border intensity all read from one normalized attention score; the lead's headline ink and rule breathe with the live --d — the field drives the measurement; CSS drives the presentation.

3 — the polarity ramp

TS
// day-over-day move → --cat:
// direction is hue, magnitude is
// intensity; no prior count = new.
const pct = prior
  ? ((views - prior) / prior) * 100
  : null;
if (pct === null) return "#8a93a6";
const t = Math.min(1, Math.abs(pct) / 60);
return pct >= 0
  ? `hsl(${32 - t * 10} …)`  // warm
  : `hsl(${208 + t * 12} …)`; // cool