Journal

3174 sparkline

Saturday, August 30th, 2025

The Invisibles

When I was talking about monitoring web performance yesterday, I linked to the CrUX data for The Session.

CrUX is a contraction of Chrome User Experience Report. CrUX just sounds better than CEAR.

It’s data gathered from actual Chrome users worldwide. It can be handy as part of a balanced performance-monitoring diet, but it’s always worth remembering that it only shows a subset of your users; those on Chrome.

The actual CrUX data is imprisoned in some hellish Google interface so some kindly people have put more humane interfaces on it. I like Calibre’s CrUX tool as well as Treo’s.

What’s nice is that you can look at the numbers for any reasonably popular website, not just your own. Lest I get too smug about the performance metrics for The Session, I can compare them to the numbers for WikiPedia or the BBC. Both of those sites are made by people who prioritise speed, and it shows.

If you scroll down to the numbers on navigation types, you’ll see something interesting. Across the board, whether it’s The Session, Wikipedia, or the BBC, the BFcache—back/forward cache—is used around 16% to 17% of the time. This is when users use the back button (or forward button).

Unless you do something to stop them, browsers will make sure that those navigations are super speedy. You might inadvertently be sabotaging the BFcache if you’re sending a Cache-Control: no-store header or if you’re using an unload event handler in JavaScript.

I guess it’s unsurprising the BFcache numbers are relatively consistent across three different websites. People are people, whatever website they’re browsing.

Where it gets interesting is in the differences. Take a look at pre-rendering. It’s 4% for the BBC and just 0.4% for Wikipedia. But on The Session it’s a whopping 35%!

That’s because I’m using speculation rules. They’re quite straightforward to implement and they pair beautifully with full-page view transitions for a slick, speedy user experience.

It doesn’t look like WikiPedia or the BBC are using speculation rules at all, which kind of surprises me.

Then again, because they’re a hidden technology I can understand why they’d slip through the cracks.

On any web project, I think it’s worth having a checklist of The Invisibles—things that aren’t displayed directly in the browser, but that can make a big difference to the user experience.

Some examples:

If you’ve got a checklist like that in place, you can at least ask “Whose job is this?” All too often, these things are missing because there’s no clarity on whose responsible for them. They’re sorta back-end and sorta front-end.

Friday, August 29th, 2025

Databasing

A few years back, Craig wrote a great piece called Fast Software, the Best Software:

Speed in software is probably the most valuable, least valued asset. To me, speedy software is the difference between an application smoothly integrating into your life, and one called upon with great reluctance.

Nelson Elhage said much the same thing in his reflections on software performance:

I’ve really come to appreciate that performance isn’t just some property of a tool independent from its functionality or its feature set. Performance — in particular, being notably fast — is a feature in and of its own right, which fundamentally alters how a tool is used and perceived.

Or, as Robin put it:

I don’t think a website can be good until it’s fast.

Those sentiments underpin The Session. Speed is as much a priority as usability, accessibility, privacy, and security.

I’m fortunate in that the site doesn’t have an underlying business model at odds with these priorities. I’m under no pressure to add third-party code that would track users and slow down the website.

When it comes to making fast websites, most of the obstacles are put in place by front-end development, mostly JavaScript. I’ve been pretty ruthless in my pursuit of speed on The Session, removing as much JavaScript as possible. On the bigger pages, the bottleneck now is DOM size rather than parsing and excuting JavaScript. As bottlenecks go, it’s not the worst.

But even with all my core web vitals looking good, I still have an issue that can’t be solved with front-end optimisations. Time to first byte (or TTFB if you’d rather use an initialism that takes just as long to say as the words it’s replacing).

When it comes to reducing the time to first byte, there are plenty of factors that are out of my control. But in the case of The Session, something I do have control over is the server set-up, specifically the database.

Now I could probably solve a lot of my speed issues by throwing money at the problem. If I got a bigger better server with more RAM and CPUs, I’m pretty sure it would improve the time to first byte. But my wallet wouldn’t thank me.

(It’s still worth acknowledging that this is a perfectly valid approach when it comes to back-end optimisation that isn’t available on the front end; you can’t buy all your users new devices.)

So I’ve been spending some time really getting to grips with the MySQL database that underpins The Session. It was already normalised and indexed to the hilt. But perhaps there were server settings that could be tweaked.

This is where I have to give a shout-out to Releem, a service that is exactly what I needed. It monitors your database and then over time suggests configuration tweaks, explaining each one along the way. It’s a seriously good service that feels as empowering as it is useful.

