Folks, this is not okay. Our industry is characterized by institutional recklessness and a callous lack of empathy for our users.
Tuesday, October 19th, 2021
Thursday, October 7th, 2021
Thursday, September 9th, 2021
The excellent (and cheap!) State Of The Browser is coming back to Conway Hall this year on Saturday, October 30th. Speakers include Rachel Andrew and Amber Case.
Everyone needs to show proof of vaccination or a negative Covid test to get into the venue, which is reassuring.
I think I’m gonna go!
Tuesday, September 7th, 2021
I keep seeing Single-Page-Apps with huge JS files that only, in terms of concrete User Experience (UX) benefits, deliver client-side validation of forms plus analytics. Apps rarely leverage the potential of a Single-Page-App. It’s still just the same ‘click, wait for load’ navigation cycle. Same as the one you get with Multi-Page-Apps. Except buggier and with a much slower initial loading time.
When you look at performance, cross-platform and mobile support, reliability, and accessibility, nearly every Single-Page-App you can find in the wild is a failure on multiple fronts.
Replacing those with even a mediocre Multi-Page-App is generally going to be a substantial win. You usually see improvements on all of the issues mentioned above. You get the same general UX except with more reliable loading, history management, and loading features—provided by the browser.
Before you dismiss Baldur as a hater based on what I’ve just quoted, you should really read the whole article. The issue he points to is not with the technical architecture of single page apps, but with management.
Single-Page-Apps can be fantastic. Most teams will mess them up because most teams operate in dysfunctional organisations.
Baldur’s conclusion chimes a lot with what I’ve been saying in conference talks this year: the biggest challenges facing the web are not technical in nature.
The biggest hindrance to the web’s progress isn’t non-expert developers, tooling, libraries, Single-Page-Apps, or Multi-Page-Apps.
It’s always humans.
Tuesday, August 31st, 2021
A wonderful bit of spelunking into the annals of software interfaces by Elise Blanchard.
Monday, August 30th, 2021
Men specialized in hardware while software development was seen as an exciting alternative to secretarial work. In 1967, Cosmopolitan published an article titled The Computer Girls, encouraging young women to pursue careers in computer science. So the curve went up, and continued to do so up until 1984. That’s when personal computers appeared.
When Apple released the Macintosh 128K and the Commodore 64 was introduced to the market, they were presented as toys. And, as toys were gendered, they were targeted at boys. We can look at advertisements from that time and quickly find a pattern: fathers and sons, young men, even one where a man is being undressed by two women with the motto Two bytes are better than one. It’s more evident with the ads for computer games; if women appear, they do so sexualized and half-naked. Not that appealing for young girls, one could imagine.
Baldur Bjarnason writes an immense treatise on the current sad state of software, grounded in the historical perspective of the past sad state of software.
Sunday, August 8th, 2021
’Sfunny, when I look back at older journal entries they’re often written out of frustration, usually when something in the dev world is bugging me. But when I look back at all the links I’ve bookmarked the vibe is much more enthusiastic, like I’m excitedly pointing at something and saying “Check this out!” I feel like sentiment analyses of those two sections of my site would yield two different results.
My journal entries have been even more specifically negative of late. I’ve been bitchin’ and moanin’ about web browsers. But at least I’m an equal-opportunities bitcher and moaner.
- Mozilla, I complained about your Facebook Container extension for Firefox.
- Apple, I complained about the ridiculous way Safari’s update cycle is tied to operating system.
- Google, I complained about the way a breaking change was rolled out in Chrome (and the implications for future breaking changes).
- Microsoft, you got off lightly. But please consider any of my criticisms of Chrome to apply to Edge too, seeing as they’re basically the same now.
I wish my journal weren’t so negative, but my mithering behaviour has been been encouraged. On more than one occasion, someone I know at a browser company has taken me aside to let me know that I should blog about any complaints I might have with their browser. It sounds counterintuitive, I know. But these blog posts can give engineers some ammunition to get those issues prioritised and fixed.
So my message to you is this: if there’s something about a web browser that you’re not happy with (or, indeed, if there’s something you’re really happy with), take the time to write it down and publish it.
Publish it on your website. You could post your gripes on Twitter but whinging on Jack’s website is just pissing in the wind. And I suspect you also might put a bit more thought into a blog post on your own site.
I know it’s a cliché to say that browser makers want to hear from developers—and I’m often cynical about it myself—but they really do want to know what we think. Share your thoughts. I’ll probably end up linking to what you write.
Saturday, August 7th, 2021
The paradox of performance:
This era of incredibly fast hardware is also the era of programs that take tens of seconds to start from an SSD or NVMe disk; of bloated web applications that take many seconds to show a simple list, even on a broadband connection; of programs that process data at a thousandth of the speed we should expect. Software is laggy and sluggish — and the situation shows little signs of improvement. Why is that?
Because we prioritise the developer experience over the user experience, that’s why:
Although our job is ostensibly to create programs that let users do stuff with their computers, we place a greater emphasis on the development process and dev-oriented concerns than on the final user product.
We would do well to heed Craig’s observations on Fast Software, the Best Software.
Tuesday, August 3rd, 2021
If you employ a hack, don’t be so ashamed. Don’t be too proud, either. Above all, don’t be lazy—be certain and deliberate about why you’re using a hack.
I agree that hacks for prototyping are a-okay:
When it comes to prototypes, A/B tests, and confirming hypotheses about your product the best way to effectively deliver is actually by writing the fastest, shittiest code you can.
I’m not so sure about production code though.
Friday, July 30th, 2021
I’ve written before about how I don’t have notifications on my phone or computer. But that doesn’t stop computer programmes waving at me, trying to attract my attention.
If I have my email client open on my computer there’s a red circle with a number in it telling me how many unread emails I have. It’s the same with Slack. If Slack is running and somebody writes something to me, or @here, or @everyone, then a red circle blinks into existence.
There’s a category of programmes like this that want my attention—email, Slack, calendars. In each case, emptiness is the desired end goal. Seeing an inbox too full of emails or a calendar too full of appointments makes me feel queasy. In theory these programmes are acting on my behalf, working for me, making my life easier. And in many ways they do. They help me keep things organised. But they also need to me to take steps: read that email, go to that appointment, catch up with that Slack message. Sometimes it can feel like the tail is wagging the dog and I’m the one doing the bidding of these pieces of software.
My RSS reader should, in theory, fall into the same category. It shows me the number of unread items, just like email or Slack. But for some reason, it feels different. When I open my RSS reader to catch up on the feeds I’m subscribed to, it doesn’t feel like opening my email client. It feels more like opening a book. And, yes, books are also things to be completed—a bookmark not only marks my current page, it also acts as a progress bar—but books are for pleasure. The pleasure might come from escapism, or stimulation, or the pursuit of knowledge. That’s a very different category to email, calendars, and Slack.
I’ve managed to wire my neurological pathways to put RSS in the books category instead of the productivity category. I’m very glad about that. I would hate if catching up on RSS feeds felt like catching up on email. Maybe that’s why I’m never entirely comfortable with newsletters—if there’s an option to subscribe by RSS instead of email, I’ll always take it.
I have two folders in my RSS reader: blogs and magazines. Reading blog posts feels like catching up with what my friends are up to (even if I don’t actually know the person). Reading magazine articles feels like spending a lazy Sunday catching up with some long-form journalism.
I should update this list of my subscriptions. It’s a bit out of date.
Oh, and if you want to have my words in your RSS reader, I have plenty of options for you.
Wednesday, July 7th, 2021
We’ve enjoyed a relatively long period when we didn’t have to think about which browser to use. Alas, that period is ending: I must now keep Chrome running all the time, much like I needed that PC in the early 2000s.
Tuesday, July 6th, 2021
A great tool is not a universal tool it’s a tool well suited to a specific problem.
The more universal a solution someone claims to have to whatever software engineering problem exists, and the more confident they are that it is a fully generalized solution, the more you should question them.
Tuesday, April 13th, 2021
The idea that your job should be the primary source of meaning in your life is an elaborately made trap, propped up across industries, designed to make you a loyal worker who uses the bulk of their intellectual and creative capacity to further their own career.
Sunday, April 11th, 2021
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.
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
Thursday, March 11th, 2021
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?
Wednesday, February 17th, 2021
Employee experience design on the Clearleft podcast
This topic came out of conversations with Katie. She really enjoys getting stuck into to the design challenges of the “backstage” tools that are often neglected. This is an area that Chris has been working in recently too, so I quized him on this topic.
They’re both super smart people which makes for a thoroughly enjoyable podcast episode. I usually have more guests on a single episode but it was fun to do a two-hander for once.
The whole thing comes in at just under seventeen minutes and there are some great stories and ideas in there. Have a listen.
And if you’re enjoying listening to the Clearleft podcast as much as I’m enjoying making it, be sure to spread the word wherever you share your recommnedations: Twitter, LinkedIn, Slack, your own website, the rooftop.
Monday, February 1st, 2021
The right coding language, system architecture, or interface design will vary wildly from project to project. But there are characteristics particular to software that consistently cause traditional management practices to fail, while allowing small startups to succeed with a shoestring budget:
- Reusing good software is easy; it is what allows you to build good things quickly;
- Software is limited not by the amount of resources put into building it, but by how complex it can get before it breaks down; and
- The main value in software is not the code produced, but the knowledge accumulated by the people who produced it.
Understanding these characteristics may not guarantee good outcomes, but it does help clarify why so many projects produce bad outcomes. Furthermore, these lead to some core operating principles that can dramatically improve the chances of success:
- Start as simple as possible;
- Seek out problems and iterate; and
- Hire the best engineers you can.