Jeremy Keith

Jeremy Keith

Making websites. Writing books. Hosting a podcast. Speaking at events. Living in Brighton. Working at Clearleft. Playing music. Taking photos. Answering email.

Journal 3225 sparkline Links 10795 sparkline Articles 87 sparkline Notes 8051 sparkline

Monday, March 9th, 2026

Testing browser support for `focusgroup`

In my previous post, I mentioned that I’ve used the web install API in production. Specifically, I’ve used it on The Session. In order to do that, I had to register for the origin trial.

I’ve just signed up for another origin trial. This time it’s for the proposed focusgroup attribute:

The focusgroup HTML attribute is a proposed declarative way to add keyboard arrow-key navigation to composite widgets such as toolbars, tablists, menus, listboxes, etc. without writing any roving-tabindex JavaScript. One attribute replaces hundreds of lines of boilerplate.

I’ve got an HTML web component on The Session called tab-controls. And yes, there’s a bunch of code in there to listen for keyboard events and respond appropriately. I would very much like to rip that code out.

So now that I’ve opted into the origin trial, I’ve added this to my HTML:

<tab-controls role="tablist" focusgroup="tablist">

If this focusgroup attribute takes off, I’ll be able to remove the role attribute but for now, it’s very much needed.

In the JavaScript for my tab-controls custom element, I need to be able to detect support for focusgroup. Here’s how I’m doing it:

if (!this.focusgroup) {
// do all my key handling stuff here
}

Here’s the important thing: don’t use getAttribute('focusgroup') to test for browser support. That will return true if the attribute is in the HTML. But the attribute will only get converted into a property if the browser understands it.

Jake has a lot more detail on the differences between attributes and properties.

Anyway, I figured I’d share that little snippet in case you too were interested in trying out the focusgroup proposal using progressive enhancement.

Installing web apps

I have websites in my dock on my computer. I have websites on the home screen of my phone. When I open these websites from the dock or from the home screen, they behave just like native apps. It’s brilliant!

But knowing that you can add a website to the dock or to the home screen remains arcane knowledge. If you don’t know it’s possible, most web browsers aren’t going to tell you it’s an option. As a site owner, you pretty much have to explain to your users what they can do.

Lately it feels like there’s been some movement to change this situation. Or, at the very least, there’s been some discussion.

As a site owner, what you want is a way for someone visiting your site to press a button to initiate the process of adding the site to the dock or the home screen.

From what I can see from the discussion, there are two contenders for how to do this: BeforeInstallPromptEvent versus navigator.install.

I’ve used both APIs in production, so I’d like to offer my balanced feedback on both:

  • BeforeInstallPromptEvent sucks.
  • navigator.install rocks.

To add more detail…

The BeforeInstallPromptEvent API relies on you capturing and delaying an event that may or not fire at all.

Based on some arbitrary heuristics, Chrome—for example—will prompt the user to install the current website. This easily-dismissable prompt looks indistinguishable from a prompt to sign up to a newsletter or grant permission for cookies, so most people dismiss it. The idea with BeforeInstallPromptEvent is that you capture that prompt, prevent it from prompting, and then release it when you think it’s an appropriate time.

If you think it takes mental gymnastics to understand that, just imagine what it’s like trying to implement it!

The whole thing rests on this flawed idea of an install prompt being shown when certain conditions are met. Other browser vendors rightly point out that users should be able to install any website they want. Ideally it should have a manifest file. But making a service worker a requirement is a step too far (and I say that as someone who literally wrote a book about service workers).

Contrast that with the Web Install API, AKA navigator.install.

Based on a user interaction—like a click on a button—the browser initiates the installation process. The user still has to confirm they want to do this, of course. You know how geolocation or web notifactions work? It’s like that. You can’t trigger any of those APIs without the user’s permission.

That’s it. No contest.

It would be absolutely wonderful if more browsers supported navigator.install. It would be a pain in the ass if they decided to support BeforeInstallPromptEvent instead.

The Artisanal Web | Another Rodeo

I feel very seen here. This describes how I built The Session:

There are still people building the web by hand, very much like we did it in the early days. They know all about what’s possible using modern tooling, yet they choose to expend their time and attention to the craft of doing it by hand. They care about the craft, and they care about what they’re making. They believe in their unique skill and vision over engagement strategies and analytics and content algorithms. They don’t need a platform, or they’ll build their own.

Sunday, March 8th, 2026

Thursday, March 5th, 2026

LLMs Are Antithetical to Writing and Humanity

If you’re dyslexic and just trying to communicate more clearly in writing, or you’ve got a bullshit job and you just want to get your bullshit job’s bullshit tasks out of the way so you can move on to more meaningful endeavors, or at least move past the day-to-day slog that permeates your workday and serves no real purpose other than to pay the bills, then I cede; I cannot fault you.

But if, say, you’re a “writer” and you’re using an LLM to “help you” “write” or “think” because it’s easier and takes less time and thought, then I stand my ground; I can and do fault you.

Wednesday, March 4th, 2026

Feedback

If you wanted to make a really crude approximation of project management, you could say there are two main styles: waterfall and agile.

It’s not as simple as that by any means. And the two aren’t really separate things; agile came about as a response to the failures of waterfall. But if we’re going to stick with crude approximations, here we go:

  • In a waterfall process, you define everything up front and then execute.
  • In an agile process, you start executing and then adjust based on what you learn.