I wish I could afford to use Releem on an ongoing basis, but luckily there’s a free trial period that I could avail of.

Thanks to Releem, I was also able to see which specific queries were taking the longest. There was one in particular that had always bothered me…

If you’re a member of The Session, then you can see any activity related to something you submitted in the past. Say, for example, that you added a tune or an event to the site a while back. If someone else comments on that, or bookmarks it, then that shows up in your “notifications” feed.

That’s all well and good but under the hood it was relying on a fairly convuluted database query to a very large table (a table that’s effectively a log of all user actions). I tried all sorts of query optimisations but there always seemed to be some combination of circumstances where the request would take ages.

For a while I even removed the notifications functionality from the site, hoping it wouldn’t be missed. But a couple of people wrote to ask where it had gone so I figured I ought to reinstate it.

After exhausting all the technical improvements, I took a step back and thought about the purpose of this particular feature. That’s when I realised that I had been thinking about the database query too literally.

The results are ordered in reverse chronological order, which makes sense. They’re also chunked into groups of ten, which also makes sense. But I had allowed for the possibility that you could navigate through your notifications back to the very start of your time on the site.

But that’s not really how we think of notifications in other settings. What would happen if I were to limit your notifications only to activity in, say, the last month?

Boom! Instant performance improvement by orders of magnitude.

I guess there’s a lesson there about switching off the over-analytical side of my brain and focusing on actual user needs.

Anyway, thanks to the time I’ve spent honing the database settings and optimising the longest queries, I’ve reduced the latency by quite a bit. I’m hoping that will result in an improvement to the time to first byte.

Time—and monitoring tools—will tell.

Tuesday, August 26th, 2025

Newsletters

Ethan tagged me in a post. I didn’t feel a thing.

“I’d love to invite a few other folks to share their favorite newsletters”, he wrote.

My immediate thought was that I don’t actually subscribe to many newsletters. But then I remembered that most newsletters are available as RSS feeds, and I very much do subscribe to those.

Reading RSS and reading email feel very different to me. A new item in my email client feels like a task. A new item in my feed reader feels like a gift.

Anyway, I poked around in my subscriptions and found some newsletters in there that I can heartily recommend.

First and foremost, there’s The History Of The Web by Jay Hoffman. Each newsletter is a building block for the timeline of the web that he’s putting together. It’s very much up my alley.

On the topic of the World Wide Web, Matthias has a newsletter called Own Your Web:

Whether you want to get started with your own personal website or level up as a designer, developer, or independent creator working with the ever-changing material of the Web, this little email is for you. ❤✊

On the inescapable topic of “AI”, I can recommend Mystery AI Hype Theater 3000: The Newsletter by Professor Emily M. Bender and Doctor Alex Hanna.

Journalist Clive Thompson has a fun newsletter called The Linkfest:

The opposite of doomscrolling: Every two weeks (roughly) I send you a collection of the best Internet reading I’ve found — links to culture, technology, art and science that fascinated me.

If you like that, you’ll love The Whippet by McKinley Valentine:

A newsletter for the terminally curious

Okay, now there are three more newsletters that I like, but I’m hesitant to recommend for the simple reason that they’re on Substack alongside a pile of racist trash. If you decide you like any of these, please don’t subscribe by email; use the RSS feed. For the love of Jeebus, don’t give Substack your email address.

Age of Invention by Anton Howes is a deep, deep dive into the history of technology and industry:

I’m interested in everything from the exploits of sixteenth-century alchemists to the schemes of Victorian engineers.

Finally, there are two newsletters written by people whose music I listened to in my formative years in Ireland…

When We Were Young by Paul Page recounts his time in the band Whipping Boy in the ’90s:

This will be the story of Whipping Boy told from my perspective.

Toasted Heretic were making very different music around the same time as Whipping Boy. Their singer Julian Gough has gone on to write books, poems, and now a newsletter about cosmology called The Egg And The Rock:

The Egg and the Rock makes a big, specific argument (backed up by a lot of recent data, across many fields), that our universe appears to be the result of an evolutionary process at the level of universes.

There you go—quite a grab bag of newsletter options for you.

Thursday, August 14th, 2025

Underlines and line height

I was thinking about something I wrote yesterday when I was talking about styling underlines on links:

For a start, you can adjust the distance of the underline from the text using text-underline-offset. If you’re using a generous line-height, use a generous distance here too.

