How this is built
Hand-written HTML, CSS and JavaScript, served straight off GitHub
Pages. No framework, no bundler, no build step between the repository and the page you
are reading. Everything below is measured from the repository itself by
generate_colophon.py rather than typed in, so it cannot go out of date
without a check failing.
What it weighs
- Stylesheet
- —
- Icon fonts
- —
- Text fonts
- —
- JavaScript
- —
- Dependencies
- 0
- Build step on deploy
- None
—
—
—
—
No npm, no lockfile, nothing to audit
Pages serves the repository as written
The main stylesheet is authored; the served file is generated by inlining the vendor CSS and then deleting every rule whose selector matches nothing on the site. The icon fonts are subset to the glyphs actually used, which is where most of that saving comes from. Nothing is minified beyond the stylesheet, because the numbers above did not justify the extra moving part.
What is in it
- Pages
- —
- Posts
- —
- Words
- —
- Reading time
- —
- Series
- —
- Topics
- —
- Photographs
- —
- Posts with a live demo
- —
End to end, at 220 words a minute
—
—
The writing
- First post
- —
- Posts a month
- —
- Average post
- —
- Longest
- —
- Shortest
- —
- Commits
- —
—
Averaged across the whole run
words
—
—
—
How it was built, month by month
Every commit to the repository, by month. The site was a single page for years; the writing, the tooling and most of what the rest of this page describes arrived in one long push through 2026.
What it runs on
It uses
- Hand-written HTML, CSS and JavaScript
- GitHub Pages, from the repository's default branch
- Python for the build scripts and the audit
- Playwright to drive the interactive posts in a real browser
- A service worker, so visited pages survive going offline
- GitHub Discussions for comments, Last.fm and Goodreads for the live figures
It deliberately does not
- Use a framework, a bundler, or a package manager
- Ship a single third-party runtime dependency
- Carry advertising, or any tracker beyond one analytics tag
- Require JavaScript to read a post
- Animate anything that a reader has asked it not to
- Publish a figure on this page that was typed rather than measured
The build
There is no build on deploy, but there is one before a commit.
— scripts generate what would otherwise be
maintained by hand, and every one of them has a --check mode that fails
rather than silently repairing.
- minify_css.py
- Inlines the vendor imports, deletes rules nothing matches, points the icon fonts at their subsets
- generate_read_times.py
- Counts each post's words, which also decides its band in the blog filter
- generate_post_facets.py
- Detects which posts carry a live demo or code, for the Format filter
- generate_related_posts.py
- Ranks neighbours by TF-IDF over body text and bakes the cards in
- generate_feed.py
- Builds the RSS feed, full-text for the twenty newest posts
- subset_icon_fonts.py
- Cuts three icon fonts down to the glyphs the site actually uses
- audit_site.py
- Links, metadata, structured data, accessibility basics, feed and sitemap
- generate_colophon.py
- Measures everything on this page
How it is checked
- Checks per push
- —
- Audit baseline
- 0 / 0
- Lines of CSS
- —
- Lines of JavaScript
- —
Run on every push and pull request
Errors and warnings, across every page
—
—
A push runs the site audit, rebuilds the stylesheet and fails if the committed one differs, and drives every interactive post in a headless browser to check it still converges, still works at phone width, and still announces itself to a screen reader.
Type and colour
Poppins
Interface, navigation, headlines on photographs. Self-hosted, seven weights.
Lora
Section headings and the body of every post. Self-hosted, three weights plus italics.
One accent does one job. Red means a control; the gradient is reserved for the two places the site signs its own name. Everything decorative is neutral, because hundreds of photographs are colour enough for one website.
The seasons
The site dresses itself for the four seasons and for the holidays below: the colours change, and each brings its own decorations, cursor and a few sounds (credited below). When a holiday falls inside a season, the holiday gets the day. Preview any of them; a preview lasts until you close the tab.
Photographs and hosting
- Photography
- My own, shot on a Canon EOS 60D (the older photos) and a Canon EOS R (the newer ones)
- Full-size files
- In a GitHub release rather than the repository, because Pages has an artifact limit and hundreds of originals do not fit inside it
- Hosting
- GitHub Pages, on a custom domain
The whole thing is written up, at considerably more length than this, in How This Site Is Built.
The slideshow's sounds
Other people's recordings, shared under free licences, each cut into a loop for the slideshow.
- Fire
- Fireplace Sound loop by PagDev (CC0)
- Rain
- Regen in de tent by luc de bruijn (CC BY 3.0)
- Rain and thunder
- Thunderstorm after hot summer day by stephan (public domain)
- Forest
- A dawn chorus in Shipton Gorge by Silas S. Brown (public domain)
- River
- Forest lawn creek by Dsw4 (public domain)
- Café
- Cafe ambiance by Marble Toast (CC0)
- City at night
- Two Lane Road in Kelowna at Midnight by Extemporalist (CC0)
The seasons' sounds
Each season puts three things on the footer, and if you turn the sounds on, most of them play a recording when clicked, also shared under free licences.
- Spring
- The slideshow's rain
- Spring peepers by JohnDziak (CC0)
- Summer
- Fall
- Walking through leaves by Gravity Sound (CC BY 4.0)
- An American crow's call from the U.S. Geological Survey (public domain)
- A low flyover by five Canada geese by Extemporalist (CC0)
- Winter
- Walking through snow in Berlin by Lukas Beck (CC BY 4.0)
- A black-capped chickadee in Calgary by ngoomie (CC0)
- Jump into snow by Gravity Sound (CC BY 4.0)
- Burns Night
- Darwin Day
- Summer's waves
- World Book Day
- A page turning by planish (public domain)
- An old book shut by cori (public domain)
- A mug of tea poured by cori (public domain)
- Holi
- A syringe emptied into water by ezwa (public domain), for the pichkari
- A dhol beat by Johnny Kalsi (CC BY 3.0)
- May the Fourth and Revenge of the Fifth
- Artemis II lifting off, from NASA (public domain)
- Neil Armstrong's first step, from NASA (public domain)
- Saturn's radio emissions, recorded by NASA's Cassini (public domain)
- International Cat Day
- Two meows by George Miquilena (CC0)
- A purring cat by Mysid (public domain)
- Halloween
- Wolf howls from the U.S. Fish and Wildlife Service (public domain)
- A barred owl in Yellowstone recorded by the National Park Service (public domain)
- A creaky wooden casket by stephan (public domain)
- Diwali
- A ghanta struck with a mallet by the_very_Real_Horst (CC0)
- Firecrackers by Almanta (CC0)
- Fireworks with a crowd by stephan (public domain)
- Bonfire Night
- The slideshow's fire
- Sparklers from Work With Sounds (CC BY 4.0)
- Fireworks over Berlin by thore (public domain)
- St Andrew's Day
- Oystercatchers at Loch Fleet from the British Library (CC BY 4.0)
- Burns Night's pipes
- Hogmanay
- Bonfire Night's fireworks over Berlin
- A knock at the door by stephan (public domain)
- A cheer by Starlite (public domain)