So crude! Much approximation!

It only recently struck me that the agile approach is basically a cybernetic system.

Cybernetics is pretty much anything that involves feedback. If it’s got inputs and outputs that are connected in some way, it’s probably cybernetic. Politics. Finance. Your YouTube recommendations. Every video game you’ve ever played. You. Every living thing on the planet. That’s cybernetics.

Fun fact: early on in the history of cybernetics, a bunch of folks wanted to get together at an event to geek about this stuff. But they knew that if they used the word “cybernetics” to describe the event, Norbert Wiener would show up and completely dominate proceedings. So they invented a new alias for the same thing. They coined the term “artificial intelligence”, or AI for short.

Yes, ironically the term “AI” was invented in order to repel a Reply Guy. Now it’s Reply Guy catnip. In today’s AI world, everyone’s a Norbert Wiener.

The thing that has the Wieners really excited right now in the world of programming is the idea of agentic AI. In this set-up, you don’t do any of the actual coding. Instead you specify everything up front and then have a team of artificial agents execute your plan.

That’s right; it’s a return to waterfall. But that’s not as crazy as it sounds. Waterfall was wasteful because execution was expensive and time-consuming. Now that execution is relatively cheap (you pay a bit of money to line the pockets of the worst people in exchange for literal tokens), you can afford to throw some spaghetti at the wall and see if it sticks.

But you lose the learning. The idea of a cybernetic system like, say, agile development, is that you try something, learn from it, and adjust accordingly. You remember what worked. You remember what didn’t. That’s learning.

Outsourcing execution to machines makes a lot of sense.

I’m not so sure it makes sense to outsource learning.

Tuesday, March 3rd, 2026

Will There Ever Be Another You by Patricia Lockwood

Patricia Lockwood’s No One Is Talking About This knocked me for six when I read it back in 2022:

It’s like a slow-building sucker punch.

Like my other favourite book of that year—A Ghost In The Throat by Doireann Ní Ghríofa—it’s hard to classify. I think it’s autofiction. Not quite autobiography. Not quite fiction.

Will There Ever Be Another You is also autofiction. I think. It might also be poetry (which shouldn’t be surprising as Patricia Lockwood is a poet after all).

I can’t say that this one had the same emotional impact of No One Is Talking About This for me but then again, very little could.

The writing feels very impressionistic, with each chapter trying on a different mode. It’s kinda Joycean …if James Joyce was stuck indoors during a global pandemic.

The narrative—such as it is—revolves around The Situation from 2020 onwards. That was a surreal bizarre time so it makes sense that this is a surreal bizarre book.

I think I liked it. I can’t quite tell. I just let the language wash over me.

Buy this book

Monday, March 2nd, 2026

The state of State Of The Browser

I went to State Of The Browser in London on the weekend. It was great!

I mean, it’s always great but this year the standard felt really high. All the talks were top quality. I’ve been at events with ticket prices a literal order of magnitude greater but with quality nowhere near this level.

Bramus got the ball rolling with an excellent presentation on CSS anchor positioning. Cassie closed the day with a great fun talk, making a game in the browser. In between we had accessibility, progressive enhancement, and other favourite topics of mine.

State Of The Browser isn’t just about the talks though. It’s very much a community event. For me, it’s like an annual get-together with some lovely people that I only get to see once a year.

But it’s not just a bunch of people who already know each other. Dave got a show of hands from people attending for the first time and it looked to me like around half the audience. That’s what you want at an event—a mix of the old and the new, the familiar and the exciting.

A personal highlight for me was spending lunchtime talking in Irish with my friend Paul from Ti.to. Bhain mé an-taitneamh as an deis Gaeilge a labhairt!

Dave handed over MC duties to Jake this year but he did do the opening and closing remarks. He’s always really, really supportive of other community events and encouraged everyone to go to Web Day Out.

He also pleads with people to buy their conference tickets early (it really does help us conference organisers sleep better) but if you’ve left it this late, you’re lucky that tickets are still available.

If you liked State Of The Browser, you’re going to like Web Day Out. And if you missed State Of The Browser and you wished you could’ve been there, you can make up for it by coming to Web Day Out.

The two events have a lot in common. Great talks, great people, and no mention of large language models.

I don’t know if it was a deliberate policy by Dave, but it felt so good to spend a day at a technology conference that wasn’t dominated by The Hype.

There were a few bits of slop in the slides of the first two talks (which always makes me cringe and wince—I crince) and Cassie threw some subtly hilarious shade during her presentation, but apart from that, the day was gloriously free of the A and the I.

No doubt some people will think that’s little more than sticking our collective head in the sand, but when the sand is this lovely, I’m okay with it.

Tickets for State Of The Browser 2027 are already on sale. Do what Uncle Dave says and get your ticket nice and early.

The nature of the job

Large language models help you build the thing faster, which is the primary end goal for your company but only sometimes for you. My primary goal might be to build the thing faster, but it also might be to learn something durably, to enjoy the work, to look forward to Monday.

I don’t like the mental fragility of not fully understanding how my own code works, where AI-generated code is “mine” in that it’s attributed to me in the git blame and I’m its maintainer going forward.

Sunday, March 1st, 2026

Friday, February 27th, 2026

But the soul is a floor. It is there to bear us up and keep us standing, not merely to be clean.

— Patricia Lockwood, Will There Ever Be Another You

Wednesday, February 25th, 2026

Older »