For some reason, I completely forgot that we’ve got a line-height unit in CSS now: lh. So if you want to make the distance of your underline proportional to the line height of the text that the link is part of, it’s easy-peasy:

text-underline-offset: 0.15lh;

The greater the line height, the greater the distance between the link text and its underline.

I think this one is going into my collection of CSS snippets I use on almost every project.

Wednesday, August 13th, 2025

Style your underlines

We shouldn’t rely on colour alone to indicate that something is interactive.

Take links, for example. Sure, you can give them a different colour to the surrounding text, but you shouldn’t stop there. Make sure there’s something else that distinguishes them. You could make them bold. Or you could stick with the well-understood convention of underlying links.

This is where some designers bristle. If there are a lot of links on a page, it could look awfully cluttered with underlines. That’s why some designers would rather remove the underline completely.

As Manu observed:

I’ve done a lot of audits in the first half of this year and at this point a believe that designing links without underlines is a kink. The idea that users don’t understand that links are clickable arouses some designers. I can’t explain it any other way.

But underlining links isn’t the binary decision it once was. You can use CSS to style those underlines just as you’d style any other part of your design language.

Here’s a regular underlined link.

For a start, you can adjust the distance of the underline from the text using text-underline-offset. If you’re using a generous line-height, use a generous distance here too.

Here’s a link with an offset underline.

If you’d rather have a thinner or thicker underline, use text-decoration-thickness.

Here’s a link with a thin underline.

The colour of the underline and the colour of the link don’t need to be the same. Use text-decoration-color to make them completely different colours or make the underline a lighter shade of the link colour.

Here’s a link with a translucent underline.

That’s quite a difference with just a few CSS declarations:

text-underline-offset: 0.2em;
text-decoration-thickness: 1px;
text-decoration-color: oklch(from currentColor l c h / 50%);

If that still isn’t subtle enough for you, you could even use text-decoration-style to make the underline dotted or dashed, but that might be a step too far.

Here’s a link with a dotted underline.

Whatever you decide, I hope you’ll see that underlines aren’t the enemy of good design. They’re an opportunity.

You should use underlines to keep your links accessible. But you should also use CSS to make those underlines beautiful.

Monday, August 11th, 2025

Session talk

I was in Nor’n Irelan’ at the end of July for my annual week of Belfast Tradfest.

It was the best one yet. Classes in the morning, sessions all day, and concerts in the evening.

There were also some excellent events at Ulster University during the afternoons—talks, film screenings, interviews and discussions.

If you squint closely at the poster for this year’s event you’ll see my name on there. That’s because one of those afternoon events was me giving a talk about thesession.org.

I’m no stranger to public speaking but this was a very different audience to the usual conferences I speak at. I had to make sure not to get technical. So I talked about the history of the site, the house rules, changes made over time, and pointed out some features that people might’ve missed.

I also made sure not to speak for too long. I had an hour but I kept the presentation to just 25 minutes so that there’d be plenty of time for questions and discussions afterwards.

It went really well. People had lots of questions and ideas.

Some interesting themes emerged from the discussion…

There was no shortage of suggestions for features that were technically possible, but that I’m probably not going to add because of they might clutter up the interface.

Some other people had suggestions for features that were actually already on the site …but implemented in such a subtle way that you could easily miss them.

This highlights an ongoing balancing act I’ve been performing for the site’s two and a half decades of existence. I want to keep improving the site and ensuring that powerful features are available. But I also want to keep the site streamlined and easy to use.

Thinking about it, this is one of the things that sets The Session apart from other tune collections out there. Many of them have great content but it’s not always easy to get to grips with it, at least at first.

Still, I may have gone too far in the other direction with The Session. In trying to avoid cluttering up the interface, I might’ve buried some features a little deep.

Anyway, all of this has been great food for thought. I’m really glad I got to meet so many people who use The Session. It literally wouldn’t exist without them.

Thursday, August 7th, 2025

Progressive web apps

There was a time when you needed to make a native app in order to take advantage of specific technologies. That time has passed.

Now you can do all of these things on the web:

  • push notifications,
  • offline storage,
  • camera access,
  • and more.

Take a look at the home screen on your phone. Looking at the apps you’ve downloaded from an app store, ask yourself how many of them could’ve been web apps.

Social media apps, airline apps, shopping apps …none of them are using technologies that aren’t widely available on the web.

“But”, you might be thinking, “it feels different having a nice icon on my homescreen that launches a standalone app compared to navigating to a bookmark in my web browser.”

I agree! And you can do that with a web app. All it takes the addition of one manifest file that lists which icons and colours to use.

