Back

Behind the page

A closer look at how it was made.

1 Globe

Every detail on the Earth and the Moon comes from real data. The coastlines, borders, lakes and rivers are traced from maps,1 Natural Earth, free map data in the public domain. and so are the faint lines for height on land and depth at sea.2 NASA, Blue Marble: the GEBCO maps of elevation on land and depth at sea. The Moon's seas3 NASA, CGI Moon Kit: the orbiter's colour map of the Moon. and about 460 of its named craters4 USGS, Gazetteer of Planetary Nomenclature: the IAU's named craters. sit where they really are. The Earth alone is about 70,000 points, redrawn up to 120 times a second.

The animation runs in a Web Worker.5 Wikipedia, Web worker: how a page gets a second thread. A web page normally runs on one thread, so a slow task holds up everything else. Rendering the globe is slow enough that the page's other animations stuttered. Making the drawing async would not have helped, since nothing else can run while a frame is being rendered.

A simpler globe, light enough to draw without a worker.

2 Fewer points

Why draw a point no one can see? At the size the globe is rendered, thousands of them land on top of each other. The Douglas-Peucker algorithm6 Wikipedia, Ramer-Douglas-Peucker algorithm: how the lines are thinned. thins them out, leaving about 17,300 points a frame where there were 30,600. The globe looks exactly the same, and each frame draws a quarter faster.

A made-up coastline: 0 of 0 points kept.

Each point is stored as the step from the one before it, a technique called delta encoding.7 Wikipedia, Delta encoding: how the map data is stored. The steps are small and much alike, which compresses far better: about 78 KB instead of 230 KB.

PositionStored
0 characters0 characters
A made-up coast in tenths of a degree: the first point in full, then only steps. Marked steps repeat, which is what compression feeds on.

3 Stars

Stars fill the dark theme's empty space, staying clear of the text. The page is cut into square cells, and each cell asks a hash function8 Wikipedia, Hash function: mapping inputs to fixed, scrambled-looking outputs. how many stars it holds and where. A hash gives the same answer for the same input, so a cell always gets the same stars.

A page being resized. Stars appear and disappear at its edges, but none moves.

Each cell has three slots. For each slot the hash returns three numbers from 0 to 1, unrelated to one another. The first decides whether the slot holds a star: above 0.8, it stays empty. The other two are the star's x and y coordinates in the cell.

Three slots, three numbers each: keep or not, then x and y.

A third of the stars slowly brighten and fade. A script updates them ten times a second, because a CSS animation would keep the browser busy on every frame.

4 From paper to page

The essays are written first for paper in Typst9 Typst: the typesetting system the essays are written in., a modern typesetting system in the spirit of LaTeX. The Typst compiler turns each document into a PDF/A.10 Wikipedia, PDF/A: the PDF standard for long-term archiving. Those originals can be downloaded from this site.

The web pages are ports of those documents. Their figures are translated from the Typst source into TypeScript, and the web ports add animations to them. Below is the same random number generator in both languages, taken from the figure of a drone swarm in the first essay.11 TvÄ artiklar om artificiell intelligens: the essay with the drone swarm, in Swedish.

Typst
s = calc.rem(s * 1103515245 + 12345,
  2147483648)
let jx = s / 2147483648
TypeScript
s = (s * 1103515245n + 12345n)
  % 2147483648n;
return Number(s) / 2147483648;
Seed 20260910, current state 20260910: 0 drones placed.

5 Fonts

The site ships ten font files from five families, all under open licenses. They are served from this site rather than from a font service, and each page loads only the fonts it uses.

  • You are reading this font right now. Libertinus Serif Regular, the text on every page 337 KB to 29 KB
  • It dates things and captions them. Libertinus Serif Italic, dates and captions 332 KB to 25 KB
  • It labels the margins. Libertinus Serif Semibold, the second essay's labels 292 KB to 26 KB
  • 1 2 3 4 5 6 7 8 9 0 Libertinus Serif Semibold, for the footnote numbers 292 KB to 3 KB
  • It sets the title above. Libertinus Serif Display, this page's title and Schrödinger's Result's 264 KB to 23 KB
  • It sets the code and signs the front page. Nordwand Mono Regular, the afterthoughts' code and the name on the front page 92 KB to 14 KB
  • It sets the first essay's headings. TeX Gyre Pagella Bold, the first essay's headings 220 KB to 18 KB
  • It names things in figures. TeX Gyre Pagella Regular, the first essay's labels 218 KB to 19 KB
  • It sets the second essay's headings. STIX Two Text Bold, the second essay's headings 296 KB to 19 KB
  • It sets the second essay's quotations. TeX Gyre Termes Italic, the second essay's quotations 141 KB to 19 KB
Ten fonts, 2.5 MB, shipped as 195 KB.

A font is drawn for dozens of languages, far more than this site needs. fontTools' subsetter12 fontTools, pyftsubset: the tool that trims a font to a subset. cuts the fonts down to the characters the site uses. They are then saved as WOFF213 Wikipedia, Web Open Font Format: the format the fonts are served in., a compressed format made for the web. Most end up about a tenth of their original size.

The PDFs use URW's14 Wikipedia, URW Type Foundry: the foundry behind the PDFs' fonts. versions of Palatino and Times. They are under the AGPL,15 URW base 35 fonts, LICENSE: the AGPL, with an exception for PDFs. which covers PDFs but not web pages. So the pages borrow the same designs from TeX Gyre. Its license asks that a modified font change its name, which is why the cut-down versions are called Pagella Janix Subset and Termes Janix Subset.

6 Security policy

A Content Security Policy16 Wikipedia, Content Security Policy: how a page tells the browser what it may run. tells the browser which scripts a page may run. The script below sets the theme. The policy holds only its hash, so changing one character is enough to block it.

sha256

This page's own theme script, hashed live in your browser.

7 Deployment

A push to GitHub starts a build on Cloudflare that checks the code for type errors, builds the pages and tests what was built before it goes live. The tests catch mistakes that break the site quietly: a stale hash, a character missing from the fonts, a broken link.

  1. git pushto main on GitHub
  2. bun installpinned dependencies
  3. bun run checkTypeScript, strict
  4. bun run buildpages, hashed assets, fonts, headers
  5. bun testagainst the built site
  6. wrangler deployout to Cloudflare's edge