I played a lot Lords of Midnight (and Doomdark’s Revenge) on my Amstrad 464 when I was a kid. Turns out there’s a dedicated labour of love to port the games to modern platforms. I just downloaded the OS X port, so there goes my weekend.
Sunday, April 11th, 2021
Thursday, April 8th, 2021
Accidental colour palettes captured in the wild.
Tuesday, April 6th, 2021
Of the web
I’m subscribed to a lot of blogs in my RSS reader. I follow some people because what they write about is very different to what I know about. But I also follow lots of people who have similar interests and ideas to me. So I’m not exactly in an echo chamber, but I do have the reverb turned up pretty high.
Sometimes these people post thoughts that are eerily similar to what I’ve been thinking about. Ethan has been known to do this. Get out of my head, Marcotte!
But even if Ethan wasn’t some sort of telepath, he’d still be in my RSS reader. We’re friends. Lots of the people in my RSS reader are my friends. When I read their words, I can hear their voices.
Then there are the people I’ve never met. Like Desirée García, Piper Haywood, or Jim Nielsen. Never met them, don’t know them, but damn, do I enjoy reading their blogs. Last year alone, I ended up linking to Jim’s posts ten different times.
Or Baldur Bjarnason. I can’t remember when I first came across his writing, but it really, really resonates with me. I probably owe him royalties for the amount of times I’ve cited his post Over-engineering is under-engineering.
His latest post is postively Marcottian in how it exposes what’s been fermenting in my own mind. But because he writes clearly, it really helps clarify my own thinking. It’s often been said that you should write to figure out what you think, and I can absolutely relate to that. But here’s a case where somebody else’s writing really helps to solidify my own thoughts.
It starts with some existentialist stock-taking. I can relate, what with the whole five decades thing. But then it turns the existential questioning to the World Wide Web itself, or rather, the people building the web.
In a way, it’s like taking the question of the great divide (front of the front end and back of the front end), and then turning it 45 degrees to reveal an entirely hidden dimension.
In examining the nature of the web, he hits on the litmus of how you view encapsulation:
I mention this first as it’s the aspect of the web that modern web developers hate the most without even giving it a label. Single-Page-Apps and GraphQL are both efforts to eradicate the encapsulation that’s baked into the foundation of every layer of the web.
Most modern devs are trying to get rid of it but it’s one of the web’s most strategic advantages.
I hadn’t thought of this before.
By default, if you don’t go against the grain of the web, each HTTP endpoint is encapsulated from each other.
Moreover, all of this can happen really fast if you aren’t going overboard with your CSS and JS.
He finishes with a look at another of the web’s most powerful features: distribution. In between are the things that make the web webby: hypertext and flexibility (The Dao of the Web).
It’s the idea that the web isn’t a single fixed thing but a fluid multitude whose shape is dictated by its surroundings.
This resonates with me because it highlights two different ways of viewing the web.
On the one hand, you can see the web purely as a distribution channel. In the past you might have been distributing a Flash movie. These days you might be distributing a single page app. Either way, the web is there as a low-friction way of getting your creation in front of other people.
The other way of building for the web is to go with the web’s grain, embracing flexibility and playing to the strengths of the medium through progressive enhancement. This is the distinction I was getting at when I talked about something being not just on the web, but of the web.
With that mindset, Baldur then takes us through some of the technologies that he’s excited about, like SvelteKit and Hotwire. I think it’s the same mindset that got me excited about service workers. As Baldur says:
They are helping the web become better at being its own thing.
That’s my tagline right there.
A genuinely interesting (and droll) deep dive into derp learning …for typography!
Receive one email a day for 30 days, each featuring at least one HTML element.
Right up my alley!
Wednesday, March 31st, 2021
Many, if not all, of our world’s most wicked problems are rooted in the excessive hiding of complexity behind illusions of simplicity—the relentless shielding of messy details in favor of easy-to-use interfaces.
But there’s always a tradeoff between complexity, truth, and control. The more details are hidden, the harder it is to understand how the system actually works. (And the harder it is to control). The map becomes less and less representative of the territory. We often trade completeness and control for simplicity. We’d rather have a map that’s easy to navigate than a map that shows us every single detail about the territory. We’d rather have a simple user interface than an infinitely flexible one that exposes a bunch of switches and settings. We don’t want to have to think too hard. We just want to get where we’re going.
Seamful and seamless design are reframed here as ethical and deceptive design:
Ethical design is like a glove. It obscures the underlying structure (i.e. your hand) but preserves some truth about its shape and how it works. Deceptive design is like a mitten. It obscures the underlying structure and also hides a lot about its shape and how it works.
Wednesday, March 24th, 2021
Given the widespread browser support for
prefers-reduced-motion now, this approach makes a lot of sense.
Tuesday, March 23rd, 2021
Service worker weirdness in Chrome
I think I’ve found some more strange service worker behaviour in Chrome.
It all started when I was checking out the very nice new redesign of WebPageTest. I figured while I was there, I’d run some of my sites through it. I passed in a URL from The Session. When the test finished, I noticed that the “screenshot” tab said that something was being logged to the console. That’s odd! And the file doing the logging was the service worker script.
I fired up Chrome (which isn’t my usual browser), and started navigating around The Session with dev tools open to see what appeared in the console. Sure enough, there was a failed
fetch attempt being logged. The only time my service worker script logs anything is in the
catch clause of fetching pages from the network. So Chrome was trying to fetch a web page, failing, and logging this error:
The service worker navigation preload request failed with a network error.
But all my pages were loading just fine. So where was the error coming from?
After a lot of spelunking and debugging, I think I’ve figured out what’s happening…
First of all, I’m making use of navigation preloads in my service worker. That’s all fine.
Secondly, the website is a progressive web app. It has a manifest file that specifies some metadata, including
start_url. If someone adds the site to their home screen, this is the URL that will open.
Thirdly, Google recently announced that they’re tightening up the criteria for displaying install prompts for progressive web apps. If there’s no network connection, the site still needs to return a
200 OK response: either a cached copy of the URL or a custom offline page.
So here’s what I think is happening. When I navigate to a page on the site in Chrome, the service worker handles the navigation just fine. It also parses the manifest file I’ve linked to and checks to see if that start URL would load if there were no network connection. And that’s when the error gets logged.
I only noticed this behaviour because I had specified a query string on my start URL in the manifest file. Instead of a
start_url value of
/, I’ve set a
start_url value of
/?homescreen. And when the error shows up in the console, the URL being fetched is
Crucially, I’m not seeing a warning in the console saying “Site cannot be installed: Page does not work offline.” So I think this is all fine. If I were actually offline, there would indeed be an error logged to the console and that
start_url request would respond with my custom offline page. It’s just a bit confusing that the error is being logged when I’m online.
I thought I’d share this just in case anyone else is logging errors to the console in the
catch clause of fetches and is seeing an error even when everything appears to be working fine. I think there’s nothing to worry about.
Update: Jake confirmed my diagnosis and agreed that the error is a bit confusing. The good news is that it’s changing. In Chrome Canary the error message has already been updated to:
DOMException: The service worker navigation preload request failed due to a network error. This may have been an actual network error, or caused by the browser simulating offline to see if the page works offline: see https://w3c.github.io/manifest/#installability-signals
Visualising the growth of the internet.
Saturday, March 20th, 2021
A profile of Brewster Kahle and the Internet Archive:
Tech’s walled gardens might make it harder to get a perfect picture, but the small team of librarians, digital archivists and software engineers at the Internet Archive plan to keep bringing the world the Wayback Machine, the Open Library, the Software Archive, etc., until the end of time. Literally.
I agree with this approach.
Tuesday, March 16th, 2021
Monday, March 15th, 2021
Based on the problems with accessiBe and its ilk, I have signed my name to this:
- We will never advocate, recommend, or integrate an overlay which deceptively markets itself as providing automated compliance with laws or standards.
- We will always advocate for the remediation of accessibility issues at the source of the original error.
- We will refuse to stay silent when overlay vendors use deception to market their products.
- More specifically, we hereby advocate for the removal of accessiBe, AudioEye, UserWay, User1st, MK-Sense, and all similar products and encourage the site owners who’ve implemented these products to use more robust, independent, and permanent strategies to making their sites more accessible.
Sunday, March 14th, 2021
This website is hosted across a network of solar powered servers and is sent to you from wherever there is the most sunshine.
Friday, March 12th, 2021
Developers, particularly in Silicon Valley firms, are definitionally wealthy and enfranchised by world-historical standards. Like upper classes of yore, comfort (“DX”) comes with courtiers happy to declare how important comfort must surely be. It’s bunk, or at least most of it is.
As frontenders, our task is to make services that work well for all, not just the wealthy. If improvements in our tools or our comfort actually deliver improvements in that direction, so much the better. But we must never forget that measurable improvement for users is the yardstick.
Thursday, March 11th, 2021
It’s official. The extremely niche browser behaviour I documented is a bug.
When service workers met framesets
Oh boy, do I have some obscure browser behaviour for you!
To set the scene…
I’ve been writing here in my online journal for almost twenty years. The official anniversary will be on September 30th. But this website has been even online longer than that, just in a very different form.
Here’s the first version of adactio.com.
Like a tour guide taking you around the ruins of some lost ancient civilisation, let me point out some interesting features:
- Observe the
.shtmlfile extension. That means it was once using Apache’s server-side includes, a simple way of repeating chunks of markup across pages. Scientists have been trying to reproduce the wisdom of the ancients using modern technology ever since.
- See how the layout is
100vh? Well, this was long before viewport units existed. In fact there is no CSS at all on that page. It’s one big
tableelement with 100% width and 100% height.
- So if there’s no CSS, where is the
border-radiuscoming from? Let me introduce you to an old friend—the non-animated GIF. It’s got just enough transparency (though not proper alpha transparency) to fake rounded corners between two solid colours.
if (navigator.appName == "Netscape")
Note that these are not iframes, they are frames. Different thing. You could create single page apps long before Ajax was a twinkle in Jesse James Garrett’s eye.
If you view source, you’ll see a React-like component system. Each
frameset component contains
frame components that are isolated from one another. They’re like web components. Each frame has its own (non-shadow) DOM. That’s because each frame is actually a separate web page. If you right-click on any of the frames, your browser should give the option to view the framed document in its own tab or window.
Now for the part where modern and ancient technologies collide…
If you’re looking at the frameset URL in Firefox or Safari, everything displays as it should in all its ancient glory. But if you’re looking in Google Chrome and you’ve visited adactio.com before, something very odd happens.
Each frame of the frameset displays my custom offline page. The only way that could be served up is through my service worker script. You can verify this by opening the framest URL in an incognito window—everything works fine when no service worker has been registered.
I have no idea why this is happening. My service worker logic is saying “if there’s a request for a web page, try fetching it from the network, otherwise look in the cache, otherwise show an offline page.” But if those page requests are initiated by a
frame element, it goes straight to showing the offline page.
Is this a bug? Or perhaps this is the correct behaviour for some security reason? I have no idea.
I wonder if anyone has ever come across this before. It’s a very strange combination of factors:
- a domain served over HTTPS,
- that registers a service worker,
- but also uses framesets and frames.
I could submit a bug report about this but I fear I would be laughed out of the bug tracker.
Still …the World Wide Web is remarkable for its backward compatibility. This behaviour is unusual because browser makers are at pains to support existing content and never break the web.
Technically a modern website (one that registers a service worker) shouldn’t be using deprecated technology like frames. But browsers still need to be able support those old technologies in order to render old websites.
This situation has only arisen because the same domain—adactio.com—is host to a modern website and a really old one.
Maybe Chrome is behaving strangely because I’ve built my online home on ancient burial ground.
It’s all to do with navigation preloads and the value of
event.preloadResponse, which I believe is only supported in Chrome which would explain the differences between browsers.
According to this post by Jake:
event.preloadResponse is a promise that resolves with a response, if:
- Navigation preload is enabled.
- The request is a GET request.
- The request is a navigation request (which browsers generate when they’re loading pages, including iframes).
event.preloadResponseis still there, but it resolves with
Notice that iframes are mentioned, but not frames.
My code was assuming that if
event.preloadRepsonse exists in my block of code for responding to page requests, then there’d be a response. But if the request was initiated from a frameset, it is a request for a page and
event.preloadRepsonse does exist …but it’s undefined.
I’ve updated my code now to check this assumption (and fall back to
This may technically still be a bug though. Shouldn’t a page loaded from a frameset count as a navigation request?
Friday, February 26th, 2021
One of the other arguments we hear in support of the SPA is the reduction in cost of cyber infrastructure. As if pushing that hosting burden onto the client (without their consent, for the most part, but that’s another topic) is somehow saving us on our cloud bills. But that’s ridiculous.
Thursday, February 25th, 2021
Today is my birthday. I am one twentieth of a millenium old. I am eighteen and a quarter kilo-days old. I am six hundred months old. I am somewhere in the order of 26.28 mega-minutes old. I am fifty years old.
The reflected light of the sun that left Earth when I was born has passed Alpha Cephei and will soon reach Delta Aquilae. In that time, our solar system has completed 0.00002% of its orbit around the centre of our galaxy.
I was born into a world with the Berlin Wall. That world ended when I turned eighteen.
Fifty years before I was born, the Irish war of independence was fought while the world was recovering from an influenza pandemic.
Fifty years after I was born, the UK is beginning its post-Brexit splintering while the world is in the middle of a coronavirus pandemic.
In the past few years, I started to speculate about what I might do for the big Five Oh. Should I travel somewhere nice? Or should I throw a big party and invite everyone I know?
Neither of those are options now. The decision has been made for me. I will have a birthday (and subsequent weekend) filled with the pleasures of home. I plan to over-indulge with all my favourite foods, lovingly prepared by Jessica. And I want the finest wines available to humanity—I want them here and I want them now.
I will also, inevitably, be contemplating the passage of time. I’m definitely of an age now where I’ve shifted from “explore” to “exploit.” In other words, I’ve pretty much figured out what I like doing. That is in contrast to the many years spent trying to figure out how I should be spending my time. Now my plans are more about maximising what I know I like and minimising everything else. What I like mostly involves Irish traditional music and good food.
So that’s what I’ll be doubling down on for my birthday weekend.
Monday, February 22nd, 2021
Ten down, one to go
The Long Now Foundation is dedicated to long-term thinking. I’ve been a member for quite a few years now …which, in the grand scheme of things, is not very long at all.
One of their projects is Long Bets. It sets out to tackle the problem that “there’s no tax on bullshit.” Here’s how it works: you make a prediction about something that will (or won’t happen) by a particular date. So far, so typical thought leadery. But then someone else can challenge your prediction. And here’s the crucial bit: you’ve both got to place your monies where your mouths are.
Ten years ago, I made a prediction on the Long Bets website. It’s kind of meta:
The original URL for this prediction (www.longbets.org/601) will no longer be available in eleven years.
One year later I was on stage in Wellington, New Zealand, giving a talk called Of Time And The Network. I mentioned my prediction in the talk and said:
If anybody would like to take me up on that bet, you can put your money down.
Matt was also speaking at Webstock. When he gave his talk, he officially accepted my challenge.
So now it’s a bet. We both put $500 into the pot. If I win, the Bletchly Park Trust gets that money. If Matt wins, the money goes to The Internet Archive.
As I said in my original prediction:
I would love to be proven wrong.
That was ten years ago today. There’s just one more year to go until the pleasingly alliterative date of 2022-02-22 …or as the Long Now Foundation would write it, 02022-02-22 (gotta avoid that Y10K bug).
It is looking more and more likely that I will lose this bet. This pleases me.