If that file exists for a website, then once the user adds the website to their homescreen it will behave just like native app.

Try it for yourself. Go to instagram.com in your mobile browser and it to your homescreen (on the iPhone, you get to the “add to home screen” option from the sharing icon—scroll down the list of options to find it).

See how it’s now an icon on your home screen just like all your other apps? Tap that icon to see how it launches just like a native app with no browser chrome around it.

This doesn’t just work on mobile. Desktop browsers like Chrome, Edge, and Safari also allow you to install web apps straight from the browser and into your dock.

About half of the icons in my dock are actually web apps and I honestly can’t tell which is which. Mastodon, Instagram, Google Calendar, Google Docs …I’m sure most of those services are available as downloadable desktop apps, but why would I bother doing that when I get exactly the same experience by adding the sites to my dock?

From a business perspective, it makes so much sense to build a web app (or simply turn your existing website into a web app with the addition of a manifest file). No need for separate iOS or Android developer teams. No need to play the waiting game with updates to your app in the app store—on the web, updates are instant.

You can even use an impressive-sounding marketing term for this approach: progressive web apps:

A Progressive Web App (PWA) is a web app that uses progressive enhancement to provide users with a more reliable experience, uses new capabilities to provide a more integrated experience, and can be installed. And, because it’s a web app, it can reach anyone, anywhere, on any device, all with a single codebase. Once installed, a PWA looks like any other app, specifically:

  • It has an icon on the home screen, app launcher, launchpad, or start menu.
  • It appears when you search for apps on the device.
  • It opens in a standalone window, wholly separated from a browser’s user interface.
  • It has access to higher levels of integration with the OS, for example, URL handling or title bar customization.
  • It works offline.

But there’s still one thing that native apps do better than the web. If you want to be able to monitor and track users to an invasive degree, the web can’t compete with the capabilities of native apps. That’s why you’ll see so many websites on your mobile device that implore to install their app from the app store.

If that’s not a priority for you, then you can differentiate yourself from your competitors by offering your users a progressive web app. Instead of having links to Apple and Google’s app stores, you can link to a page on your own site with installation instructions.

I can guarantee you that users won’t be able to tell the difference between a native app they installed from an app store and a web app they’ve added to their home screen.

Tuesday, July 22nd, 2025

Streamlining HTML web components

If you’re a front-end developer and you don’t read Chris Ferdinandi’s blog, you should change that right now. Add that RSS feed to your feed reader of choice!

Lately he’s been posting about some of the thinking behind his Kelp UI library. That includes some great nuggets of wisdom around HTML web components.

First of all, he pointed out that web components don’t need a constructor(). This was news to me. I thought custom elements had to include this incantation at the start:

constructor () {
  super();
}

But it turns that if all you’re doing is calling super(), you can omit the whole thing and it’ll be done for you.

I immediately refactored all the web components I’m using on The Session. While I was at it, I implemented Chris’s bulletproof web component loading.

Now technically, I don’t need to do this. I’m linking to my JavaScript at the bottom of every page so I know it’s going to load after the HTML. But I don’t like having that assumption baked into my code.

For any of my custom elements that reference other elements in the DOM—using, say, document.querySelector()—I updated the connectedCallback() method to use Chris’s technique.

It turned out that there weren’t that many of my custom elements that were doing that. Because HTML web components are wrapped around existing markup, the contents of the custom element are usually what matters (rather than other elements on the same page).

I guess that’s another unexpected benefit to HTML web components. Because they’ve already got their own bit of DOM inside them, you don’t need to worry about when you load your markup and when you load your JavaScript.

And no faffing about with the dark arts of the Shadow DOM either.

Monday, July 21st, 2025

Portugeating

Hi Chris. You mentioned you were off to Portugal soon to explore Lisbon and Porto and I promised I’d send along some food tips from my previous visits.

I’ll skip over the obvious. No doubt you’ll seek out pasteis de nata in Lisbon. And I’m sure someone will convince you to have a francesinha in Porto (perhaps at the tail end of a beery night out).

Personally, I think one of Portugal’s treasures is its tinned fish. Find a spot where you can peruse a selection and have a tin with a beer or a glass of excellent Portugese wine.

In Lisbon there’s Sol E Pesca, just down the street from the Time Out market.

In Porto there’s Prova, though the focus is there is more on cheese.

A lot of the best tinned fish will hail from Matosinhos, a northern suburb of Porto. I recommend making your way up there.

Check out the fish market there, which is also the former home to a digital design school where I spent a week teaching a few years back. At lunch time you can pick out a fish from the market and take it straight to Taberna Lusitana to have them cook it for you.

In the evening, every place in Matosinhos hauls a grill out onto the street to cook sardines. It smells wonderful!

Take every opportunity that comes your way to eat the local percebes—goose barnacles—hand-harvested in risky conditions from the Atlantic coastline.

There are lots of seafood restaurants in Matosinhos but I can personally recommend O Gaveto. Myself and Jessica were enticed in by the owner one evening as we stood outside admiring the fish tank. We ended up having an astoundingly delicious seafood rice.

We also witnessed a mysterious gathering of robed figures bedecked with chains who ate from a large pot filled with a dark mixture. When we asked our waiter about it, he told us it was “the brotherhood of the lamprey!”

Oh, and when you’re in Porto you absolutely must have tripas à moda do Porto—an excellent tripe stew that costs next to nothing and tastes great no matter where you get it.

If you’re eating out along the waterfront, there’s a spot a little further along from the usual touristy spots called Vinhas d’Alho. Get one of the outside tables if you can for a great view of the Port places across the river. Pick out one you like the look of and go for a Port tasting.

Even if you don’t go for a Port tasting, be sure to have a Port Tonico at some point—it’s like a more refreshing version of a gin and tonic, made with white Port.

That’s all I can think of right now. I’m afraid I can’t give you an address for the most memorable meal I had in Porto:

The most unexpected thing I ate in Porto was when I wandered off for lunch on my own one day. I ended up in a little place where, when I walked in, it was kind of like that bit in the Western when the music stops and everyone turns to look. This was clearly a place for locals. The owner didn’t speak any English. I didn’t speak any Portuguese. But we figured it out. She mimed something sandwich-like and said a word I wasn’t familiar with: bifana. Okay, I said. Then she mimed the universal action for drinking, so I said “agua.” She looked at with a very confused expression. “Agua!? Não. Cerveja!” Who am I to argue? Anyway, she produced this thing which was basically some wet meat in a bun. It didn’t look very appetising. But this was the kind of situation where I couldn’t back out of eating it. So I took a bite and …it was delicious! Like, really, really delicious.

Sunday, July 20th, 2025

Donegal to Galway to Clare

After spending a week immersed in the language and the landscape of Glencolmcille, Jessica and I were headed to Miltown Malbay for the annual Willie Clancy music week.

I could only get us accommodation from the Monday onwards so we had a weekend in between Donegal and Clare. We decided to spend it in Galway.

We hadn’t booked any travel from Glencolmcille to Galway and that worked out fine. We ended up getting a lift from a fellow student (and fellow blogger) heading home to Limerick.

Showing up in Galway on a busy Saturday afternoon was quite the change after the peace and quiet of Glencolmcille. But we dove right in and enjoyed a weekend of good food and music.

A man playing button accordion and a man playing banjo at a pub table covered with pints. A fiddle in the foreground as a man plays pipes accompanied by another man on guitar.

But I missed speaking Irish. So on the Sunday afternoon we made a trip out to Spiddal for lunch just so we could say a few words as Gaeilge.

We also got some practice in every morning getting coffee at the Plámás cafe. You get a ten-cent discount for ordering in Irish. What a lovely little piece of behaviour design—a nice gentle nudge!

From Galway we made our way down to Miltown Malbay where the Willie Clancy festival was in full swing. We were staying out in Spanish Point, so we could escape the madness of the town each evening. Mind you, there was plenty going at the Armada hotel too.

The hotel was something of an extravagance but it was worth it—we had a beautiful view on to the beach at Spanish Point and our room was tucked away far from the wild shenanigans in the hotel bar (not to mention the céilís on the other side of the hotel!).

I have to admit, I got quite overwhelmed the first day I ventured into Miltown proper. It’s easy to have a constant state of FOMO, constantly searching for the best session. But once I calmed down and accepted the situation, I had a lovely time at some really nice sessions.

A kitchen crammed with musicians. A line of musicians playing away. A selfie with some other musicians in a pub corner. A man playing banjo and a woman playing fiddle.

Last time we were in Miltown Malbay was three years ago …and three years before that. Maybe we’ll be back in another three years.

I don’t know, though. It kind of felt like going to the South By Southwest after it got crazy big and the host town could no longer bear the weight of the event.

Still, I thoroughly enjoyed our two-week excursion down a stretch of the Wild Atlantic Way from Donegal to Galway to Clare.

Older »