The Blogroll

From: Boagworld

Marketing UX Within Your Organization

Learn guerrilla marketing tactics to raise UX awareness and shift your organization's culture without a big budget.

From: Meyerweb

Custom Asidenotes

In which I turn inline asides into robustly enhanced sidenotes with CSS and just a touch of JS.

From: Stuff & Nonsense

Getting creative with small screens

Yours truly over at CSS Tricks: “Over the past few months, I’ve explored how we can get creative using well-supported CSS properties. Each article is intended to nudge web design away from uniformity, toward designs that are more distinctive and memorable. One bit of feedback deserves a follow up.”

Read Getting creative with small screens.

From: Codepen

415: Babel Choices

Robert and Chris hop on the show to talk about choices we’ve had to make around Babel. Probably the best way to use Babel is to just use the @babel/preset-env plugin so you get modern JavaScript features processed down to a level of browser support you find comfortable. But Babel supports all sorts of plugins, […]

From: Adactio

Cryosleep

On the last day of UX London this year, I was sitting and chatting with Rachel Coldicutt who was going to be giving the closing keynote. Inevitably the topic of converstation worked its way ’round to “AI”. I remember Rachel having a good laugh when I summarised my overall feeling:

I kind of wish I could go into suspended animation and be woken up when all this is over and things have settled down one way or another.

I still feel that way. Like Gina, I’d welcome a measured approach to this technology. As Anil puts it:

Technologies like LLMs have utility, but the absurd way they’ve been over-hyped, the fact they’re being forced on everyone, and the insistence on ignoring the many valid critiques about them make it very difficult to focus on legitimate uses where they might add value.

I very much look forward to using language models (probably small and local) to automate genuinely tedious tasks. That’s a very different vision to what the slopagandists are pushing. Or, like Paul Ford says:

Make it boring. That’s what’s interesting.

Fortunately, my cryosleep-awakening probably isn’t be too far off. You can smell it in the air, that whiff of a bubble about to burst. And while it will almost certainly be messy, it’s long overdue.

Paul Ford again:

I’ve felt so alienated from tech over the past couple of years. Part of it is the craven authoritarianism. It dampens the mood. But another part is the monolithic narrative—the fact that we live in a world where there seem to be only a few companies, only a few stories going at any time, and everything reduces to politics. God, please let it end.

From: Meyerweb

Parenthetical Asidenotes

In which I turn inline asides into sidenotes, but not in a way anyone should actually use.

From: Boagworld

The Psychology of Ethical E-commerce: How to Help Customers Buy (Without Manipulation)

Your customers want to buy, but you keep accidentally stopping them. Four psychological principles that remove barriers without manipulation.

From: Jim Nielsen

Don’t Forget These Tags to Make HTML Work Like You Expect

I was watching Alex Petros’ talk and he has a slide in there titled “Incantations that make HTML work correctly”.

This got me thinking about the basic snippets of HTML I’ve learned to always include in order for my website to work as I expect in the browser — like “Hey I just made a .html file on disk and am going to open it in the browser. What should be in there?”

This is what comes to mind:

<!doctype html>
<html lang="en">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">

Why each?

doctype

<!doctype html>

Without <!doctype html>, browsers may switch to quirks mode, emulating legacy, pre-standards behavior. This will change how calculations work around layout, sizing, and alignment.

<!doctype html> is what you want for consistent rendering. Or <!DOCTYPE HTML> if you prefer writing markup like it’s 1998. Or even <!doCTypE HTml> if you eschew all societal norms. It’s case-insensitive so they’ll all work.

html lang

<html lang="en">

Declare the document’s language. Browsers, search engines, assistive technologies, etc. can leverage it to:

  • Get pronunciation and voice right for screen readers
  • Improve indexing and translation accuracy
  • Apply locale-specific tools (e.g. spell-checking)
  • And more…

Omit it and things will look ok, but lots of basic web-adjacent tools might get things wrong. Specifying it makes everything around the HTML work better and more accurately, so I always try to remember to include it.

meta utf-8

This piece of info can come back from the server as a header, e.g.

return new Response(
    "<!doctype html><h1>Hello world</h1>",
    {
        status: 200,
        headers: { "Content-Type": "text/html; charset=utf-8" },
    }
);

But I like to set it in my HTML, especially when I’m making files on disk I open manually in the browser.

<meta charset="utf-8">

This tells the browser how to interpret text, ensuring characters like é, ü, and others display correctly.

So many times I’ve opened a document without this tag and things just don’t look right — like my smart quotes.

For example: copy this snippet, stick it in an HTML file, and open it on your computer:

<!doctype html>
<h1>Without meta utf-8</h1>
<dl>
  <dt>Smart quotes</dt>
  <dd>“” and ‘’</dd>
  <dt>Symbols</dt>
  <dd>©, ™, ®, etc.</dd>
  <dt>Ellipsis</dt>
  <dd></dd>
  <dt>Emojis</dt>
  <dd>👍</dd>
  <dt>Non-latin characters</dt>
  <dd>é, ñ, etc.</dd>
</dl>

Things might look a bit wonky. But stick a <meta charset="utf-8"> tag in there and you’ll find some relief.

Meta viewport

<meta name="viewport" content="width=device-width,initial-scale=1.0">

Sometimes I’ll quickly prototype a little HTML and think, “Great it’s working as I expect!” Then I go open it on mobile and everything looks tiny — “[Facepalm] you forgot the meta viewport tag!”

Take a look at this screenshot, where I forgot the meta viewport tag on the left but included it on the right:

Two screenshots of a basic HTML with an h1 tag that says “Hello world” that are side-by-side. The one on the left looks like it’s zoomed way out becuase it’s missing the meta viewport tag. The one on the right looks like you expect.

That ever happen to you? No, just me? Well anyway, it’s a good ‘un to include to make HTML work the way you expect.

Last But Not Least…

I know what you’re thinking, I forgot the most important snippet of them all for writing HTML:

<div id="root"></div>
<script src="bundle.js"></script>

Lol.


Reply via: Email · Mastodon · Bluesky

From: Adactio

Responses

I had a very pleasant experience last week while I was reading through the RSS feeds I’m subscribed to. I came across two blog posts that were responding to blog posts of my own.

Robin Sloan wrote a post clarifying his position after I linked to him in my post about the slipperiness of the term “AI”.

Then Jim Nielsen wrote a deliciously satirical piece in response to my pithy little parable about research.

I love it when this happens!

Elizabeth Spiers recently wrote a piece called What Made Blogging Different?:

And if they wanted to respond to you, they had to do it on their own blog, and link back. The effect of this was that there were few equivalents of the worst aspects of social media that broke through.

It’s so true. I feel like a response from someone’s own website is exponentially more valuable than a response on Bluesky, Mastodon, Instagram, or any other social media platform.

Don’t get me wrong: I absolutely love the way that Brid.gy will send those social-media responses right back here to my own site in the form of webmentions. It also pings me whenever someone likes or shares a post of mine. But I’ve noticed that I’m not that interested in those anymore.

Maybe those low-investment actions were carried over from the old days of Twitter just because that’s the way things were always done, without us really asking whether they serve much purpose.

Right now I accept these likes and shares as webmentions. I display a tally of each kind of response under my posts. But I’m not sure why I’m doing it. I don’t particularly care about these numbers. I’m pretty sure no one else cares either.

If I cared, then they’d be vanity metrics. As it is they’re more like zombie metrics. I should probably just put them out of their misery.

From: Stuff & Nonsense

Ambient animations in web design: Practical applications (Part 2)

Yours truly over at the Smashing Magazine: “Ambient animations are subtle, slow-moving details that add atmosphere without stealing the show. In part two of his series, web design pioneer Andy Clarke shows how ambient animations can add personality to any website design.”

Read Ambient animations in web design: Practical applications (Part 2)

From: Stuff & Nonsense

Can you catch ’em all?

I’d been tinkering with animations last week and wondered what else I could do with my Magnificent 7 characters. I love surprising people with hidden Easter Eggs, so I decided to use them in a little hidden game.

Press the mysterious-looking question mark under any of the animated graphic banners, and a collection of wanted posters pops up in a dialog. One of them is catchable. Press the button to capture him and collect the reward. Only one of the characters is catchable at a time, and there’s a different character to capture on each page.

Wanted posters
My complete series of wanted posters

I started building the game by making a black-and-white wanted poster version of each character’s face. These are SVGs and optimised; each weighs around 8kb.

Wanted poster version of each character’s face

Then I made a torn paper border, which weighs less than 1kb, so all the graphics combined weigh more than 50kb. I really love SVG.

Six SVG graphics, weighing in at just 50kb

Once I had all the outlaws staring back at me, I needed to present them in a way that felt like part of the site rather than a separate element. A <dialog> turned out to be perfect for that. It contains a header and a placeholder for the posters:

<dialog class="game-dialog">
 <button id="close-dialog">×</button>

 <header class="game-header">
 […]
 </header>

 <div class="game-content">
 <div id="posters-container">
 <!-- posters -->
 </div>
 </div>
</dialog>

A script then creates each of the posters:

<div class="game-poster">
<p class="status">[…]</p>
 <div class="game-svg">
  <svg>[…]</svg>
 </div>
<p class="game-reward">[…]</p>
</div>

It adds a data- attribute for each poster, plus another class attribute if the character has been caught:

<div class="game-poster game-captured" data-id="1">
 […]
</div>

I turned my attention to writing the CSS, starting with the dialog element. It fills 80% of the viewport width and 90% of its height and is centered horizontally and vertically:

.game-dialog {
height: 90vh;
max-width: 1200px;
position: fixed;
top: 50%;
transform: translate(-50%, -50%);
width: 80vw; }

When the dialog is open, the ::backdrop is slightly transparent to allow a hint of the page behind to peek through:

.game-dialog::backdrop {
background-color: #161d1a;
opacity: .75; }

With the dialog and its ::backdrop working, I could focus on how the posters should look and behave. The posters needed to look like they’ve been tacked to a wall, while still adapting to different screen sizes.

Posters grid

On small screens, the posters are arranged in a horizontally scrolling panel.

Small screen horizontal scrolling

So I placed them into a grid container with six columns:

#posters-container {
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 1rem;
max-width: 100%;
overflow-x: auto;
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch; }
Large screen grid layout

For larger screens, I reduced the grid to three columns:

@media screen and (min-width: 64em) {
#posters-container {
grid-template-columns: repeat(3, 1fr);
overflow-x: visible;
max-width: none; }
}

Wanted posters

The posters themselves have a torn-paper border applied with border-image, one of the least-used CSS properties:

.game-poster {
border-image-slice: 40 fill;
border-image-width: 40px;
border-image-repeat: stretch;
border-image-source: url("[…]");
border-style: solid; }
Large screen grid layout with rotations

Finally, to break the rigidity of the grid, I rotated some of the posters:

.game-poster {
rotate: 0deg; }

.game-poster:nth-of-type(1),
.game-poster:nth-of-type(5) {
rotate: -2deg; }

.game-poster:nth-of-type(3) {
rotate: 2deg; }

Now that the posters looked the part, it was time to add interactivity. A few subtle animations can turn what’s essentially a static grid into a design that feels tactile.

Animations and interactions

Elements that respond to someone’s actions can help elevate what would otherwise be a static design. So first I reset those rotations on :hover:

.game-poster {
rotate: 0deg;
scale: 1;
transition: all var(--animate-duration-faster) ease-in; }

.game-poster:hover {
rotate: 0deg; }
Large screen grid layout with interactions

Then—using one of my favourite :has techniques—I reduced the size of the posters except for the one being hovered over:

#posters-container:has(.game-poster:hover) .game-poster:not(:hover) {
scale: .95; }

Finally, to make a poster shake when someone presses the capture button, I defined a shaking animation and applied it to a poster when it contains an :active capture button:

@keyframes poster-shake {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(-1.5deg); }
75% { transform: rotate(1.5deg); }
}

.game-poster:has(.game-capture:active) {
animation: poster-shake .2s ease-in-out infinite; }

With the animations in place, the next step was to show which characters had already been caught.

Captured stamp

Each poster contains a class attribute which indicates whether a character has been captured. It also includes a status paragraph with values including “game-available”, “game-captured”, and “game-wanted”:

<div class="game-poster captured">
<p class="status game-captured">[…]</p>
[…]
</div>

When a character is available to capture or is just wanted, this stamp is included at the top of a poster.

Wanted poster with captured stamp

But once they’ve been caught, this status turns into a red rubber stamp across the poster. For this, I styled the status stamp, positioned, then rotated it on the poster:

.game-poster.captured {
position: relative; }

.status.game-captured {
background-color: rgba(230,250,240,.75);
border: 5px solid var(--game-accent);
border-radius: 5px;
color: rgba(90,10,25,.75);
left: 10%;
padding: 1rem;
position: absolute;
rotate: -30deg; }

Eyes blinking

I’ve written about ambient animations a fair bit recently (1, 2) and wanted to add a few subtle animations to my posters to indicate which characters are available and those who have been captured. I decided to do this by opening and closing their eyes.

Closed eyelids paths

First, I added extra paths for each character’s closed eyelids into their SVG:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1800 1800">
<g>[…]</g>
<path class="game-eyelids" d="[…]"/>
</svg>

Each poster has a data-id and includes its character’s status:

<div class="game-poster" data-id="1">
<p class="status game-available">Capture this outlaw</p>
<svg>[…]</svg>
</div>

When a character is available to be caught, I change the eyelid opacity to 0 and apply a blinking animation:

.game-poster:has(.status.game-available) .game-eyelids {
animation: eyelids 4s infinite;
opacity: 0; }

@keyframes eyelids {
0%, 92% { opacity: 0; }
93%, 94% { opacity: 1; }
95%, 97% { opacity: 0.1; }
98%, 100% { opacity: 0; }
}
Eyes variations

But when a character has already been captured, his eyes stay closed:

<div class="game-poster" data-id="1">
<p class="status game-captured">Captured</p>
<svg>[…]</svg>
</div>

.game-poster:has(.status.game-captured) .game-eyelids {
opacity: 1; }

Reduced motion

Not everyone experiences motion the same way. For some, even a small shake or flicker can feel distracting or disorienting. That’s why I always wrap animations inside a media query that checks for the user’s motion preferences. The prefers-reduced-motion feature lets me detect when someone’s system is set to limit motion, so I can adapt the design accordingly. I only apply the shaking animation when someone hasn’t asked for reduced motion:

@media (prefers-reduced-motion: no-preference) {

.game-poster:has(.game-capture:active) {
animation: poster-shake .2s ease-in-out infinite; }

@keyframes poster-shake {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(-1.5deg); }
75% { transform: rotate(1.5deg); }
}
}

This means the posters stay still for anyone who prefers less motion, while others still see the playful shake when they hit “Capture.”

Rewarding curiosity

I’ve always believed that the web should reward curiosity. Hiding this little Magnificent 7 game beneath my banners isn’t about gamification or engagement metrics, it’s a nod to the early web, when people built weird things for their own amusement.

Technically, this project reminded me why I still love SVG. The fact that I can fit my characters, a torn-paper frame, and all the surrounding interaction into less than 150kb still feels magical.

From: Zeldman

Receipts: a brief list of prominent articles proclaiming the death of the web.

They say AI will replace the web as we know it, and this time they mean it. Here follows a short list of previous times they also meant it, starting way back in 1997. Wired: March 1, 1997: “You can kiss your web browser goodbye” – Kevin Kelly and Gary Wolf, The Big Story. Inspired by […]

The post Receipts: a brief list of prominent articles proclaiming the death of the web. appeared first on Jeffrey Zeldman Presents.

From: Jim Nielsen

Everything Is Broken

Chris Coyier wrote about it.

Now it’s my turn.

Last week I’m flying home.

My flight gets delayed in air, then lands late so I miss my connecting flight…

[Skip over all the stuff about airline customer support, getting rebooked, etc.]

It’s ~10pm and I’m stranded overnight. I need a last-minute hotel room.

I figure I’ll try HotelTonight because that’s their shtick, right? “Incredible last-minute hotel deals” says their homepage hero banner.

I find the closest hotel, click “Purchase” it takes me to checkout, I do the whole Apple Pay thing, then it says “failed to book” because there are no more rooms left.

Ok? Would’ve been nice to know that before going through all the checkout stuff, but ok. I’ll find another.

Two more hotels, same deal. Click through, checkout, blah blah blah, payment won’t go through. It says there are no more rooms left.

No I’m getting frustrated. I’ll try one more time…

Same flow. Finally! Payment goes through. Confirmation number and all — I’m good to go!

I leave the airport and get a rideshare to the hotel.

Go up to the desk. “Yes, I’m checking in please.” They ask for my name. I give it.

They can’t find me.

“Oh, no…” I think.

“Do you have a reservation number?”

Hell yes I do! Right here in the email HotelTonight sent me.

I give it to them.

It’s not in their system.

“Ok well, can you get me a room?”

Nope, they are completely full for the night.

Knowing that I booked through a third-party system, and it’s not in the first-party system, I know there’s no chance I’m getting a room.

So now it’s 10:30pm. I’m in the lobby of the hotel for which I have a bogus confirmation and I begin my search for the next-closest hotel.

I know at this point I’m not using anything internet-based to make a reservation. Over-the-phone only!

I call a bunch of nearby hotels. Every one is giving me their automated phone system — “If you want to book a reservation, press 1. If you want to…”

I sit through the first couple calls and eventually connect to a human: “Do you have any rooms available tonight?”

“Yes sir, can you confirm which location you are calling for?” They don’t know because this isn’t someone at the hotel. This is a call center somewhere.

I quickly realize this ain’t gonna work.

New rule: if the number online is a centralized number that gives me your automated phone system, I’m out. Next hotel.

I just need to connect to a human at a front desk.

I call maybe 12 hotels. About two give me humans at the front desk. Both of those are booked solid for the night.

But you know what? Props to those hotels for having direct lines to a human. YUGE props.

A direct line to a human feels like the ultimate luxury at this point.

“Hey you got any rooms tonight? No? That’s ok. I appreciate you being there to answer my call, friend. You have a good night.”

Eventually I find a hotel 20 minutes down the road where somebody at the front desk answers and says they have a room. “It’s twice the cost since it’s our last room.” I don’t care, I book it. This is a phone call with a person at the front desk, I know I’m getting a room.

Postscript: I also spent several days going back and forth with a rep at HotelTonight to get a refund. I guess it’s hard to prove that their system sold me a room that did not exist.


Reply via: Email · Mastodon · Bluesky

From: Chris Coyier

Tom Burkert on controlling what he reads, through RSS of course. If I’m in the mood for something lighter, I can just look into my “Fun” folder to check out new stuff from The Oatmeal or xkcd. If I feel like reading something more thoughtful, I’d dive into my “Reads” folder for The Marginalian or Sentiers. Feeling like catching up on […]

October 24, 2025, 5:04 pm >>

From: Jim Nielsen

AI Browsers: Living on the Frontier of Security

OpenAI released their new “browser” and Simon Willison has the deets on its security, going point-by-point through the statement from OpenAI’s Chief Information Security Officer. His post is great if you want to dive on the details. Here’s my high-level takeaway:

Everything OpenAI says they are doing to mitigate the security concerns of an LLM paired with a browser sounds reasonable in theory. However, as their CISO says, “prompt injection remains a frontier, unsolved security problem”. So unless you want to be part of what is essentially a global experiment on the frontier of security on the internet, you might want to wait before you consider any of their promises “meaningful mitigation”.

(Aside: Let’s put people on the “frontier” of security for their daily tasks, that seems totally fine right? Meanwhile, Tom MacWright has rationally argued that putting an AI chatbot between users and the internet is an obvious disaster we’ll all recognize as such one day.)

What really strikes me after reading Simon’s article is the intersection of these two topics which have garnered a lot of attention as of late:

  1. npm supply chain attacks
  2. AI browsers

This intersection seems primed for exploitation, especially if you consider combining different techniques we’ve seen as of late like weaponizing LLM agents and shipping malicious code that only runs in end-users’ browsers.

Imagine, for a second, something like the following:

You’re an attacker and you stick malicious instructions — not code, mind you, just plain-text English language prose — in your otherwise helpful lib and let people install it.

No malicious code is run on the installing computer.

Bundlers then combine third-party dependencies with first-party code in order to spit it out application code which gets shipped to end users.

At this point, there is still zero malicious code that has executed on anyone’s computer.

Then, end users w/AI browsers end up consuming these plain-text instructions that are part of your application bundle and boom, you’ve been exploited.

At no point was any “malicious code” written by a bad actor “executed” by the browser engine itself. Rather, it’s the bolted on AI agent running alongside the browser engine that ingests these instructions and does something it obviously shouldn’t.

In other words: it doesn’t have to be code to be an exploit. Plain-text human language is now a weaponizable exploit, which means the surface for attacks just got way bigger.

But probably don’t listen to me. I’m not a security expert. However, every day that voice in the back of my head to pivot to security gets louder and louder, as it’s seemingly the only part of computer science that gets worse every year.


Reply via: Email · Mastodon · Bluesky

From: Codepen

414: Apollo (and the Almighty Cache)

Rachel and Chris jump on the show to talk about a bit of client-side technology we use: Apollo. We use it because we have a GraphQL API and Apollo helps us write queries and mutations that go through that API. It slots in quite nicely with our React front-end, providing hooks we use to do […]

From: Boagworld

Culture Hacking: Shaping a UX-Friendly Organization

Four practical approaches to embed UX into your organization's culture, from hackathons to celebrating wins.

From: Dave Rupert

Vibe Check №40

Another hot Fall in Texas. No notable rain since June. Air-conditioning humming. Water bill up. Backyard is a dust bowl from the dogs tearing up all the grass.

My schedule is a constant loop of kid activities; school, cheer, baseball, guitar, birthday parties, randomized school holidays, etc. I call it “The Luge”. A family bobsled ride downhill with no meaningful breaks until Christmas. There’s been some real highlights like nights at the ballpark, singing through the K-Pop Demon Slayers album with a car full of girlie-pop tweenagers, and watching my son play his first rock show. But personally, there’s been an overwhelming cloud through it all.

I’ve been grumpy, like super grumpy

I’ve been in an incurably foul mood for the last month. I’m almost not sure this vibe-check is worth putting out into the world, but not all seasons in life are bangers. If you want to avoid the mire of my emotional dysfunction, feel free to bounce on this post.

I think what compounds this problem is that I feel this isn’t my natural state (despite what my resting scowl would suggest). Sure there’s bouts of depression and some generalized anxiety mixed in there, but it feels against my core.

Politics, ugchk

If you’re a person who can divorce the rise of authoritarianism from your day-to-day emotional well-being… wow. I’m not that person. Each day unveils a new horror of economic anxiety, children being zip-tied in raids, parents abducted in school drive lines, dark money funding open corruption, feckless judges, and meme-driven political discourse. This administration adds a lime green background of radioactive stress to my life.

Anyways, this whole situation is contributing to my bad mood.

Hypertense

I’m still untangling the Gordian Knot of stress, weight, and ADHD in my life. I switched my ADHD meds over the summer to “baby meth”. It’s super effective! But that change triggered some heightened concern from my doctors about my blood pressure.

Ten years ago, I got diagnosed with White Coat Syndrome; a condition where your body panics around anyone in a lab coat and your blood pressure skyrockets. Whether it’s doctors, dentists, optometrists –you name it– I can see their eyes pop out of their head when the little arm cuff says “This person will probably die in this chair.”

My doctor didn’t want to roll the dice on “probably not dying.” He prescribed hypertension medicine which is medicine you’re on for the rest of your life unless some radical life change event happens; extreme weight-loss, becoming vegan (?), a trust fund appears, etc.

Without oversharing here, the psychological aspect of this is the hardest. There’s a feeling of shame attached to it that I’ve fucked my body up by being a sedentary computer boy; like I’ve sacrificed my body for capitalism and now I get to use capitalism and the inefficient American healthcare system to buy the cure. Ugh. But it could also be genetic. Who knows.

The initial battery of tests didn’t come back as hoped. Also the medicine… It’s not very effective. A week later I was lying on a table having my kidneys scanned and arteries measured. Thankfully, it wasn’t renal hypertension (or damage/failure) but a small part of me wanted to be at the end of the medical mystery journey. Still don’t know the root cause yet, so I’ll try that radical life change approach.

Anyways, this whole situation is contributing to my bad mood.

Working out and hydrating

Pursuing radical change, I decided to set up that bike trainer I bought during the pandemic. The weather is nice enough now I can be in the garage without dying of heat stroke. As a result, I’ve managed to ride my bike nearly every day for the past month.

I’m abusing an old ADHD trick called “Task Pairing” to make it happen. It’s super effective! I pair something I need to do (workout) with something I want to do (watch YouTubes). I do this with washing dishes while I listen to audiobooks. Now instead of doomscrolling in my recliner… I’m doomscrolling on my bike, baby! What an improvement! Other than a sore coccyx, I could probably sit on the bike for hours. A nice unlock and a guilt-free way to enjoy brain rot.

But there’s the twist! After a month of riding my bike I’ve lost …. 0 pounds! I’m actually up two-to-five pounds from where I started. 😵‍💫 Someone suggested dehydration might be the problem so that day I bought one of those dumb water bottles that has timestamps on the side with encouraging affirmations that say “7:00am - Get to it”, “9:00am - Be your best”, “11:00am - You go, girl!” Hydration is great and all, but in practice it means frequent work and sleep interruptions for trips to the bathroom.

The key takeaway here is that Calories-In/Calories-Out is a fucking lie. Fuck that fat-phobic shit right into the sun. Even if it worked for you. Fuck it. Fuck it right off.

Anyways, this whole situation is contributing to my bad mood.

Artificially-induced psychosis?

We’re being “encouraged” (ahem) to use AI at work more and while I appreciate the opportunity to learn and explore, it’s chipping away at my mental health a bit. The prompt → wait → disappointment loop is dealing a form of psychic damage over time. Initial demos are a dopamine hit, but over time the context window dependably explodes. I’m not here to be a hater –if anything I’m genuinely curious about what these new fangled machines can do– but sometimes it feels like that episode of Star Trek where the Cardassians kidnapped Picard and put him in a room with four lights and told him to say there were five lights but Picard kept saying there were four lights… y’know like that. Mix in a couple projects growing in complexity and it adds up.

Anyways, this whole situation is contributing to my bad mood.

The root cause and the probable cure

I think the common thread of everything from “The Luge” to me threatening a genius computer with its life is the loss of autonomy in my schedule, my nation, my body, and my work. In Daniel Pink’s book Drive he describes the three pillars that drive people to perform at their best: autonomy, mastery, and purpose… those are all sorely lacking right now. That’s my best guess for why I’ve been in such a foul mood.

This past week I’ve hung out with friends in-person and online and that seems to have improved my mood considerably. Diner breakfast with seasonal pumpkin pancakes with my friend Zach. A small collaboration with the Frost Brothers on a big thing they’re working on. A birthday party for my friend Taylor featuring a bunch of old camping buddies admiring how our kids are all grown up now. Those connections are meaningful.

Anyways, I hope you’re doing better.

Lifeloggers hate this one weird trick…

Can you believe I’ve done forty of these vibe checks? Well here you go you number perverts.

💪 Health and Fitness

I’ve worked out everyday for the last month and lost zero pounds. That’s demoralizing. I am happy that I’ve found a form of exercise that works for my mind and body –at least for now. Task pairing my negative-impact YouTube habit with a positive-impact exercise habit feels like I’m creating a balance in the world in a local-cosmic sense.

My blood pressure is going down a bit too and it’s probably worth celebrating small wins… by getting a milkshake.

📖 Reading

Win Every ArgumentThe Dawn of EverythingThe AI ConFailure Is Not an OptionSapiensH.P. Lovecraft's The Call of CthulhuSeparation of Church and HateExtra FocusAt HomeFight OligarchySlow Down
  • Win Every Argument ★★★★ - Former MSNBC anchor Medhi Hasan shares some Oxford debate club knowledge on how to convincingly argue your point and back it up with receipts.

  • The Dawn of Everything ★★★★½ - A wonderful book that really reprogrammed a lot of inherent biases I had about “uncivilized” cultures. I never viewed Native Americans as “savages” like the history books and cowboy movies want you to believe, but… primitive? I’m almost embarassed to admit that this is what I thought anyways until I read this book and realized they were quite civilized and more advanced than us on many levels (civically and emotionally), operating on a different rule book entirely. It makes you wonder if society, without its kings, could function differently.

  • The AI Con ★★★★ - A good book. Obviously, two people very educated on the subject of AI. They’re very comfortable in their negative opinion of it. And bring receipts to back it up. It’s maybe worth another listen because I don’t quite have a fist full o’ takeaways from it.

  • Failure Is Not an Option ★★★★½ - Maybe the biggest biography I read this year but continuing my theme probing the Space Race.

  • Sapiens [In progress]

  • H.P. Lovecraft’s The Call of Cthulhu ★★★★ - I saw this book on the shelf at Kinokuniya and it called to me… it called to me saying… Cthulu Fhtagn. A manga adaptation of H.P. Lovecraft’s The Call of Cthulhu. This is my first time dipping my toe into Lovecraftian space horror and to be honest, the manga version was probably the best for me. I don’t think I would have followed or enjoyed the flashback sequences set in 1920’s rhetoric, but in manga form I was able to follow along and see the story weave together. I’m on the fence if I’ll buy more, but was was enjoyable enough that I might. The art is incredible and dark.

  • Separation of Church and Hate ★★★★ - A dig into how American Christianity is actually quite the opposite of what the Bible says. Not just some of the time, but lots of the time. If you find American Imperialist Christianity doesn’t fit your world view or your family is full of evangelical fundamentalists… this book is worth reading. One issue I had with the book –that I’ve had with books by other comedians– is when the author runs out of content, they resort to a series of one-liners to fill a chapter. It takes me out of the non-fiction.

  • Extra Focus ★★★★ - Short n’ sweet. Probably the best book I’ve read on Adult ADHD and how it impacts our time, memory, and emotional management. The major themes are all followed by a tactical “guide” chapter which has tips and tricks like creating launchpads, setting timers, or posting a sticky by the job that needs to be done. Basic advice but feels like a best-of-the-best distillation of all the brainhacks out there.

  • At Home [In progress]

  • Fight Oligarchy ★★★★½ - Bernie wraps up some his thoughts and thesis from the recent Fight Oligarchy tour. The billionaires have too much and own too much of our government. They are too organized too.

  • Slow Down [In progress]

📝 Blogging

📺 Media

Movies

  • Demon Slayer: Kimetsu no Yaiba Infinity Castle (2025) - An entire season of anime bottled into one 2.5 hour long movie. Lots of swords, blood, gore, internal monologues probing enemy weaknesses, internal monologues with gooey tears complimenting an adversary’s form and skill, flashbacks and character exposition… it’s what Demon Slayer does best.

TV

  • Murderbot (AppleTV) - Finished Season 1. I didn’t like it. Almost all the diversions from the book were unnecessary, boring, and lacked chemistry. Curious if Season 2 will be better… but I’m not holding my breath.
  • The Rookie (Hulu) - Family has been into this so I’ve caught some episodes. It’s great but not for me.

🎙 Recording

⌨️ Open source

Not much, participating in specs behind the scenes a bit.

👾 Video games

Playing casual puzzle games everyday. Also started making some games but that’s TBD.

From: Chris Coyier

Everything is Broken

Over in the ol’ ShopTalk Discord (that’s what our Patreon thingy unlocks) our editor Chris Enns was venting about some streaming gear woes. And I said: Nothing Ever Works Chris ultimately blogged the situation and used my reply as part of the title of the blog post. Then shortly after, Jason Rodriguez’s post made the […]

From: Stuff & Nonsense

More Magnificent 7 Malarkey

I had some spare time earlier this week to add a little more finesse to my Magnificent 7 animated graphics, so I added a new background to my blog pages’ illustrations, which has some hidden features.

Most of the visitors to my website come for the blog, so I decided to spice up the animated graphic by adding a full-colour Old West town background.

Adaptive SVG at three breakpoints. (Full size)

Twenty years ago, Dunstan Orchard was famous in web circles for adapting his blog illustrations to the current weather. I wanted to adjust my background to the time of day by changing its brightness and saturation.

Daytime background. (Full size)
Twilight background. (Full size)
Nighttime background. (Full size)

So I created a dark blue overlay which covers the town’s buildings.

Dark blue overlay.

Leaving gaps for light from the windows to shine through.

Overlay during dayight.
Overlay at twilight.
Overlay at Nighttime.

A simple script checks for the time of day in a visitor’s location, then appends a class attribute value (time-day, time-twilight, and time-night) to the SVG.

Phases of the moon.

Not knowing when to stop, I made ten moon-phase graphics and extended the script to include them, too. Then I added CSS rules that display the correct moon at twilight and during the night.

Lighting up the about page animation

I love including Easter Eggs in my designs, and the graphic animation on my about page seemed like the perfect candidate. So, using the same technique, I created a green overlay that covers the inside of the town jailhouse, turning it dark.

Dark green overlay.

Then I added the elements I want illuminated when the overhead light is turned on.

Illumination.

A simple script toggles class attributes on the SVG (lighting-on, lighting-off). Triggering that toggle? Well, that should remain a mystery.

Lighting off.
Lighting on.

People may never notice the moon shifting or the jailhouse lights flicking on, but you know what? That’s fine. As web designers, we talk a lot about accessibility, performance, and responsiveness, and rightly so. But entertainment matters too, even if the only person entertained is the one making the website.

From: Chris Coyier

Plates

I bought a new set the other day, after asking about it on Bluesky. This is me jotting down the good recommendations I got.

From: Adactio

Jake Archibald is speaking at Web Day Out

I’m very happy to announce that the one and only Jake Jaffa-The-Cake Archibald will be speaking at Web Day Out!

Given the agenda for this event, I think you’ll agree that Jake is a perfect fit. He’s been at the forefront of championing user-centred web standards, writing specs and shipping features in browsers.

Along the way he’s also created two valuable performance tools that I use all the time: SVGOMG and Squoosh, which has a permanent place in my dock—if you need to compress images, I highly recommend adding this progressive web app to your desktop.

He’s the man behind service workers and view transitions—two of the most important features for making websites first-class citizens on any device.

So what will he talk about at Web Day Out? Image formats? Offline functionality? Smooth animations? Something else entirely?

All will be revealed soon. In the meantime, grab yourself a ticket to Web Day Out—it’s just £225+VAT—and I’ll see you in Brighton on Thursday, 12 March 2026!

From: Boagworld

AI In UX: Achieve More With Less

A simple but powerful mental model for working with AI: treat it like an enthusiastic intern with no real-world experience. I share lessons learned from real client projects across user research, design, development, and content creation.

From: Codepen

Google Chrome & Iframe `allow` Permissions Problems

If you’re a CodePen user, this shouldn’t affect you aside from potentially seeing some console noise while we work this out. Carry on! At CodePen we have Embedded Pens which are shown in an <iframe>. These contain user-authored code served from a non-same-origin URL. We like to be both safe and as permissive as possible […]

From: Codepen

Chris’ Corner: Stage 2

We get all excited when we get new CSS features. Well, I do anyway. It’s amazing, because sometimes it unlocks something we’ve literally never been able to do before. It’s wonderful when an artist finishes a new painting, and something to be celebrated. But this is more akin to a new color dropping, making possible […]

From: Jim Nielsen

Write Code That Runs in the Browser, or Write Code the Browser Runs

I’ve been thinking about a note from Alex Russell where he says:

any time you're running JS on the main thread, you're at risk of being left behind by progress.

The zen of web development is to spend a little time in your own code, and instead to glue the big C++/Rust subsystems together, then get out of the bloody way.

In his thread on Bluesky, Alex continues:

How do we do this? Using the declarative systems that connect to those big piles of C++/Rust: CSS for the compositor (including scrolling & animations), HTML parser to build DOM, and for various media, dishing off to the high-level systems in ways that don't call back into your JS.

I keep thinking about this difference:

  • I need to write code that does X.
  • I need to write code that calls a browser API to do X.

There’s a big difference between A) making suggestions for the browser, and B) being its micromanager.

Hence the title: you can write code that will run in the browser, or you can write code that calls the browser to run.

A Few Examples

So what are the browser ‘subsystems’ I can glue together? What are some examples of things I can ask the browser to do rather than doing them myself?

A examples come to mind:

  • View transitions API (instead of JS DOM diffing and manual animation).
  • CSS transitions or @keyframes (GPU-accelerated) vs. manual JS with setInterval updates.
  • scroll-behavior: smooth in CSS vs. JS scroll logic.
  • CSS grid or flexbox vs. JS layout engines (e.g., Masonry clones).
  • <video> and <audio> elements with native decoding and hardware acceleration vs. JS media players.
  • <picture> or <img> with srcset for responsive images vs. manual image swapping logic in JS.
  • Built-in form state (formData) and validation (required, pattern, etc.) vs. JS-based state, tracking, and validation logic.
  • Native elements like <details>, <dialog>, <select>, etc., which provide built-in keyboard and accessibility behavior vs. custom ARIA-heavy components.

Going Galaxy Brain

Galaxy brain meme from top to bottom: setTimeout -> requestAnimationFrame -> document.startViewTransition -> @view-transition

The trick is to let go of your need for control. Say to yourself, “If I don’t micromanage the browser on this task and am willing to let go of control, in return it will choose how to do this itself with lower-level APIs that are more performant than anything I can write.”

For example, here are some approaches to animating transitions on the web where each step moves more responsibility from your JavaScript code on the main thread to the browser’s rendering engine:

  • setTimeout
    • JS timers, DOM manipulation, browser repaints when it can. Dropped frames.
  • requestAnimationFrame
    • Syncs to browser repaint cycle. Smooth, but you gotta handle a lot yourself (diffing, cleanup, etc.)
  • View Transitions in JS
    • JS triggers, browser snapshots and animates. Native performance, but requires custom choreography on your part.
  • View Transitions in CSS
    • Declare what you expect broadly, then let the browser take over.

It’s a scale from:

I want the most control, and in exchange I’ll worry about performance.

To:

I don’t need control, and in exchange you’ll worry about performance.

I don’t know about you, but I’d much rather hand over performance, accessibility, localization, and a whole host of issues to the experts who build browsers.

It’s Trade-offs All the Way Down

Building on the web is a set of choices:

  • Do it yourself.
  • Let the browser do it.
  • Somewhere in between.

Anytime you choose to do something yourself, you’re choosing to make a trade-off. Often that increase in control comes at the cost of a degradation in performance.

Why do it yourself? Often it’s because you want a specific amount of control over the experience you’re creating. That may be perfectly ok! But it should be a deliberate choice, not because you didn’t consider (or know) the browser offers you an alternative. Maybe it does!

So instead of asking yourself, “How can I write code that does what I want?” Consider asking yourself, “Can I write code that ties together things the browser already does to accomplish what I want (or close enough to it)?”

Building this way will likely improve your performance dramatically — not to mention decrease your maintenance burden dramatically!


Reply via: Email · Mastodon · Bluesky

From: Zeldman

My Glamorous Life: Entertaining Uncle George

Fam and I are visiting my 96-year-old Uncle George tonight. We love him. His complicated and somewhat meandering stories have been music to my daughter’s ears since she fell asleep in a cab at age six listening to him lament his wife’s death. George is my late mother’s only sibling, and the only survivor of […]

The post My Glamorous Life: Entertaining Uncle George appeared first on Jeffrey Zeldman Presents.

From: Zeldman

My Glamorous Life: Bots, Books, and Betrayal

My father was an engineer who designed robots. When I first learned what he did, I imagined the Robot from “Lost in Space,” and asked him to make me one. When I turned 13, I realized that the pick-and-place robots he designed replaced assembly-line workers, and asked how he, who’d been a socialist in his impoverished […]

The post My Glamorous Life: Bots, Books, and Betrayal appeared first on Jeffrey Zeldman Presents.

From: Boagworld

Boosting UX Influence and Perception

Why changing organizational culture toward UX takes time, patience, and subtle culture hacking—not force or quick fixes.

From: Dave Rupert

Lots to shout about in Quiet UI

From the homepage of Quiet UI, a mouse mascot in a hoodie using a laptop with the text: A UI library for the Web focusing on accessibility, longevity, performance, and simplicity

As President of Web Components, it’s my duty to publicly comment on every Web Component library and framework that exists. Today I’m taking a look at Quiet UI, a new source-available web component library soft-launched by Cory LaViska, the creator of Shoelace WebAwesome. You might be asking “another UI library? But why?” and that’s a good question, I’ll let Cory tell you in his own words

I wanted to play with bleeding edge features that weren’t available in all browsers yet… I wanted to take everything I learned from developing components over the years and challenge some ideas, try new things, and bake in opinions that I’ve traditionally veered away from. It felt liberating.

“Play” as a foundation is compelling to me. A lot of writing and ancient programming advice says “Write the thing, then throw it away and write it again” and while that sounds like an incredible waste of time, your second draft understands the problem set better than the first and you can make smarter/different decisions. And as Cory points out, the last half-decade has been a heyday for Web APIs and browser interop, which means your components can be more robust with less code. Whether you use web components or not, it’s a good time to re-evaluate your component system and do some quality-of-life upgrades.

Peeking at what’s inside the box of what Quiet UI has to offer, I’ve found some interesting concepts beyond the industry standard set of components. Let’s take a look…

Theming system

A design token theming system is pretty standard fare for a component system. Out of the box you get a generous set of harmonious static color primitives all based on color-mix() to generate a consistent palette.

A 10-step color pallette with four tiers cof colors: primary, neutral, constructive, destructive

With the static primitives, you get a set of “Adaptive Colors” for text, fill, and stroke colors. Rather than a numeric ramp, this ramp is a 5-stop vibrancy/loudness scale and each color ramp adapts to light and dark modes.

The same four-tier color pallet but only 5-steps of colors

It’s tempting to have an 11-step color ramp and then think your adaptive color ramp needs to also be 11-steps, but based on personal experience that leads to more contrast problems than it’s worth, so limiting the adaptive light/dark colors to 5-steps and the border and text ramps to 3-steps is a good idea. I applaud the restraint that went into that decision.

It’s a minor thing aspect, but naming the color collections “primary”, “neutral”, “destructive”, and “constructive” are nice, semantic –yet generic– buckets for values. It wouldn’t be too difficult to add one or two more collections for extra spice.

Restyle native elements

Quiet’s “Restyle” stylesheet has a lot of appeal to me. It’s a cross between a CSS Reset and a default stylesheet to theme native elements to look like your design system components.

An HTML form with different types of inputs all custom styled

These are all plain ol' HTML

I could see this as a nice offering so consumers of your design system can use regular ol’ HTML alongside the first-party components and it’ll all maintain the same look and feel because they’re using the same underlying token architecture.

Adding to the base theme and restyle, you also get some global CSS utilities to glue everything together.

Useful utilities

The CSS utilities are nice but Quiet UI goes a bit further and offers a handful of helpful JavaScript utilities in the form of web component wrappers.

Now, I’m the kind of idiot who wants to learn how to handwrite observers, then not use them for awhile and forget how they work, then have to re-learn observer patterns from scratch every two years… but I could see how others would not want to do that.

Abstracting away some of the more painful learning curves through a thin, declarative web component wrapper API seems like a smart decision.

Components and gimmicks galore!

Inside Quiet UI is an impressive number of components for a side project. There’s all the standard UI components like Accordion, Breadcrumbs, Cards, Dialog, etc. The documentation breaks off Form controls into its own little section, which makes sense because form-associated custom elements are a bit unique in webcomponents-land.

But what I want to call special attention to is what I will lovingly refer to as “Gimmick Components”. A gimmick sounds bad, like a cheap trick, but I mean it in the “Aww, that’s cool, they didn’t have to do that, but that’s cool” sort of way. Quiet UI bundles tons of little non-everyday, nice-to-have components into the kit. As you start digging through the LEGO bin, the mental image of what you could build starts growing…

  • Browser Frame - A one-off to frame screenshots or make a section feel more web-like.
  • Comparison - Don’t always need a responsive image compare tool, but I know I don’t want to build my own.
  • Expander - Truncation happens… and it’s nice to have a good option right out of the box.
  • Flip Card - Few know how to master this CSS-trickery.
  • Joystick - A design system with a joystick? Novel.
  • QR Code - It’s Friday and the marketing team needs a website by Monday.
  • Slide Activator - Slide to activate! In a website!
  • Sparkline - A matter of time before someone asks for a baby chart.
  • Random Content - Spicy Lorem Ipsum!
  • Timed Content - The holiday campaign goes live when you’re asleep and must end when you’re unwrapping presents with your family. And there’s a code freeze.
  • Zoomable Frame - Browse infinite canvases with ease.

And there’s a whole collection of smaller components dedicated to text formatting.

  • Bytes - This isn’t hard to do, but I’d rather have a component and call it done.
  • Countdown - 8 out of 10 cats recommend this plugin. Check it out before the timer reaches zero.
  • Fit Text - Feel like I’ve heard about this somewhere…
  • Number - I had an Intl.NumberFormat issue the other day, would have been nice not to have that issue.
  • Number Ticker - Bosses love number go up!
  • Relative Time - Again, Intl.RelativeTimeFormat… not the funnest one to get sucked into.
  • Text Mask - An old effect, but a goodie.
  • Typewriter - Taka-taka-taka-tak. Look like your favorite generative AI chat bots.

Like I said, there’s a lot of gimmicks inside of here. A lot of these are already available (or could be) as “Standalone” components, but bundled in with a consistent styling API makes it all that much nicer.

I browse a lot of design systems everyday and they’re all the same boring collection of 20-30 components with different levels of Bootstrap / Material / Tailwind / ShadCN flavoring mixed in. These types of random, not-solely utilitarian components elevate Quiet UI above the pack.

The gimmicks create an atmosphere of “Play” that’s part of Quiet UI’s foundation. It culminates into a feeling of “fun” instead of business, business, business. It ticks a box in my brain that if my UI needs some pizzazz or something a little unconventional like a countdown timer or a number ticker on a random Tuesday in November… Quiet UI might be a good base to build on. I’m seriously considering making this the default component set for all side projects going forward.

Quiet UI? Oh, that’s the fun one.

From: Stuff & Nonsense

How I fixed my Reduced Motion Broke My Layout problem

It’s incredibly important to respect people’s preferences and to ensure that any movement is turned off when they’ve set “reduced motion” in their OS settings. After adding my Magnificent 7 animations yesterday, I went back to check them with reduced motion enabled. Oh hell, my CSS grid has also stopped working, and it took me all morning to realise the issue wasn’t the grid, but how I’d structured my media queries.

I’d used this boilerplate CSS:

@media screen and (prefers-reduced-motion: reduce) {
html {
scroll-behaviour: auto;
animation-duration: 1ms !important;
animation-iteration-count: 1 !important;
transition-duration: 1ms !important; }
}

@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation: none !important;
transition: none !important; }
}

That looked fine until I noticed that when reduced motion was selected, grid layouts weren’t applied. They didn’t even appear in DevTools. It was like my whole layout was trapped inside a media query it shouldn’t be in.

Where it all went wrong

1. Two separate prefers-reduced-motion blocks

I’d written two different queries—one with screen and one without. Turns out that browsers treated them as separate layers in the cascade. Sometimes they combined, sometimes they didn’t, depending on their position in the file.

That made it possible for reduced-motion rules to override layout ones. In DevTools, it even looked like my @media (min-width:64em) rules were nested inside reduced motion, even though technically they weren’t.

2. The reduced-motion block came after my layout queries

Later in the file, I had a @media (prefers-reduced-motion: reduce) block sitting below my layout breakpoints. That meant when reduced motion was enabled, it took priority over my grid display rules:

@media (min-width: 64em) {
[role="banner"] {
display: grid;
grid-template-columns: var(--grid-compound); }
}

Even though my motion reset didn’t touch layout properties, the browser’s cascade flattened them together, and the result was no grid.

3. My animation reset wasn’t truly global

I’d disabled transitions on *, but only changed scroll behaviour on html:

html { scroll-behavior: auto; }
*, *::before, *::after {
  animation: none !important;
  transition: none !important; }

That meant nested containers—like scrollable divs or SVGs—could still animate or scroll smoothly. So even though the top of the CSS respected reduced motion, some other sections didn’t.

4. My motion reset didn’t really stop animations

Setting an animation’s duration to 1ms makes it very, very short, but it’s not the same as disabling it altogether. It still fires, just instantly. That can trigger layout reflows, flashes, or elements appearing mid-animation.

5. Layout transforms were tied to those animations

Some layout elements use transforms inside animations. When reduced motion shortened those animations to 1ms, the transform started and ended before the layout had fully rendered. That left my grid invisible until a resize or refresh.

The fix: isolate motion resets

Although it took a while to figure out, the solution turned out to be pretty simple—move all motion resets to a single, self-contained section near the top of the stylesheet.

/* REDUCE MOTION GLOBALLY */

@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto !important; }

*, *::before, *::after {
animation: none !important;
transition: none !important;
scroll-behavior: auto !important; }
}

@media (prefers-reduced-motion: no-preference) {
html { scroll-behavior: smooth; }
}

That was it. No more layout interference.

Why it works

By isolating motion resets early in the cascade, I:

  • Keep layout media queries separate so breakpoints, flex, grids keep working
  • Avoid nested screen and rules, which can confuse browsers (and me)
  • Disable motion globally

So, now I think of my stylesheets in “layers”:

  1. Global styles
  2. Reduced motion reset
  3. Layout media queries
  4. Components and animations

That way, the reduced-motion section never affects my layout. Here’s the pattern I’ll follow from now on:

  1. Put reduced-motion reset near the top
  2. Keep it separate from grid or breakpoint media queries
  3. Never mix layout and motion in the same block

That way, my designs will respect accessibility settings without breaking the layout as they’ve done before.

From: Codepen

413: Still indie after all these years

We’re over 13 years old as a company now. We decide that we’re not a startup anymore (we’re a “small business” with big dreams) but we are still indie. We’ve seen trends come and go. We just do what we do, knowing the tradeoffs, and plan to keep getting better as long as we can. […]

From: Adactio

Reasoning

Tim recently gave a talk at Smashing Conference in New York called One Step Ahead. Based on the slides, it looks like it was an excellent talk.

Towards the end, there’s a slide that could be the tagline for Web Day Out:

Betting on the browser is our best chance at long-term success.

Most of the talk focuses on two technologies that you can add to any website with just a couple of lines of code: view transitions and speculation rules.

I’m using both of them on The Session and I can testify to their superpowers—super-snappy navigations with smooth animations.

Honestly, that takes care of 95% of the reasons for building a single-page app (the other 5% would be around managing state, which most sites—e-commerce, publishing, whatever—don’t need to bother with). Instead build a good ol’-fashioned website with pages of HTML linked together, then apply view transitions and speculation rules.

I mean, why wouldn’t you do that?

That’s not a rhetorical question. I’m genuinely interested in the reasons why people would reject a simple declarative solution in favour of the complexity of doing everything with a big JavaScript framework.

One reason might be browser support. After all, both view transitions and speculation rules are designed to be used as progressive enhancements, regardless of how many browsers happen to support them right now. If you want to attempt to have complete control, I understand why you might reach for the single-page app model, even if it means bloating the initial payload.

But think about that mindset for a second. Rather than reward the browsers that support modern features, you would instead be punishing them. You’d be treating every browser the same. Instead of taking advantage of the amazing features that some browsers have, you’d rather act as though they’re no different to legacy browsers.

I kind of understand the thinking behind that. You assume a level playing field by treating every browser as though they’re Internet Explorer. But what a waste! You ship tons of uneccesary code to perfectly capable browsers.

That could be the tagline for React.

From: Stuff & Nonsense

Say hello to my Magnificent 7

When I started writing for CSS-Tricks, Geoff and I talked about what to put in my bio. He called me a “veteran” web designer. Geez, I felt old enough. So we settled on “pioneer.” That word stuck—and it’s what inspired the new set of animated pioneers now roaming my website.

Pioneers of the Old West
Doyle Malarkey and the pioneers of the Old West

I’ve had animated SVG characters on my website for years, and I like to change them up once in a while. Last time, I went back to a Madness-inspired set of nutty boy characters, which were based on artwork I’d commissioned from Josh Cleland. This time, I planned to play on the pioneer theme with seven magnificent Old West characters, drawn in the style of Hanna-Barbera cartoons.

My Magnificent 7
My Magnificent 7

I struggle with poses and, for the life of me, can’t draw hands. But after a lot of cussing, I managed to sketch outlines of my characters in Procreate on my iPad Pro. I’m more confident drawing paths in Sketch, so I relaxed once I had my vector outlines organised and could concentrate on colouring.

Press for large version

I wanted the colours of my pioneers to be consistent, and for the browns, greys, and reds in each character to match, so I sampled colours from a few of my Toon Title recreations.

Sampled colours
Sampled colours

Breaking the characters into separate SVG files let me rearrange and resize them for each animated graphic.

The more time I’ve spent studying cartoon backgrounds, the more I appreciate the work of artists like Lawrence (Art) Goble. I took inspiration from Hanna-Barbera cartoons, which use a limited palette of colours, simple, solid shapes, and just the right amount of detail to avoid dominating a scene.

Hanna-Barbera background
Hanna-Barbera background

I made five backgrounds, including a desert scene, a hardware store, a jailhouse and saloon interior, and a station.

Five Hanna-Barbera-inspired backgrounds

First, I made a rough sketch in Procreate, often sketching over parts of reference images I’d found online.

Store interior sketch
Store interior sketch

Using Sketch, I blocked out the simplest shapes I could and added objects, using the same symbols repeatedly. Finally, I added linework for definition, being careful not to add too much detail to the backgrounds.

Blocking. Optimised size: 7Kb
Details. Optimised size: 37Kb
Complete background. Optimised size: 44Kb

For the monochromatic colour palette, I chose only four shades and tints to prevent the background from competing with characters in the foreground.

Adaptive SVGs

When I’m implementing animated graphics like these, I use a method I’ve called Adaptive SVGs. I wrote about it recently in Smashing Magazine where I said:

By combining <symbol>, <use>, CSS Media Queries, and specific transforms, I can build adaptive SVGs that reposition their elements without duplicating content, loading extra assets, or relying on JavaScript. I need to define each graphic only once in a hidden symbol library. Then I can reuse those graphics, as needed, inside several visible SVGs. With CSS doing the layout switching, the result is fast and flexible.

I won’t cover Adaptive SVGs again here. You should read the full rundown in the original article.

Ambient animations

And of course, having animated so many cartoon titles recently, I couldn’t resist adding a few ambient animations to my characters, plus a few background details. Eyes blink, heads move, moustaches twitch, and toes tap. I wrote about Ambient animations recently in Smashing Magazine, where I said:

Ambient animation is like seasoning on a great dish. It’s the pinch of salt you barely notice, but you’d miss when it’s gone.

Accessibility

Commenting on that article, Nat Tarnoff made a good point about ensuring that ambient animations can be turned off using a visible button and the prefers-reduced-motion media query. He wrote:

These animations are specifically what cause problems for users sensitive to motion or distraction, as they do not come across as “ambient.” WCAG has 4 success criteria about animation. This style of animation violates 2.2.2 Pause, Stop, Hide while conforming to the others. This means there needs to be a visible button for users to stop or pause the animation. Prefers-reduced-motion is not considered sufficient to meet this requirement.

That was a helpful comment, so I added a button to each animation to toggle it on or off using a little bit of JavaScript.

Pioneering web design

I’ve always loved cartoon animation, especially Hanna-Barbera. The more I’ve experimented with their techniques in CSS, JavaScript, and SVG, the more fun I’ve had. I hope visitors enjoy that same sense of play—and if you’ve got a project you think I’d enjoy (cowboys optional), get in touch.

From: Codepen

Chris’ Corner: Design (and you’re going to like it)

Damning opening words from Edwin Heathcote in Why designers abandoned their dreams of changing the world. Every single thing on Earth not produced by nature had been designed. That was the spiel. Design wanted it all. Now Earth is a mess, its climate warming rapidly, its seas full of waste. There are microplastics in the glaciers, the air […]

From: Chris Coyier

Oregon Rocketry

My co-worker Robert is into model rocketry. I made a few rockets in my day, but the hobby stopped at Estes. I didn’t really realize people take rocketry much further until knowing Robert. His partner Michelle produced a short video piece for OPB on the community around it here. I’d embed the video here, but […]

From: Dave Rupert

The killer feature of Web Components

A left right flow chart starting at Add JSDoc pointing to CEM analyze then branching off into 8 different directions: API documentation, Storybook, Language Server, Linter, React Wrappers, More Wrappers, Jest Mocks, JSX Types, Figma Code Connect, and MCP Server

One unsung feature in the web components space that I don’t think gets enough attention is the Custom Elements Manifest initiative. I think it’s the killer feature of web components.

Known as “CEM” to its friends, a CEM is a community standard JSON format that surfaces information about your component APIs. The analyzer scans your class-based component to build up a “manifest” of all the methods, events, slots, parts, tag name, and CSS variables you want to expose. It works on a single component or an entire system’s worth of components. If you want to surface more details to consumers (like accepted attributes or CSS custom properties), you can provide more context to the analyzer through JSDoc comments and/or TypeScript types – which is good code hygiene and a favor for your future self anyhow. Here’s an example from the playground:

/**
 * @attr {boolean} disabled - disables the element
 * @attribute {string} foo - description for foo
 *
 * @csspart bar - Styles the color of bar
 *
 * @slot - This is a default/unnamed slot
 * @slot container - You can put some elements here
 *
 * @cssprop --text-color - Controls the color of foo
 * @cssproperty [--background-color=red] - Controls the color of bar
 *
 * @prop {boolean} prop1 - some description
 * @property {number} prop2 - some description
 *
 * @fires custom-event - some description for custom-event
 * @fires {Event} typed-event - some description for typed-event
 * @event {CustomEvent} typed-custom-event - some description for typed-custom-event
 *
 * @summary This is MyElement
 *
 * @tag my-element
 * @tagname my-element
 */
class MyElement extends HTMLElement {}

The JSDoc notation is forgiving (it supports both @cssprop and @cssproperty) and with the ability to document your ::part() and <slot> APIs, it’s more descriptive than what you’d get with a basic TypeScript interface. Eagle-eyed observers will notice there’s a distinction made between an @attribute and an @property, that’s because those are different concepts in HTML, ergo different in Custom Elements. Attributes (strings, numbers, booleans) tend to reflect, properties don’t.

After that thin layer of documentation, it’s a two-liner to generate the manifest:

npm i -D @custom-elements-manifest/analyzer
cem analyze

This will generate a file called custom-elements.json in your package directory.

View Sample Output
{
    "schemaVersion": "1.0.0",
    "readme": "",
    "modules": [
        {
            "kind": "javascript-module",
            "path": "src/my-element.js",
            "declarations": [
                {
                    "kind": "class",
                    "description": "",
                    "name": "MyElement",
                    "cssProperties": [
                        {
                            "description": "Controls the color of foo",
                            "name": "--text-color"
                        },
                        {
                            "description": "Controls the color of bar",
                            "name": "--background-color",
                            "default": "red"
                        }
                    ],
                    "cssParts": [
                        {
                            "description": "Styles the color of bar",
                            "name": "bar"
                        }
                    ],
                    "slots": [
                        {
                            "description": "This is a default/unnamed slot",
                            "name": ""
                        },
                        {
                            "description": "You can put some elements here",
                            "name": "container"
                        }
                    ],
                    "members": [
                        {
                            "kind": "field",
                            "name": "disabled"
                        },
                        {
                            "kind": "method",
                            "name": "fire"
                        },
                        {
                            "type": {
                                "text": "boolean"
                            },
                            "description": "some description",
                            "name": "prop1",
                            "kind": "field"
                        },
                        {
                            "type": {
                                "text": "number"
                            },
                            "description": "some description",
                            "name": "prop2",
                            "kind": "field"
                        }
                    ],
                    "events": [
                        {
                            "name": "disabled-changed",
                            "type": {
                                "text": "Event"
                            }
                        },
                        {
                            "description": "some description for custom-event",
                            "name": "custom-event"
                        },
                        {
                            "type": {
                                "text": "Event"
                            },
                            "description": "some description for typed-event",
                            "name": "typed-event"
                        },
                        {
                            "type": {
                                "text": "CustomEvent"
                            },
                            "description": "some description for typed-custom-event",
                            "name": "typed-custom-event"
                        }
                    ],
                    "attributes": [
                        {
                            "name": "disabled",
                            "type": {
                                "text": "boolean"
                            },
                            "description": "disables the element"
                        },
                        {
                            "type": {
                                "text": "string"
                            },
                            "description": "description for foo",
                            "name": "foo"
                        }
                    ],
                    "superclass": {
                        "name": "HTMLElement"
                    },
                    "tagName": "my-element",
                    "customElement": true,
                    "summary": "This is MyElement"
                }
            ],
            "exports": [
                {
                    "kind": "custom-element-definition",
                    "name": "my-element",
                    "declaration": {
                        "name": "MyElement",
                        "module": "src/my-element.js"
                    }
                }
            ]
        }
    ]
}

API extraction through TypeScript or JSDoc isn’t a novel concept, but what I find novel is the community tooling built around it. With a Custom Element Manifest, community plugins can use that information to generate files, populate dropdowns, add red squiggles, provide autocomplete, and automate a lot of the mundane meta-system DX work that comes with supporting a component library:

  • API Documentation - Your CEM can power your readme.md and component-level documentation.
  • Storybook - Using the Storybook plugin you can use your CEM to automate the generation of your Storybook stories.
  • Language Servers - It can be frustrating to not have your editor recognize the HTML you invented. CEM-powered language servers solve that issue. A few options here.
  • Linter - Want to lint HTML before shipping? CEM can power this.
  • React Wrappers - React 19 supports web components, but if you’re trying to use web components in a React <= 18 project, you’ll need little wrapper shims. Creating these by hand isn’t fun and we can hand this work off to the CEM.
  • Other Framework Wrappers - Shims for SolidJS, Svelte, and Vue.js.
  • JSX Types - JSX isn’t happy unless you add new interfaces to the JSX namespace. CEM can generate this for you.
  • Jest Mocks - If you’re still using Jest in the year of our lord 2025, I feel bad for you but there are plenty of people in this situation. Jest hates Custom Elements because Custom Elements are real DOM and not VDOM. No plugin to link to (sorry!) but I have seen teams using CEM to generate Jest mocks to smooth over the process when integrating with legacy testing solutions.
  • Figma Code Connect - If you want to connect your web components to Figma, you can automate that as well.
  • MCP Server - If you want to give your AI Agents insights into the components available in the current project, you can install an MCP Server that parses your CEM. (Couple options here)

Burton Smith who runs WC Toolkit has been helping us roll out some of our CEM work and we’re starting to turn some of these capabilities on. One pain point I’m hoping to solve is too much boilerplate. We have a lot of files in our individual component packages to power assorted tasks and integrations and I can see a world where we generate nearly all our readmes, storybooks, and even some low-level test coverage from the CEM at build-time or run-time.

From a single file we get the following outcomes…

  • Spend less time/energy maintaining and schlepping boilerplate code
  • Improve baseline test coverage and make it more predictable
  • Make new components easier to create, ideally speeding up development
  • Reduce cognitive overhead when jumping into the project
  • Provide a forcing function for more/better documentation
  • Potentially improve the design-developer bridge through Figma Code Connect and MCPs

Again, I want to applaud the web components community here. There’s no VC-funded corporate overlord roadmap driving the Custom Elements Manifest initiative, just fellow enthusiasts. From a community perspective, that’s a positive signal for me. Adding it to your project is low-effort, high-impact type work and I probably only covered about a quarter of what a CEM can do for you, which goes to show a community agreeing on a standardized way to describe components is a powerful tool.

From: Adactio

Live

I don’t get out to gigs as much as I’d like. But for some reason, the past week has been packed with live music.

On Tuesday I saw Ye Vagabonds. I’m particularly partial to their nice mandolin playing. It was a nice concert that felt like being in a Greenwich Village folk club in the ’60s. It’s great to see how popular Ye Vagabonds are with indie kids, even if I’m slightly perplexed by the extent of the popularity—see also Lankum.

On Thursday it was time for Robert Forster and his band. I’m a huge fan of The Go-Betweens, as well as Forster’s solo work. He gave us a thoroughly enjoyable show, interspersing some select Go-Betweens tracks, including quite a few off 16 Lovers Lane.

On Saturday Jessica and I made the journey over to Lewes to see The Wilderness Yet at the folk club. We know Rowan and Rosie from when they used to live ‘round here and it was lovely to see and hear them again.

Then last night we went out to see DakhaBrakha. The Ukrainian population of Brighton came out to give them a very warm welcome. The band themselves were, unsurprisingly, brilliant. Like I said last time they came to town:

Imagine if Tom Waits and Cocteau Twins came from Eastern Europe and joined forces. Well, DakhaBrakha are even better than that.

A good week of music from Ireland, Australia, England, and Ukraine.

October 13, 2025, 3:29 pm Live >>

From: Boagworld

A Non-Developer’s Experience Vibe Coding

We have all heard of vibe coding (AI-assisted coding), but is it just a tool for developers or does it really allow a non-developer to build production-ready apps? I share my experience.

From: Jim Nielsen

Research Alt

Jeremy imagines a scenario where you’re trying to understand how someone cut themselves with a blade. It’d be hard to know how they cut themselves just by looking at the wound.

But if you talk to the person, not only will you find out the reason, you’ll also understand their pain.

But what if, hear me out here, instead we manufactured tiny microchips with sensors and embedded them in all blades?

Then we program them such that if they break human flesh, we send data — time, location, puncture depth, current blade sharpness, etc. — back to our servers for processing with AI.

This data will help us understand — without bias, because humans can’t be trusted — how people cut themselves.

Thus our research scales much more dramatically than talking to individual humans, widening our impact on humanity whilst simultaneously improving our product (and bottom line)!

I am accepting venture funds for this research. You can send funds to this bitcoin address: 17HzyHWNrdS7GpMArshSBLpJpcvrre93P6.


Reply via: Email · Mastodon · Bluesky

From: Adactio

Research

Suppose somebody is using a blade. Perhaps they’re in the bathroom, shaving. Or maybe they’re in the kitchen, preparing food.

Suppose they cut themselves with that blade. This might have happened because the blade was too sharp. Or perhaps the blade was too dull.

Either way, it’s going to be tricky to figure out the reason just by looking at the wound.

But if you talk to the person, not only will you find out the reason, you’ll also understand their pain.

From: Chris Coyier

Oatmeal on AI Art

Reading Oatmeal stuff is always such a seesaw for me. It’s so riddled with like boobshark jokes and I’m like, yeah yeah ha ha. I don’t hate that kind of humor or find it offensive, I just don’t think it’s very funny. Then it’s also so riddled with such earnest heartfelt well-articulated thoughts that I’m […]

From: Chris Coyier

Media Diet

📺 Wondla — 10/10 kids show. I was way into it. Post-apoc situation with underground bunkers (apparently Apple loves that theme) where when the protagonist girl busts out of it, the world is quite different. The premise and payoff in Season 1 was better than the commentary vibe of Season 2, but I liked it […]

From: Codepen

412: 2.0 Embedded Pens

Or just “Embeds” as we more frequently refer to them as. Stephen and Chris talk about the fairly meaty project which was re-writing our Embeds for a CodePen 2.0 world. No longer can we assume Pens are just one HTML, CSS, and JavaScript “file”, so they needed a bit of a redesign, but doing as […]

From: Boagworld

Key UX Topics to Educate Your Organization On

Focus educational content on common mistakes, points of contention, and frequently asked questions for maximum impact.

From: Adactio

Simplify

I was messing about with some images on a website recently and while I was happy enough with the arrangement on large screens, I thought it would be better to have the images in a kind of carousel on smaller screens—a swipable gallery.

My old brain immediately thought this would be fairly complicated to do, but actually it’s ludicrously straightforward. Just stick this bit of CSS on the containing element inside a media query (or better yet, a container query):

display: flex;
overflow-x: auto;

That’s it.

Oh, and you can swap out overflow-x for overflow-inline if, like me, you’re a fan of logical properties. But support for that only just landed in Safari so I’d probably wait a little while before removing the old syntax.

Here’s an example using pictures of some of the lovely people who will be speaking at Web Day Out:

Jemima Abu Rachel Andrew Lola Odelola Richard Rutter Harry Roberts

While you’re at it, add this:

overscroll-behavior-inline: contain;

Thats prevents the user accidentally triggering a backwards/forwards navigation when they’re swiping.

You could add some more little niceties like this, but you don’t have to:

scroll-snap-type: inline mandatory;
scroll-behavior: smooth;

And maybe this on the individual items:

scroll-snap-align: center;

You could progressively enhance even more with the new pseudo-elements like ::scroll-button() and ::scroll-marker for Chromium browsers.

Apart from that last bit, none of this is particularly new or groundbreaking. But it was a pleasant reminder for me that interactions that used to be complicated to implement are now very straightforward indeed.

Here’s another example that Ana Tudor brought up yesterday:

You have a section with a p on the left & an img on the right. How do you make the img height always be determined by the p with the tiniest bit of CSS? 😼

No changing the HTML structure in any way, no pseudos, no background declarations, no JS. Just a tiny bit of #CSS.

Old me would’ve said it can’t be done. But with a little bit of investigating, I found a nice straightforward solution:

section >  img {
  contain: size;
  place-self: stretch;
  object-fit: cover;
}

That’ll work whether the section has its display set to flex or grid.

There’s something very, very satisfying in finding a simple solution to something you thought would be complicated.

Honestly, I feel like web developers are constantly being gaslit into thinking that complex over-engineered solutions are the only option. When the discourse is being dominated by people invested in frameworks and libraries, all our default thinking will involve frameworks and libraries. That’s not good for users, and I don’t think it’s good for us either.

Of course, the trick is knowing that the simpler solution exists. The information probably isn’t going to fall in your lap—especially when the discourse is dominated by overly-complex JavaScript.

So get yourself a ticket for Web Day Out. It’s on Thursday, March 12th, 2026 right here in Brighton.

I guarantee you’ll hear about some magnificent techniques that will allow you to rip out plenty of complex code in favour of letting the browser do the work.

From: Adactio

Coattails

When I talk about large language models, I make sure to call them large language models, not “AI”. I know it’s a lost battle, but the terminology matters to me.

The term “AI” can encompass everything from a series of if/else statements right up to Skynet and HAL 9000. I’ve written about this naming collision before.

It’s not just that the term “AI” isn’t useful, it’s so broad as to be actively duplicitous. While talking about one thing—like, say, large language models—you can point to a completely different thing—like, say, machine learning or computer vision—and claim that they’re basically the same because they’re both labelled “AI”.

If a news outlet runs a story about machine learning in the context of disease prevention or archeology, the headline will inevitably contain the phrase “AI”. That story will then gleefully be used by slopagandists looking to inflate the usefulness of large language models.

Conflating these different technologies is the fallacy at the heart of Robin Sloan’s faulty logic:

If these machines churn through all media, and then, in their deployment, discover several superconductors and cure all cancers, I’d say, okay … we’re good.

John Scalzi recently wrote:

“AI” is mostly a marketing phrase for a bunch of different processes and tools which in a different era would have been called “machine learning” or “neural networks” or something else now horribly unsexy.

But I’ve noticed something recently. More than once I’ve seen genuinely-useful services refer to their technology as “traditional machine learning”.

First off, I find that endearing. Like machine learning is akin to organic farming or hand-crafted furniture.

Secondly, perhaps it points to a severing of the ways between machine learning and large language models.

Up until now it may have been mutually benificial for them to share the same marketing term, but with the bubble about to burst, anything to do with large language models might become toxic by association, including the term “AI”. Hence the desire to shake the large-language model grifters from the coattails of machine learning and computer vision.

From: Chris Coyier

Clap on the off beat

Clapping on the on-beat sounds weird and wrong on (most?) songs. In (most?) 4/4 songs, that means clapping on the 1 and 3 sounds bad and 2 and 4 sounds good/normal. But an audience of a bunch of random folks just getting excited can get it wrong! This video of Harry Connick Jr. extending a […]

From: Jim Nielsen

Social Share Imagery via a Data Attribute

I’ve done something few on the internet do. I’ve changed my mind.

Double take meme of girl with a disgusted face on one side then the same girl with a face of changed opinion. Both faces have the text “og:image” superimposed.

A few posts on my blog have started to unfurl social share imagery.

Screenshot of a post from @jimniels@mastodon.social showing a link to blog.jim-nielsen.com and an accompanying og:image preview.

You might be wondering, “Wait Jim I thought you hated those things?”

It’s not that I hate social share imagery. I just think…well, I’ve shared my thoughts before (even made a game) so I won’t get on my soapbox.

But I think these “previews” have their place and, when used as a preview — i.e. an opportunity to graphically depict a brief portion of the actual, underlying content — these function well in service of readers.

For example, I often write posts that have zero images in them. They’re pure text. I don’t burden myself with the obligation to generate a graphical preview of the ideas contained in those posts.

But, sometimes, I create posts that have lots of imagery in them, or even just a good meme-like photo and it feels like a shame to not surface that imagery in some way.

So, in service of that pursuit, I set out to resolve how I could do og:images in my posts.

It’s not as easy as “just stick it your front-matter” because my markdown files don’t use front-matter. And I didn’t want to “just add front-matter”. I have my own idiosyncratic way of writing markdown for my blog, which means I need my own idiosyncratic way of denoting “this post has an og:image and here’s the URL”.

After giving it some thought, I realized that all my images are expressed in markdown as HTML (this lets me easily add attributes like alt, width, and height) so if I wanted to mark one of my images as the “preview” image for a post, I could just add a special data attribute like so:

You guys, I made the funniest image to depict this:

<img data-og-image src="" width="" height="" alt="">

Isn’t that hilarious?

Then my markdown processor can extract that piece of meta information and surface it to each post template, essentially like this:

<html>
  <title>{post.title}</title>
  {post.ogimage &&
    <meta property="og:image" content={post.ogimage}>}
  <body>
    <h1>{post.title}</h1>
    {post.content}

I love this because it allows me to leverage existing mechanisms in both the authoring and development processes (data attributes in HTML that become metadata on the post object), without needing to introduce an entirely new method of expression (e.g. front-matter).

It also feels good because:

  1. It’s good for me. It doesn’t require any additional work on my part. I don’t have to create additional images for my posts. I’m merely marking images I’ve already created — which were done in service of a post’s content — as “previews” for the post.
  2. It’s good for users. Readers of my site get image previews that are actually, well, previews — e.g. a graphical representation that will contextually reappear in the post, (as opposed to an image template whose contents do nothing to provide an advanced graphical preview of what’s to follow in the post itself).

It’s technology in service of content, rather than content in service of technology.

Or at least that’s what I like to tell myself :)


Reply via: Email · Mastodon · Bluesky

From: Chris Coyier

Fixing the `opendiff` command line tool

On my Mac, you can use this command like… And it’ll open some built-in GUI app called FileMerge to show you the diff. It wasn’t working for me. I wish I copied the exact error but it was something about the path being wrong or the executable not being available or something. The solution that […]

From: Adactio

Decontrolled

I was supposed to be in Cork over the weekend.

Not only was it high time I paid my mother a visit, but the Cork Folk Festival was happening too. So I booked some relatively cheap plane tickets for myself and Jessica back in August and noted down the days in my calendar.

We didn’t end up getting our flight. This time it wasn’t because I messed up the flight times. We made it to Gatwick airport in plenty of time. That’s when we saw that our flight was delayed.

See, Storm Amy was moving in. We were hoping to get into Cork before the storm hit, but now with the flight delayed, that wasn’t likely. In fact, it was more likely that the flight would just get more and more delayed and possibly even get diverted.

To start with, we settled in at the airport, prepared to spend an hour or two more than we had planned. But, sure enough, the delays kept piling up. It was time to make decision; wait it out in the hopes that we’d eventually make a very bumpy landing in Cork, or cut our losses and run.

I quickly looked up flights for the next couple of weekends and spotted some cheap ones a fortnight away. I booked them and then called my mother to tell her we wouldn’t be showing up that night, but we’d see her in a couple of weeks.

Alright then, time to go home.

Wait a minute …how exactly are we supposed to leave the airport other than on an airplane?

It turns out there’s a process called “decontrolling”. You need to find someone from the airline (or in our case, a third-party contractor operating on the airline’s behalf) who has the security privileges to walk you back out. But you still need to go through passport control …even though you never left the building.

Luckily we didn’t have any checked luggage or it would’ve gotten complicated. As it was, it was just weird. It was all very City And The City.

That flight we abandoned did finally take off …six hours late. By that time we were back home on the sofa eating pizza and listening to the wind gusting outside. I think we made the right choice.

From: Chris Coyier

Local by Flywheel was Ultra Slow Because I Had The Wrong Version

Maybe a few months ago on my Mac Studio, Local by Flywheel became incredibly slow clicking any button in the UI would take literally minutes. I was gonna just give up and switch to Studio, but I had tried that once and it had enough rough edges I gave up (can’t remember why now, but […]

From: Boagworld

Run Your Agency from One AI Driven System: Notion for Agency Owners & Freelancers

Learn to run your agency with Notion AI. Live build + Q&A. 29th Oct, 2:30pm UK time.

From: Codepen

Chris’ Corner: Discontent

Nothing is above a little healthy criticism. Here’s Den Odell’s article We Keep Reinventing CSS, but Styling Was Never the Problem. It’s easy to forget what CSS was originally designed for: documents. You’d write some HTML, style a few headings and paragraphs, maybe float an image to the left, and call it a day. In […]

From: Stuff & Nonsense

The thing about contrast-color

I have to admit that I got a little over-excited when I read that the contrast-color() function is supported in Safari and was keen to try it out. But there’s a problem, the thing with contrast-color is…

As Juan writes on CSS Tricks:

Given a certain color value, contrast-color() returns either white or black, whichever produces a sharper contrast with that color. So, if we were to provide coral as the color value for a background, we can let the browser decide whether the text color is more contrasted with the background as either white or black.

So yeah, define a background colour and the browser will choose either black or white to contrast it with:

h1 {
background-color: var(--color-background);
color: contrast-color(var(--color-background)); }

For my website design, I chose a dark blue background colour (#212E45) and light text (#d3d5da). This colour is off-white to soften the contrast between background and foreground colours, while maintaining a decent level for accessibility considerations.

Dark blue background and off-white text

But here’s the thing. The contrast-color() function chooses either white for dark backgrounds or black for light ones. At least to my eyes, that contrast is too high and makes reading less comfortable, at least for me.

Dark blue background and white text

It feels even more uncomfortable on really dark backgrounds like my bio page.

Black background and white text

And, inexplicably, there’s no way to adjust that contrast, even though there’s a contrast filter which does offer that flexibility:

filter: contrast(50%);

I just wish these two things were joined up in some way. Maybe by adding the filter syntax to the contrast-color() function. Something like this:

h1 {
color: contrast-color(var(--color-background) 50%); }

Oh well. I guess we just can’t have nice things. (Yet.)

From: Stuff & Nonsense

Smashing Animations Part 5: Building adaptive SVGs with symbol, use, and CSS Media Queries

Yours truly over at the Smashing Magazine: “SVGs, they scale, yes, but how else can you make them adapt even better to several screen sizes? Web design pioneer Andy Clarke explains how he builds what he calls “adaptive SVGs” using symbol, use, and CSS Media Queries.”

Read Building adaptive SVGs with symbol, use, and CSS Media Queries

From: Stuff & Nonsense

Getting creative with shape-outside

Yours truly over at CSS Tricks: “There are so many creative opportunities for using shape-outside that I’m surprised I see it used so rarely. So, how can you use it to add personality to a design? Here’s how I do it.”

Read Getting creative with shape-outside.

From: Stuff & Nonsense

Unfinished Business #136: Encourage people to think differently

In this episode of Unfinished Business, Andy talks about what he learned from running an online layout workshop and Rich describes his new, up-coming conference, Web Day Out.


Sponsored by Web Day Out

A one-day event all about what you can do in web browsers today. On Thursday, 12 March 2026, eight speakers will dive deep into HTML, CSS, and some JavaScript, getting you up to speed on the most powerful web platform features that you can use right now.

Buy a ticket


Also available on YouTube

For anyone who can’t get enough Unfinished Business, we publish the show in video format on YouTube.

Watch “Unfinished Business” on YouTube

Sponsor Unfinished Business

The best way to promote your product or service to the Unfinished Business audience of creative professionals, designers, and developers. Sponsors get one exclusive two-minute ad per episode, live read by me or Rich, which feels personal and relatable. We can use your script or ad-lib, and you’ll also receive a link on each episode’s post, as well as a thank-you on our Bluesky and Mastodon accounts. Interested? We’d love to hear from you.

Support Unfinished Business on Patreon

We also have three monthly membership plans so you can support Unfinished Business on Patreon. $5, $10, and $20 if you’re feeling especially generous. All money goes towards podcast editing and hosting. Support Unfinished Business on Patreon.

From: Jim Nielsen

Doing It Manually

I have a standing desk that goes up and down via a manual crank.

I’ve had it for probably ten years.

Every time I raise or lower that thing, it gets my blood pumping.

I often think: “I should upgrade to one of those standing desks that goes up and down with the push of a button.”

Then there’s the other voice in my head: “Really? Are you so lazy you can’t put your snacks down, get out of your comfy chair, in your air conditioned room, and raise or lower your desk using a little elbow grease? That desk is just fine.”

While writing this, I get out of my chair, star the timer, and raise my desk to standing position. 35 seconds.

That’s the cost: 35 seconds, and an elevated heart rate.

As I have many times over the last ten years, I recommit to keeping it — mostly as a reminder that it’s ok to do some things manually. Not everything in my life needs to be available to me at the push of a button.


Reply via: Email · Mastodon · Bluesky

From: Boagworld

Education: Your Most Powerful UX Leadership Tool

Discover how to use workshops, talks, and self-learning to scale UX impact across your organization.

From: Chris Coyier

Danger Gently

Danger Gently is the name of the band I occasionally get a seat in here in lovely Bend, Oregon. We played at the High Desert Museum the other week for their “Art in the West” event. We play at The Cellar every Wednesday night (I make it to as many as I can). Here’s a […]

From: Dave Rupert

Why I hate the MVP car

Illustration from the MVP car analogy. On the top of the illustration is a flow labelled 'Not like this' followed by a wheel pointing to a chassis with wheels pointing to a convertible pointing to a car. Above the drawings are frowning faces until you get to the car which has a smiling face. On the bottom is a flow labelled 'Like this!' which has a skateboard pointing to a scooter pointing to a bicycle pointing to a motorcycle pointing to a convertible. The faces above the five vehicles move from frowning to super happy.

I have a love-hate relationship with “the MVP car”, that classic illustration that shows us the RIGHT and WRONG way to build a product. To be fair, I don’t think its creator Henrik Kniberg would want it called “the MVP car” at all. According to his post the whole point of the illustration is to replace “MVP” with something more descriptive like “Earliest Testable/Usable/Lovable Product”. I wholeheartedly agree with the notion and short-cycle iteration beats long-cycle “Bing Bang Delivery” as Kniberg refers to it.

Kniberg notes that sharing the car like a meme erases his original context and all we see is the car. Despite taking the time to get the context and being a lover of iteration, I think I have built up petty grievances over the years with the MVP car. The next thousand or so words are about those disagreements.

First off, skateboards are rad. That should be a happy face.

My first real issue is that the wheel → chassis → convertible → car is way closer to the way you actually build a car from an industrialized manufacturing perspective. Henry Ford didn’t put skateboards into the factory and poop out cars. Ford’s factories started with wheels and pre-fabricated chassis and transformed them into consumer vehicles through a process of craftsman-level precision and heaps of welding and stitching. This is still the same process car manufacturers use today but with robots and giga-presses. Most product organizations need to develop a predictable process for pushing work through the system.

Next grievance! Apart from the bike → motorcycle evolution, the skateboard → scooter → bike → motorcycle → convertible path is not how any of these products evolved. They evolved over literal centuries and millennia through repeated processes of invention and miniaturization/optimization. If we’re trying to be accurate, between the bike and the motorcycle, you probably need a steam ship with an apartment complex-sized engine room. A lot of products follow a simple formula: Take thing that exists and bolt on new technology.

One thing the MVP car does well is that it lets you imagine alternate routes on how you might evolve the complexity of a feature over time while delivering something usable the whole way through. Kniberg is right about learning too. By reducing scope and “following the fun” you might find customers strongly prefer one idea over another. Instead of “one big release” you mature your idea over time with happy customers along the way. But that leads me to the next handful of issues I have with the MVP car.

In the MVP car analogy, you have to know where you’re going. You have to have a clear idea of the end state and work a plan backwards from there to deliver something over time. It’s like how you write a murder mystery in reverse. This process works great if you’re building something that’s a known quantity but “know where you’re going” works less great for exploratory or emergent work. The wheel → chassis → convertible → car flow is a more realistic product evolution; a cobbling together of existing technologies, then adding features to make it more user-friendly (like a steering wheel).

With the MVP car, there’s also Theranos-levels of risk in over-promising to management and investors. You’ve already sold the idea in PowerPoints and Figma without technical constraints and now they signed-off on it. We’re a car company, does anyone here even know how to make good UI a skateboard? Can we even source wood? There’s now downward pressure to deliver on a predetermined timeline and no opportunity to pivot to a rickshaw or a tuk-tuk instead of a car because any divergence is a mission failure.

It takes specific skills to pull off an MVP car. It takes people who have built up a specific kind of innate muscle memory. It takes a team composition that has a mix of people with high and low standards. Not too high that nothing ever ships, but not too low that garbage goes out the door. People who can intuit around what is essential, who can kill their darlings, and people who can answer the question “Given the timeframe, what does this need to be right now?”

The MVP car intends to be customer focused… but is it though? Have you ever done a redesign? Bosses question them and audiences universally hate them even if it’s 10,000x better. They cost a fortune and customers complain you’ve inconvenienced their lives with this new direction. Smaller, imperceptible iteration tends to sail through the gauntlet a lot smoother. And we want to move fast and have five major iterations of our product? That’s a hard sell both internally and externally. I can already hear engineering departments saying they’d rather not build five different vehicles, they’d rather build one vehicle once. A codebase with five apps turducken’d inside is going to be difficult to work in unless a lot of planning went into it from the start.

The biggest issue I have is that there’s no tactical or practical advice contained within the MVP car other than “break your goal down into five separate modes of transportation of increasing difficulty to build.” The advice is so general and non-specific that it’s almost meaningless. I get that Kniberg’s goal was to be vague but exciting… but as a foundation to build your castle on, it’s hard to grab hold. The absence of a process is also a process and creates a void where people fill it with a lot of strange ideas.

As I said, I think there’s value in the MVP car’s premise that it’s best to iterate forward to a goal. I think it’s important to find what makes your product good and focus on the essential pieces. Do you know what fits within the spirit of the MVP car without rebuilding the customer-facing app five times? A way to evolve an idea with customers before you get there? A tool that helps you see and feel the end goal before you commit? A tangible artifact that gives a discussion point for breaking an job down into deliverable phases? That’s right… prototypes. And notably, in Kniberg’s post three of the four case studies talk about sharing prototypes or rough versions of ideas with customers.

In conclusion, those are my beefs with the MVP car. It’s actually a fine analogy, inspiring even, but this list has been building for years and it feels good to get it all out there. Ironically, the last line of Kniberg’s post about the MVP car is this:

And remember – the skateboard/car drawing is just a metaphor. Don’t take it too literally :o)

Oops.

From: Adactio

Summer’s end

It’s October. Autumn is wrapping itself around us, squeezing the leaves from the trees. Summer has slipped away, though it gave us a parting gift of a few pleasant days this week to sit outside at lunchtime.

I’ve got a bit of a ritual now for the end of September. I go to Spain and soak up the last of the sun. There’s an Irish music festival in the beautiful medieval town of Cáceres.

It’s not easy to get to, but that’s all part of the ritual. Set out for Madrid or Seville and spend a night there. Then get on a train for the long journey through a landscape straight out of a spaghetti western.

Once you get to Cáceres there’s nothing to do but enjoy the sun, the food, and the music. So much music! Open-air concerts in a medieval square that go well past midnight. Non-stop sessions scattered throughout the town’s pedestrianised streets.

For me, it’s the perfect way to see out the summer.

Cáceres Irish Fleadh 2025

From: Codepen

411: The Power of Tree-Sitter

Alex and Chris hop on the show to talk about a bit of technology that Alex calls “The 2nd best technological choice he’s ever made.” That technology is called Tree-sitter. It’s a code parsing tool for building ASTs (Abstract Syntax Trees) out of code. GitHub uses it to power search and “go to” functionality. The […]

From: Codepen

Chris’ Corner: Word Search

My daughter had a little phase of being into Word Searches. I found it to be a cool dad moment when I was like “I’ll make you a tool to make them!”. That’s what she was into. She liked doing them OK, but she really liked the idea of making them. So my tool starts […]

From: Jim Nielsen

Running Software on Software You’ve Never Run

I love a good look at modern practices around semantic versioning and dependency management (Rick Hickey’s talk “Spec-ulation” is the canonical one I think of).

Niki recently wrote a good ‘un at tonsky.me called “We shouldn’t have needed lockfiles”.

What struck me was this point about how package manifests allow version ranges like ^1.2.3 which essentially declare support for future versions of software that haven’t yet been written:

Instead of saying “libpupa 1.2.3 depends on liblupa 0.7.8”, [version ranges] are saying “libpupa 1.2.3 depends on whatever the latest liblupa version is at the time of the build.”

Notice that this is determined not at the time of publishing, but at the time of the build! If the author of libpupa has published 1.2.3 a year ago and I’m pulling it now, I might be using a liblupa version that didn’t even exist at the time of publishing!

The funny thing is, we use version ranges only to go freeze them with lock files:

version ranges end up not being used anyway. You lock your dependencies once in a lockfile and they stay there, unchanged

In other words: we avoid locking ourselves to specific versions in package.json by using version ranges, only to then go lock ourselves to specific versions in package-lock.json — lol!

I mean, that’s funny when you think about it.

But to go back to Niki’s earlier point: version ranges let us declare to ourselves that some code that exists today is compatible with some other future code that has yet to be written.

This idea allows us to create automated build systems that resolve to an artifact whose dependencies have never existed before in that given combination — let alone tested and executed together in that combination.

Now I get it, semantic versioning is an idea not a guarantee. But it’s also pretty wild when you think about it — when you encounter the reality of how semantic versioning plays out in the day-to-day world of building software.

I guess that’s a way of acknowledging out loud that we have normalized shipping production systems on top of the assumption that untested, unwritten combinations of software will behave well together — if not better, since patch updates fix bugs right?

And that’s not even getting into the security side of the equation. Future versions of packages have no guarantee to be as safe as previous ones, as we’ve seen with some of the npm supply chain attacks which rely on version ranges for their exploits. (Funny, isn’t it? Upgrading to the latest version of a package can get you into trouble. The solution? Upgrading to the latest version of a package.)

Anyhow, this all gets me thinking that version ranges and dependency management were the gateway drug to the non-determinism of LLMs.


Reply via: Email · Mastodon · Bluesky

From: Stuff & Nonsense

What I learned from hosting last week’s practical layout workshop

Last week, I hosted what I plan to be the first in an ongoing series of online workshops. Overall, the event went well, and here’s what I learned and how I’ll improve things next time.

My friend Paul recommended that instead of writing another full-length book, I should spread my design education content across as many media and platforms as possible. He suggested that, say, I have material about how to improve layout design.

  • I might host an in-person event or an online workshop.
  • I could make a video course and sell it on my website or Skillshare.
  • I may turn the script into an e-book to sell on my site or Amazon.

Then, I could repeat the process with other topics. I’ve heard Paul say plenty of stupid things, but this idea sounded plausible. After coming back from the summer break, I spent a few weeks working on content for the first topic and an online practical layout design workshop.

Practical layout workshop for designers and creative teams

Marketing and sales

This was my first time producing an online workshop. Not knowing how well it would be received, I only marketed it to people who follow me on Bluesky, LinkedIn, and Mastodon, or who read my blog. Geoff kindly wrote a promo post on CSS Tricks and Andy included it in The Index, his Piccalilli email newsletter.

According to my survey of attendees, 60% heard about the workshop on my blog, 20% from LinkedIn, 10% from Bluesky, 10% Mastodon, and 10% somewhere else. This time, I didn’t email my 1300 newsletter subscribers, so I expect that might’ve made a difference too.

I sold tickets at £69, which is the same price as one of Paul’s two-hour workshops and hit my unambitious goal for ticket sales. Like Paul, I offered an add-on session for an extra £29, but no one opted for that, so I likely won’t offer it again.

Only one person said the price was “somewhat” fair. Everyone else felt it was a good value.

An example design from my workshop

Setting up

Paul uses Google Meets for his online workshops. I’ve never used Google Meets for anything, so instead I opted for Zoom Webinars, as I use Zoom a few times a week for client meetings. I liked the familiar interface, the ability to overlay my camera video on top of the screen sharing, and how Zoom recorded the session to the cloud.

I didn’t like the fact that I couldn’t see attendees’ camera videos, and the usual chat was replaced by Q&A. It often felt like I was talking to myself, and it wasn’t easy to judge people’s reactions to what I was saying. I’m told that I could’ve changed those settings when I scheduled the webinar, so I need to look into that.

I have a Zoom Workplace Pro subscription, so paying for one month of Zoom Webinars costs me £64 excluding VAT. If this idea takes off and I run more workshops, I’d consider paying annually to save myself a few quid.

An example design from my workshop

Presenting

I used my MacBook Pro and iPad Pro to present the workshop, running Zoom and my Keynote slides on my laptop and my notes on the tablet. Switching between apps was initially fiddly, especially since I had Keynote running in full-screen mode. It also meant that the Zoom Q&A was often hidden from view. Before my next workshop, I need to experiment with using my iPad Pro as an external monitor for the MacBook Pro so I can keep Zoom visible.

I decided to use my iPhone as a Continuity Camera to film myself, as it gives better resolution than the MacBook Pro camera. I also used my AirPods Pro for headphones and a microphone. Listening back to the recorded audio, next time I’ll try the DJI lavalier mic I use for my YouTube videos.

Demonstrating

I’d split the two-hour workshop into six chapters, each starting with a Keynote deck and then sharing my screen while I built layouts in Sketch. I’d pre-prepared these Sketch files so I could make the demonstrations appear smooth, and this went well. I only wish I’d used duplicate files for the demonstrations, as Sketch’s auto-save meant going back to the original state of the files was impossible. I won’t make that mistake again.

An example design from my workshop

Getting feedback

I asked everyone who attended to complete a brief survey at the end of the workshop. 50% did. Seventy-five per cent said they’d attend a future workshop, and the rest said they might, depending on the topic. Comments were overwhelmingly positive, including:

I loved the mix of slides, cultural background, and practical sessions in Sketch.

And

Enjoyed the course. As a developer, I would also like to see how some of these designs translate to mobile.

That’s fair. I didn’t cover small-screen designs during the time we had. That’s possibly a topic for another workshop.

Final thoughts

I thoroughly enjoyed working on the content for this workshop. In fact, I didn’t get through everything I made, so I’ll have that for when I make a video version. I also enjoyed the event, although there are plenty of areas I’d like to improve on for next time, including:

  1. Broader marketing and sales
  2. Improved sound quality with a DJI mic
  3. Different Zoom set-up so I can see attendees
  4. Better MacBook Pro and iPad Pro configuration

After that, my plan is to host more in-depth workshops with deeper dives into topics such as responsive layout and techniques, including the use of compound and modular grids. However, my next step will be to adapt the content from this workshop into a video course for Skillshare and other platforms, and to transform the script into a short e-book.

From: Boagworld

Personas: Make Them Useful With Functional, Task-Led Personas

Learn why traditional customer personas fall short and how to create functional personas that focus on tasks, questions, and objections to improve UX and conversions.

From: Stuff & Nonsense

Meet my new Modular grid generator

Before my workshop last week, I made some changes to my Compound grid generator. After the workshop, I made a new grid generator tool, this time designed to create modular grids.

This new Modular grid generator lets you choose the number of columns and rows you need for your modular grid. You can also specify the column and row gaps in px, em, rem, and % units. Lastly, you can choose from a selection of common aspect ratios for your modules.

An automatic preview of your grid also includes column and row position values. You can download a WebP image of the generated grid.

You can also copy the HTML and CSS code to your clipboard.

But there’s more. Press on any of the modules to open a modal where you can choose how many columns or rows a module can span.

This lets you easily create a variety of layouts from your modular grid.

And, if you’re the Tailwind sort, you can copy code for that framework too.

Finally, I also added Tailwind to the export options in my Compound grid generator, to keep the functionality of my layout generators in sync.

Try out the new Modular grid generator and improved Compound grid generator. If you like them, you can buy me a coffee.

From: Chris Coyier

Strongbacks

Back when I went to the Alaska Folk Festival, a real highlight was catching The Strongbacks do their version of sea shanties live on the main stage. I remember a real tear-jerker protest shanty that I’d love to hear again. As fate would have it, I also went to Zig Zag campout this year and […]

From: Zeldman

How do you spell success?

Working in tech means being comfortable with change and uncertainty. Successfully working in tech means not letting change and uncertainty paralyze you. Forge ahead on the best information you have, and be prepared to change direction as needed.

The post How do you spell success? appeared first on Jeffrey Zeldman Presents.

From: Chris Coyier

Microwaves

Chef’s kiss stuff here from Colin Cornaby: Today’s microwave can cook a frozen burrito. Tomorrow’s microwave will be able to cook an entire Thanksgiving Dinner. […] We all need to transition to this way of cooking, because clearly this is where the future is going. I expect in a few short years kitchens will be […]

From: Zeldman

Behind every successful launch, there are 100 interesting failures. 

We must stop thinking of failure as an end of something, and learn to see it as a natural part of progress. The first incarnation of a new idea may die, but the best ideas will find new lives. Behind every successful launch, there are 100 interesting failures. 

The post Behind every successful launch, there are 100 interesting failures.  appeared first on Jeffrey Zeldman Presents.

From: Stuff & Nonsense

Ambient Animations In Web Design: Principles And Implementation (Part 1)

Yours truly over at the Smashing Magazine: “Creating motion can be tricky. Too much and it’s distracting. Too little and a design feels flat. Ambient animations are the middle ground — subtle, slow-moving details that add atmosphere without stealing the show.”

Read Ambient Animations In Web Design: Principles And Implementation (Part 1)

From: Jim Nielsen

The Risks of NPM

There was a time when I could ask, “Did you see the latest NPM attack?” And your answer would be either “Yes” or “No”.

But now if I ask, “Did you see the latest NPM attack?” You’ll probably answer with a question of your own: “Which one?”

In this post, I’m talking about the Qix incident:

  • Prolific maintainer Qix was phished.
  • Qix is a co-maintainer on many packages with Sindre Sorhus, the most popular maintainer on NPM (by download count).
  • Attackers pushed malicious code to packages that are indirectly depended by a huge portion of the ecosystem (hundreds of millions of downloads a week).

When I first heard about it, I thought “Oh boy, better not npm i on the old personal machine for a little while.”

But as details began to emerge, I realized the exploit wasn’t targeting my computer. It was targeting the computers of people downstream from me: end users.

The malicious code didn’t do anything when running npm install. Instead, it laid there dormant, waiting to be bundled up alongside a website’s otherwise normal code and served to unsuspecting end users.

Maybe we should rename “bundlers” to “trojan horses”, lol.

Graphic depicting many source assets on the left, like .js files, passing through a trojan horse in the middle and coming out as singular files on the right.

That’s all to say: you didn’t have to run npm install to be affected by this attack. You just had to visit a website whose code was sourced via npm install. (You needed a bitcoin wallet too, as that was the target of the exploit.)

It’s wild because browsers work really hard to make it safe to visit any webpage in the world — to do a GET to any URL. But attacks like this chip away at those efforts.

So while it’s easy to think NPM can be unsafe for your computer because running npm install allows running arbitrary code, that’s not the whole story. npm install can be unsafe for:

  • Your computer (install time execution)
    • Lifecycle scripts (preinstall, install, postinstall) allow running arbitrary code which can read/write files locally, steal keys and tokens, install malware, and otherwise exfiltrate data.
  • Your dev/CI computer(s) (build time execution)
    • Compilers, bundlers, transpilers, plugins, etc., can all execute arbitrary code and leak secrets, corrupt build artifacts, add hidden payloads, etc.
  • Your application server (server runtime execution)
    • Any dependency runs top-level in production and exposes risk to data exfiltration, unsafe privilege escalation, remote command execution, etc.
  • Your users’ computers (client runtime execution)
    • Bundled dependencies ship with your website, exposing your users to malicious code that runs in their browser and can exfiltrate data, insert hidden trackers/miners, etc.

Reply via: Email · Mastodon · Bluesky

Related posts linking here: (2025) Social Share Imagery via a Data Attribute · (2025) AI Browsers: Living on the Frontier of Security

From: Codepen

410: Trying to help humans in an industry that is becoming increasingly non-human

Chris & Marie jump on the podcast to talk about just how drastically customer support has changed over the last few years. We still exclusively do customer support over email. Incoming email from real customers who need a hand with something where they type out that email in plain languages themselves are few and far […]

From: Stuff & Nonsense

New and improved compound grid generator

To get ready for my first practical layout workshop for designers this week, I upgraded my compound grid generator with a new and improved version.

The brilliant Michelle Barker made the first compound grid generator and I included a modified version with Layout ❤︎. To get ready for my layout workshop for designers, I’ve added some extra functionality:

  • Add a gap value in em, px, % or rem
  • Copy the generated compound grid CSS to the clipboard
  • Download a WebP image of the generated compound grid

Try the new and improved compound grid generator and book a spot on my workshop. There are still one or two tickets available.

From: Buzzmachine

The nation is lost

In this terrible time, what disappoints and angers me so about my own field of journalism — to which I have devoted 50 years of my life — is its refusal to recognize fascism, to even use the word so as to explain it, and to judge Trump and the Trumpists for their crimes against decency, democracy, and humanity.  […]

The post The nation is lost appeared first on BuzzMachine.

From: Codepen

Chris’ Corner: Little Bits of CSS

Adam Argyle is clear with some 2025 CSS advice: I think every front-end developer should know how to enable page transitions, transition a <dialog>, popover, and <details>, animate light n’ dark gradient text, type safe their CSS system, and add springy easing to animation. Nobody asked me, but if I had to pick a favorite of Adam’s six, it’s all the stuff about animating […]

From: Stuff & Nonsense

New date for my practical layout workshop for designers

If you thought you’d missed my practical layout workshop for designers, well—thanks to COVID—you didn’t.

Yeah, COVID is still a thing, and last week it knocked me sideways. So far sideways that I had to postpone my practical layout workshop for designers for a week. The new date is this coming Thursday, 25th September online at 3pm UK time. If you bought a ticket, it’s valid for the new date and there’s a special treat coming your way by means of an apology for the inconvenience. If you didn’t, now’s the time to pick one up.

Let’s be honest: Website layouts have become a bit boring

Design systems, frameworks, and templates are everywhere. And sometimes, even great ideas look like everything else. Over the past year, I’ve been exploring how classic layout principles from comics, posters, and magazines can bring energy and storytelling to digital design. This session is where I share what I’ve learned, with examples, demos, and practical takeaways you can actually use.

Why attend?

Grab a seat and join me for a two-hour session where you’ll:

  • Explore layout ideas from places like comics, fanzines, movie posters, wrestling promos, and more
  • Learn how to break the rules of the grid without breaking your design
  • See real-world examples of expressive, narrative-driven layouts for websites and products
  • Leave with layout ideas you’ll want to try right away

What we’ll cover

Hour 1: Creative layout thinking

  • Why 12-columns aren’t the only option
  • How modular grids help create hierarchy
  • Why compound grids expand creative options
  • Patterns and layout techniques that create visual rhythm

Hour 2: Real demos, real feedback

  • Watch me break apart and rebuild layouts live
  • See how to apply layout principles to existing designs
  • Ask layout questions, and I’ll answer as many as I can in a live Q&A

Who’s this for?

This is for you if:

  • You’re a designer or front-end dev tired of playing it safe
  • You love good craft, but want more fun and feeling in your layouts
  • You’re building sites or products and want them to stand out, not blend in
  • You’ve got a basic grasp of layout tools (Figma, Webflow, or code), but want to level up creatively

This isn’t a beginner tutorial or a deep dive into CSS. It’s for working designers who want to push past the obvious and bring more of themselves to the page.


Practical details

New date: Thursday, 25th September
Time: 3pm UK time
Duration: 2 hours live (with demos and Q&A)
Format: Online (join from anywhere)
Recording included

Only £69. Get all Layout ❤︎ templates free, worth £9.99.



UPGRADE: VIP feedback session

Want me to take a closer look at your layout challenges? Add a VIP follow-up session (capped at 8 people) for just £29:

Friday, 26th September, 3pm UK time
60 minutes of small group feedback—bring your own layouts
Recording included and tips tailored to you


Design doesn’t have to be boring

You don’t need to rip up your process or become a “creative genius” overnight. You just need fresh eyes, inspiration, and a few tools to help you bring more life into your layouts. I’ll show you how. Ready to design with more personality? Book your place now and get all Layout ❤︎ templates free, worth £9.99.

From: Jim Nielsen

Anti-*: The Things We Do But Not All The Way

I was reading Chase McCoy’s article “Antibuildings” where he cites Wikipedia’s entry on the term “Antilibrary” which points to another entry about the Japanese concept of Tsundoku, all of which deal with this idea of things we do with intention but that never make it to fruition.

Antilibraries are the books we buy but never read.

Antibuildings the architect’s version of sketches and plans drafted but buildings never made.

It got me thinking about the stuff I’ve started with intention but never brought to fruition — my own anti-*’s.

To name a few:

  • Antidomains: the domains I bought and had big plans for, but they never progressed beyond being parked at my registrar. (Zach Leatherman recently made a list kinda like this, if you haven’t seen it.)
  • Antiwebsites: the sites I was gonna make, but never shipped.
  • Antilayers: the Photoshop, Sketch, or Figma designs I painstakingly crafted to the level of “completeness”, but then never began building with code.
  • Anticode: the changes I made that functioned to the level of being usable and shippable, but then I never could pull the trigger on ‘em.
  • Antiposts: (also known as “drafts”, lol) all those blog posts I poured time and energy into researching, writing, and editing, but never could take all the way to “published”.
  • Antitweets: all the Tweets/Toots/Skeets I meticulously crafted as witty comebacks or sarcastic quips, but then never posted (honestly, probably for the better).

And last, but certainly not least — in fact, probably grandest of them all:

  • Antitabs: all the browser tabs of articles, videos, recipes, and other good things I collected and was going to read, watch, bake, etc. but never did.

Photo of a bookshelf on top with lots of books, below that a screenshot of a bunch of tabs where all you can see is favicons


Reply via: Email · Mastodon · Bluesky

Related posts linking here: (2025) Social Share Imagery via a Data Attribute

From: Stuff & Nonsense

Unfinished Business #135: Andy Bell. All the best bands are power-trios

In this episode of Unfinished Business, Andy and Rich are joined by Set Studio founder and publisher of Piccalilli, Andy Bell.


Sponsored by:

Practical layout workshop for designers and creative teams

This workshop is for designers who want to break free from the gridlock and create layouts that feel bold, expressive, and uniquely theirs, without losing clarity or usability.

Design systems, frameworks, and templates are everywhere. And sometimes, even great ideas look like everything else. Over the past year, Andy has been exploring how classic layout principles from comics, posters, and magazines can bring energy and storytelling to digital design. This session is where he shares what he’s learned, with examples, demos, and practical takeaways you can actually use.

Date: Thursday, 25th September
Time: 3pm UK time
Duration: 2 hours live (with demos and Q&A)
Format: Online (join from anywhere)
Recording included

Only £69


Also available on YouTube

For anyone who can’t get enough Unfinished Business, we publish the show in video format on YouTube.

Watch “Unfinished Business” on YouTube

Sponsor Unfinished Business

The best way to promote your product or service to the Unfinished Business audience of creative professionals, designers, and developers. Sponsors get one exclusive two-minute ad per episode, live read by me or Rich, which feels personal and relatable. We can use your script or ad-lib, and you’ll also receive a link on each episode’s post, as well as a thank-you on our Bluesky and Mastodon accounts. Interested? We’d love to hear from you.

Support Unfinished Business on Patreon

We also have three monthly membership plans so you can support Unfinished Business on Patreon. $5, $10, and $20 if you’re feeling especially generous. All money goes towards podcast editing and hosting. Support Unfinished Business on Patreon.

From: Zeldman

Everybody’s lost it, Part I

My beloved veterinarian’s office apparently moved to a new office location without informing customers. They also changed phone systems. The new phone system doesn’t work, and they didn’t leave a forwarding message on the old phone system. You call, leave a message, never hear back, and never learn what’s become of the business. Our oldest […]

The post Everybody’s lost it, Part I appeared first on Jeffrey Zeldman Presents.

From: Codepen

409: Our Own Script Injection

Chris and Stephen talk about how we use a Cloudflare Worker & HTMLRewriter to inject a very special <script> tag into the previews of the Pens you work on. This script has a lot of important jobs so it’s presence is crucial, and getting it in there reliably can is a bit of a challenge. […]

From: Codepen

Chris’ Corner: Terminological Fading

I found myself saying “The Edge” in a recent podcast with Stephen. I was talking about some server-side JavaScript that executes during a web request, and that it was advantageous that it happens at CDN nodes around the world rather than at one location only, so that it’s fast. That was kinda the whole point […]

From: Meyerweb

Bookmarklet: Load All GitHub Comments (take 2)

In which I update a bookmarklet to load all the comments on super-long GitHub threads.

From: Dave Rupert

Many years on the job and I still don't get it.

I’m coming up on 20 years of professional web development and I still don’t get it sometimes. I tend to measure myself or view work productivity through the lens of “How much code did I write?” and that does a great disservice to myself and what I do.

There’s a lot more to the job:

  • Checking email
  • Scheduling calls
  • Writing release notes
  • Contributing to newsletters
  • Documentation (code and otherwise)
  • Making spreadsheets
  • Demystifying the work I do to teammates
  • Clarifying decisions
  • Having technical conversations with teammates
  • Having non-technical conversations with teammates
  • Investigating weird browser behaviors
  • Babysitting servers and build processes
  • Reviewing PRs
  • Manual QA on branch deploys
  • Attending meetings
  • Attending talks (internal/external)
  • Cross-org contributions
  • Learning
  • Planning
  • Dreaming
  • Scheming
  • Community Ops
  • Moving cards across a board
  • Reading thru backlogs
  • Associating tickets to PRs
  • Closing out old tickets
  • Reading specs
  • Giving feedback on web standards
  • Eating lunch
  • Taking walks
  • Cleaning my home office

These are all aspects of becoming a better web developer. It’s not always about lines-of-code or hours-in-chair. Ideally, we’re all shipping our creations, but sometimes you’re the lead role and sometimes you’re a supporting role. A lot of the work is immeasurable, but it all counts towards something. So… self, don’t be so hard on yourself.

From: Codepen

408: Proxied Third-Party JavaScript

Chris and Stephen hop on the podcast to discuss the concept of a proxy. Possibly the most “gray hat” thing that CodePen does. We use a third-party analytics tool called Fullres. We could just put a link to the <script> necessary to make that work directly to fullres.com, but being an analytics tool, it’s blocked […]

From: Codepen

Chris’ Corner: Simple, Accessible Multi-Select UI

There’s a nice article by Enzo Manuel Mangano called Checkbox Interactions – The beauty of Layout Animations. In the end, you get some nicely animated checkboxes, essentially: I like it. It’s a modern-looking multiple-choice with very clear UX. Enzo’s tutorial is all React Native-ified. I think Enzo is a React Native guy and that’s his […]

From: Stuff & Nonsense

Anti-Nazi League inspired, Far Right. So Wrong t-shirt-designs

The Reform UK conference is happening this weekend. While they aim to portray themselves as an alternative to mainstream parties, their intolerance, racism, and xenophobia are not far from the surface. So I designed “Far Right. So Wrong” shirts with profits going to support Hope not hate.

I’ve seen the kind of distrust and hatred of immigrants whipped up by Farage and his supporters before, in the late 1970s and ’80s when The National Front—forerunners of the British National Party, who were forerunners of the Brexit Party and now Reform UK—stoked fear and exploited frustration. The far right was defeated then, and it must be defeated again.

Anti-Nazi League inspired t-shirts
Smash the Nazis • Nazis Keep Out • Black & White Unite.

Available designs


Set up in 1977, the Anti-Nazi League opposed the rise of far-right groups in the UK. Until its closure in 1982, the ANL stood against the National Front and the British National Party (BNP). Now, with the far-right and racist Reform UK gaining ground, we must rekindle the spirit of the Anti-Nazi League.

Anti-Nazi League inspired t-shirts
Don’t Vote for Nazis • RFM=NZS • Available in black or white.

Available designs


All proceeds go to Hope not hate

Inspired by the iconic Anti-Nazi League artwork by David King, every purchase helps fund HOPE not hate, who are dedicated to challenging the far right in Britain.

From: Dave Rupert

“Why would anybody start a website?”

Nilay Patel sat down for a Decoder interview with Microsoft CTO Kevin Scott to talk about NLWeb, an open source effort to allow an LLM-style indexing of small websites and provide local search. Instead of having large centralized search indexes like Google or Bing, the indexing shifts to sites having their own local indexes that large search platforms hook into via an MCP, an API endpoint for LLMs (basically). Lots to unpack there, but at first glance I like the idea of local ownership of search indexes over the “scrape everything” model that’s killing the Open Web.

I was listening to the episode because it’s relevant to my work, but I also like Nilay Patel’s perspective and think he has a sober 10,000ft view of the tech industry; without fawning over CEOs, new tech, and VC hype. That is rare in “ride the wave” tech media space. One moment in the episode that hit me a little hard was Nilay asking “Why would anyone start a website (in 2025)?”

You know what’s interesting about that? I’ve asked a lot of people over the past several years, “Why would anybody start a website?” And the frame for me is when we started The Verge, the only thing we were ever going to start was a website. We were a bunch of people who wanted to talk about technology, so in 2011 we were going to start a website. We weren’t even going to start a YouTube channel. That came later after people started doing YouTube channels at scale. At the time that we started, it was “you’re going to start a big website.”

Now in 2025, I think, Okay, if I had 11 friends who wanted to start a technology product with me, we would start a TikTok. There’s no chance we would be like, we have to set up a giant website and have all these dependencies. We would start a YouTube channel, and I’ve asked people, “Why would anyone start a website now?” And the answer almost universally is to do e-commerce. It’s to do transactions outside of platform rules or platform taxes. It’s to send people somewhere else to validate that you are a commercial entity of some kind, and then do a transaction, and that is the point of the web.

The other point of the web, as far as I can tell, is that it has become the dominant application platform on desktop. And whether that’s expressed through Electron or whether it’s expressed through the actual web itself in a browser, it’s the application layer… [interview swerves back to AI tools]

As someone who loves websites, blogs in particular, this is a tougher question than I want it to be. Nilay’s conclusion comes down to two types of websites:

  • E-commerce
  • Application

I don’t think this is a wrong answer, but it does have a whiff of capitalism. These are certainly the most profitable forms of website. Nilay implies the new “way of doing things” is to build your platform in a silo and then branch out into the website game for an economic end. Is the new path to start a YouTube or TikTok and then figure out your web strategy? I certainly know of web dev streamers who jumped into the selling coffee game after minting themselves on YouTube and Twitch. They still maintain their X accounts to capture those eyeballs. I suppose it’s hard to abandon those monetize-able surfaces.

This conversation feels akin to the conversation around the role of a content creator in the age of AI. If these tools can produce content faster, cheaper, and at times better (see: good-fast-cheap triangle)… how do you make a living in the content creation space? Woof. That’s a tough question. And I’d point out the invasion of low-effort content seems to disrupt the whole “content-to-lamborghini” pipeline that Nilay suggested above.

I think my answer to “Why would anybody start a website (in 2025)?” is the same answer for the content creator in the age of AI problem: I don’t know, but you gotta want to. Money sweetens the deal when making content or websites, but we’ve shaken the money tree pretty hard over the last couple decades and it’s looking bare. Increasingly, you’ve got to find other sources of inspiration to make a website – which by the way are still the coolest fucking things ever.

To put a pin on the question about making a website, I guess I’d say… if you have ideas bigger than the 280~500 characters limit? A website. If you make non-portrait videos longer than two-minutes? A website. If you make images bigger than the 1280x720 summary card? A website. You throwing an event and need to communicate details but not everyone has Facebook accounts? A website. You want to eschew the algorithmic popularity game? A website (with RSS). You want to take part in the rewilding your attention movement? A website (with RSS). You want to own your own content? A website. You want to be an anti-capitalist? A website (with RSS). If you want to be a capitalist too, I guess? A website (with a paywall). You want to be anonymous? A website. You want to “share what you know”? A website.

Still reasons to make a website, I think.

From: Codepen

407: Our Own CDN

Robert and Chris jump on to talk about our little CDN project. Maybe that’s not the right term, but we struggled with naming it. Truth be told, it’s the /public/ folder in our monorepo, where the purpose is getting files to the world wide internet at URLs that anyone can access. Our favicon is a […]

From: Codepen

Chris’ Corner: Clever Clever

David Darnes made a <code-pen> web component, which is a basic HTML/CSS/JS panel layout that renders them into an iframe (using the very cool <syntax-highlight> web component as well). Then it ate itself when Ariel Salminen put a <code-pen> in a <code-pen>. Then the universe collapsed upon itself when Rob Rhoades made a code pen […]

From: Dave Rupert

Git diagramming "The Weave"

We all know the current US President is one hell of an orator and often assures us that he has “the best words”:

I went to an Ivy League school. I’m very highly educated. I know words. I have the best words.

The man knows words. Says so right there. While some might view his non-sequitur ramblings as the nascent stages of dementia or an unfiltered ADHD brain launching into successive short (at times racist) bullet-point diatribes based on the last word or phrase he said like a cursed game of word association, the President asserts this is not the case:

You know, I do the weave. You know what the weave is? I’ll talk about, like, nine different things, and they all come back brilliantly together. And it’s like - and friends of mine that are, like, English professors - they say, it’s the most brilliant thing I’ve ever seen.

The Weave” re-entered my consciousness this week after I watched a quick snippet of an Oval Office event where Trump says the (“radical left-wing”) CBO projects tariffs will reduce the deficit by $4 trillion USD. I was skeptical –and for good reason– but I tuned in. What shocked me was not the complete lack of specifics about the CBO projection, but rather the actual reason for the Oval Office meeting: a FIFA event? Wow.

For awhile now, I’ve clued into the cyclical pattern of his speeches, little snippets of “the best words” and talking points assembled like a ransom note cut from a magazine. I often wondered if it’s possible to diagram “the weave”. The “branching” narratives Trump uses made me think a git-graph-style visualization was apropos. So I grabbed a transcript and got to work.

For my first attempt, I used Mermaid.js’ GitGraph Diagram which worked well but only supports horizontal charts. As I sat with it I realized I wanted a chronological list of statements that read like a transcript. I repurposed the Mermaid’s GitGraph DSL and made a web component called <git-graph> to help me visualize and document Trump’s derailing trains of thought from the above event.

I would recommend viewing this on my site with JavaScript enabled.

branch tarrifs
checkout tarrifs
commit id: "I was very happy that today, as you saw, the uh group that does this [the CBO], a government group,"
branch radical-left
checkout radical-left
commit id: "a radical left group, announced that Trump was right"
checkout tarrifs
merge radical-left
commit id: "took in $4 trillion worth of tariffs"
commit id: "The $4 trillion they're going to reduce the deficit by numbers far greater than they ever expected or heard of."
branch stock-market
checkout stock-market
commit id: "And by the way, the stock market went up a thousand points. That was as of 10 minutes ago."
commit id: "I can't tell you what happened. A lot of things happened, but the stock market's up almost a thousand points."
cherry-pick id: "I was very happy that today, as you saw, the uh group that does this [the CBO], a government group,"
commit id: "It's basically on the news that uh the release that just came out from government that uh the tariffs that everybody was talking about that"
branch world-respect
checkout world-respect
commit id: "the whole world respects us for because of what we did"
cherry-pick id: "took in $4 trillion worth of tariffs"
commit id: "The tariffs are going to be at $4 trillion." 
cherry-pick id: "The $4 trillion they're going to reduce the deficit by numbers far greater than they ever expected or heard of."
commit id: "They're going to reduce the deficit by $4 trillion."
branch ask-jd
checkout ask-jd
commit id: "[Seeks validation from JD Vance]"
checkout stock-market
merge ask-jd
cherry-pick id: "And by the way, the stock market went up a thousand points. That was as of 10 minutes ago."
commit id: "It's had a huge impact and the stock market is way up."
commit id: "But this will drive more than $30 billion in US economy"
commit id: "and create 185,000 American jobs."
branch fifa-event
checkout fifa-event
commit id: "No sporting event attracts more attention or more fans or anything else"
commmit id: "And I just look forward to the draw."
commit id: "So we're going to have the draw essentially, Gianni, at the Kennedy Center"
branch kennedy-center-remodel
checkout kennedy-center-remodel
commit id: "and by that time it'll be in even better shape. We're working on it."
commit id: "It's about a year project to make it."
commit id: "It'll be great. It'll be fantastic."
branch oval-office-remodel
checkout oval-office-remodel
commit id: "You see the way [the oval office] is looking?"
commit id: "Looks nice."
commit id: "I can't tell you how much that gold costs, a lot of money."
commit id: "There's nothing like gold and there's nothing like solid gold."
commit id: "But this beautiful office needed it."
commit id: "It had to be representative when we took it over."
commit id: "It was dirty, not clean."
commit id: "I immediately changed the chair and had the this beautiful desk renovated, brought out by the White House."
commit id: "People that do this, they did a great job."
commit id: "They sent it out. We have a craftsman who's great."
commit id: "But this was not appropriate for the Oval Office when I took over."
commit id: "And now you look at all those paintings [instructs to look at paintings]"
branch painting-vault
checkout painting-vault
commit id: "All of these are great presidents and they were all in the vaults."
commit id: "They were in vaults for in some cases much more than a hundred years."
commit id: "And now they're proudly hanging on the oval office walls and I can't imagine anybody changing it."
commit id: "But they were they were buried in vaults for over a hundred years, many of them."
checkout oval-office-remodel
merge painting-vault
commit id: "So it's very exciting. People come in, they really love it."
branch self-congratulations
checkout self-congratulations
commit id: "They love what we're doing here."
commit id: "They love what we're doing in DC [deploying the national guard against American citizens]"
commit id: "and they love what we're doing most importantly in the country in the world. [citation needed]"
checkout fifa-event
merge self-congratulations
commit id: "I'd like to ask Gianni to say a few words ... [flattery] ... he's got the biggest event in the world coming right here to the United States."
commit id: "We did a little for Canada,"
commit id: "we did a little for Mexico."
checkout self-congratulations
merge fifa-event
commit id: "We thought, see, I'm a good citizen. I said, let them have a little piece."
cherry-pick id: "We did a little for Canada,"
commit id: "So, we gave a little to Canada."
commit id: "See how nice I am."
cherry-pick id: "we did a little for Mexico."
commit id: "And we gave a little bit to Mexico."
checkout fifa-event
merge self-congratulations
commit id: "Gianni, please say a few words."

By my count in that four-minute address there were ten distinct themes or “branches”, most of which are common grievances or rhetorical themes found in nearly all Trump speeches. I used “cherry-picking” to model callbacks to a previous statement (e.g. “the stock market is up”) that seem to reverberate into later trains of thought, a quintessential feature of the weave.

Four minutes of the weave was about all I could handle but I think this visualization models what I experience when trying to follow along to the President’s speeches. One or two phrases on a topic, then jumping to a new topic, weaving in a (sometimes unrelated) point from a previous topic to make the thought appear more cohesive and linear, then driving deep down an inconsequential topic. When he talks so long about ten different topics at a time, I’d forgive you for thinking he said something salient. But when you break it down you see it for what it is: a mishmash of talking points.

From: Codepen

406: Hot Trends of 2025

Marie and Chris jump on to discuss some of the trends of what people are building on CodePen here, approximately halfway through 2025. New CSS! Hot Styles Hot Pens Time Jumps

From: Stuff & Nonsense

Unfinished Business #134: Léonie Watson. Bundles of enthusiasm

In this episode of Unfinished Business, Andy and Rich are joined by accessibility consultant, co-founder, and bundle of enthusiasm, Léonie Watson.


Sponsored by:

Practical layout workshop for designers and creative teams

This workshop is for designers who want to break free from the gridlock and create layouts that feel bold, expressive, and uniquely theirs, without losing clarity or usability.

Design systems, frameworks, and templates are everywhere. And sometimes, even great ideas look like everything else. Over the past year, Andy has been exploring how classic layout principles from comics, posters, and magazines can bring energy and storytelling to digital design. This session is where he shares what he’s learned, with examples, demos, and practical takeaways you can actually use.

Date: Thursday, 25th September
Time: 3pm UK time
Duration: 2 hours live (with demos and Q&A)
Format: Online (join from anywhere)
Recording included

Only £69


Also available on YouTube

For anyone who can’t get enough Unfinished Business, we publish the show in video format on YouTube.

Watch “Unfinished Business” on YouTube

Sponsor Unfinished Business

The best way to promote your product or service to the Unfinished Business audience of creative professionals, designers, and developers. Sponsors get one exclusive two-minute ad per episode, live read by me or Rich, which feels personal and relatable. We can use your script or ad-lib, and you’ll also receive a link on each episode’s post, as well as a thank-you on our Bluesky and Mastodon accounts. Interested? We’d love to hear from you.

Support Unfinished Business on Patreon

We also have three monthly membership plans so you can support Unfinished Business on Patreon. $5, $10, and $20 if you’re feeling especially generous. All money goes towards podcast editing and hosting. Support Unfinished Business on Patreon.

From: Stuff & Nonsense

Far Right. So Wrong. New t-shirt designs

I’m sickened by the rise in support for Far Right politics, especially Reform UK, especially in Wales. So I designed a set of “Far Right. So Wrong” shirts with all profits going to support Hope not hate.

Look, I get it. People are increasingly disappointed with successive governments and disillusioned by mainstream political parties. The decades-long pendulum swings between centre-left and centre-right parties have left the country worse off, not better. Plus, the established narrative about immigration and the problems surrounding migration faced by many countries has given them a focus for their grievance with politics.

A party like Reform UK–exploiting people’s fears and led by former investment banker Nigel Farage, a political charlatan who both “delivered” Brexit and then applied for German citizenship while drawing a £73,000 EU pension–is not the answer.

I’ve seen the kind of distrust and hatred of immigrants whipped up by Farage and his supporters before, in the late 1970s and ’80s when The National Front—forerunners of the British National Party, who were forerunners of the Brexit Party and now Reform UK (no link)”marched with Union Flags and the cross of St. George through British Cities. The far right was defeated then, and it must be defeated again.

David King’s designs, the Anti Nazi League, and Rock Against Racism spearheaded opposition to the far right in the 1970s.

David King posters for the Anti Nazi League
David King poster for the Anti Nazi League

BWanker!

Inspired by David’s iconic designs for the Anti Nazi League, I’ve made a set of Far Right. So Wrong t-shirts. The first one, “BWanker!” is available in black, white, and Reform UK colours.

Banker t-shirt

FCK FRG, FCK RFM

Then, there’s “FCK FRG” and “FCK RFM” in the style of FCK NZS, plus “Stop Racism. Stop Reform” which are available in black and white.

FCK FRG, FCK RFM t-shirts

All proceeds go to Hope not hate

All proceeds from these shirts will go directly to help fund Hope not hate, the organisation dedicated to opposing far-right extremism.

From: Codepen

Chris’ Corner: Pretty Palettes

I’m not terribly good at picking a good color palette out of thin air. My go-to is a dark look with bright colored accents, but I’m wildly envious whenever I see a beautiful website with great looking colors that are very far away from what I could pull off. Sometimes, a little inspiration can go […]

From: Stuff & Nonsense

Getting creative with images in long-form content

Yours truly over at CSS Tricks: “When you picture placing images in long-form content — like articles, case studies, or reports — the standard approach is inline rectangles, breaking up blocks of text. Functional? Sure. Inspiring? Hardly. So, how do you use images to add personality, rhythm, and even surprise someone along the way? Here’s how I do it.”

Read Getting creative with images in long-form content.


Practical layout workshop

As well as writing for CSS Tricks I will also be running a workshop on layout design on Thursday, 18th September. I will be covering:

  • Why 12-columns aren’t the only option
  • How modular grids help create hierarchy
  • Why compound grids expand creative options
  • Patterns and layout techniques that create visual rhythm

You can learn more and book here.

From: Meyerweb

No, Google Did Not Unilaterally Decide to Kill XSLT

The Web Discourse has been spicy of late, and XSLT is to blame. Well, sort of. It’s complicated.

From: Dave Rupert

Limiting YouTube to a Single Tab

This week I decided to go nuclear on my bad YouTube habit. I installed a plugin called Tab Limiter that lets me limit youtube.com to one tab at a time. Clicking links that open in new tabs will now auto-close the tab.

Why do this? I talked about it before but when I’m bored I open tabs. Adding friction here prevents me from CMD+clicking videos during moments of boredom and creating a month’s-worth unclose-able tabs of videos to watch. It encourages me to stay focused and nudges me towards YouTube’s lossy1 “Add to queue” feature to queue up one video at a time in a single tab. I sort of prefer this way of using YouTube and it makes it feel a lot more like a native app.

That inspired me to install the YouTube Progressive Web App and because the PWA is basically a dedicated tab, Tab Limiter keeps me from opening other videos in new tabs. I’m now funneled into the application.

Opening a dropdown and clicking “Add to queue” is adding more “good friction” to the process. It also comes with a counter. 20 tabs open, no big deal, I’m immune to that effect. 20 items in a queue. Yeesh. That’s a todo list.

Screenshot of the tablimiter UI, it has unstyled for fields for URL and a tab limit quantity

Tab Limiter has a brutalist UI and that’s what makes it perfect. It’s also open sourced on GitHub which is important to me so I can make sure it’s not sending my browsing history to China. And I can fork it. One improvement I’m considering is to add the closed video’s ID to the YouTube queue before closing the tab. It seems easy enough, but probably not as easy as I’m hoping. The core idea there is that it might be helpful if I come across an urgent watch-now link or someone sends me a link.

I’m also still using Raycast Focus which is a great way to blockout time and stop distractions at the source.

  1. YouTube queues only exist in memory in the tab context, it’s not a cross-tab feature so if you close a tab and started a new one, the entire old queue got erased forever.

From: Zeldman

Too many meetings?

At Automattic, we know our time is finite and precious. Here are the questions we ask ourselves before agreeing to any meeting:

The post Too many meetings? appeared first on Jeffrey Zeldman Presents.

From: Meyerweb

To Infinity… But Not Beyond!

More explorations of ways to abuse the CSS `infinity` keyword, this time with more than just lengths.

From: Codepen

405: Elasticsearch → Postgres Search

Alex & Chris get into a fairly recent technological change at CodePen where we ditched our Elasticsearch implementation for just using our own Postgres database for search. Sometimes choices like this are more about team expertise, dev environment practicalities, and complexity tradeoffs. We found this change to be much better for us, which matters! For […]

From: Dave Rupert

Classifiers and cosmotechnics

I’ve been playing around with Midjourney for work and the one thing that makes Stable Diffusion cool and useful to me is the --sref flag to summon results in a specific visual style or “style reference” (e.g. Celestial Swirlscape is --sref 2566192150). They differ a bit from traditional or “artist” styles (e.g. “In the style of Picasso” or “Rip off Studio Ghibli”) but can be that or they can be more generic or compositional like “Pink Retronetic Dreamscape”. I’ve read a deep-dive on SREF codes and it’s still a bit unclear how they work to me. They’re like a hybrid between prompt shorthand and style classification. Curated and collected by humans, but a code generated by machines. I have to imagine there’s some clumped circles on a node graph chart somewhere that determine this… but I don’t know those answers.

The idea of a classifier (human assisted or otherwise) that can suck up and analyze all the art on the internet and end up with a 10-digit number that represents nearly any visual style of imagery I’ve ever seen is mind-bending. Not to mention the ability to overlay that style reference on any image I want in under a minute. “Anime waifu. --sref 3196580341” is the “Tea. Earl gray. Hot” of digital imagery. It feels unreal.

Could we apply a universal classifier to blog posts so that your “longread about cool bugs” and my “longread about cool bugs” have the same --sref tag? And then we retro-actively apply human-readable tag names to this stylistic tag? And then could I subscribe to a feed of those specific types of posts? That might be interesting… or radicalizing.

Design tokens? Could those be a system of classifiers instead of arbitrary language? Probably not. But why not? Web design almost certainly could, if it isn’t already.

While the idea of classifiers tickles the logical computer part of my brain, reducing the entirety of the visual arts down to a set of ten billion categories offends the artist part of my brain. It is odious. There’s an observer effect to it whereby in the act of classifying the art you’ve limited and altered your ability to understand it. And any mimicked generation has an imposter-like, soul-less character to it, no matter the quality. I can’t explain that. Even though I’ve seen the machine generate incredible art beyond anything I’m capable of, I still feel that intangible void on my retinas when I interact with it.

My wife and I were joking about how the algorithm is serving us videos about certain personality quirks that map to (possibly made-up) niche disorders. My wife –who can remember the melody to every guitar solo but can’t remember the words of the songs from her own band– has a diagnosis from Dr. TikTok that she has “polyphonic perception”. My personality quirks all point to my particular flavor of ADHD. How long until our entire personalities are all tied to a collection of niche diagnoses? How long until our brains are all classified by a ten-digit number? That could be incredibly useful for getting help but brings up nature versus nurture questions for me. Did God make me this way or did I dent the packaging? Can people with --brainSpiceRef 2566192150 even apply for this job? How long until the machines build these types of preferences? Myers-Briggs but instead of made by a racist, it’s made by MechaHitler.

When I think about the future I want, it always comes down to one idea: I want a pod-like chamber I can walk into that scans my entire body, makes bleep-bloop noises to show that it’s working, and prints out a receipt with a list of all my ailments (cancers, deformities, disorders, and otherwise) and recommends a diet and exercise plan until my next scheduled visit to the pod. Bonus points if it orders groceries accordingly after my entire family has exited the chamber. I’m aware this has “Big Theranos Energy” and is an incredible surface area for conspiracy theories… but it’s the science fiction future I want. Classifiers seem inevitable on that pathway. But how do we preserve our humanity when reducing the human race –who we are and what we create– down to a series of ten-digit codes?

From: Dave Rupert

Vibe Check №39

In the middle of the night on the morning of July 4th, a storm parked over the Texas Hill Country and caused the Guadalupe river to rise more than 25 feet in two hours. 135 dead, including dozens of children from summer camps along the river. As a parent, this is the greatest tragedy you could imagine. My heart goes out to the families and friends who lost a little one that week.

As a Texan, this is yet another tragedy in a growing list of rare but forecastable tragedies where federal, state, and local officials failed Texans. I’m tired.

With that event casting a dark shadow on the summer acknowledged, here’s a recap of the last couple months.

A trip to the Grand Canyon

the grand canyon near bright angel trailhead

In late June my family stole away for a quick trip to Arizona. My in-laws bought a vacation place in Flagstaff to escape the Phoenix heat. We wanted to check out the new place and figured we could do something American and tag on a quick trip to the Grand Canyon.

On the morning of the second day we arrived at Grand Canyon National Park early. We found a good parking spot steps from the canyon’s edge and told our kids to get out and see the view. I’ve been to the canyon a couple times but nothing can truly prepare you for the enormity and pastel grandeur you’re about to see. I enjoyed re-living the first glimpses through my kids’ collective gasps of awe… and after about 10 minutes they were ready to go home and get on their iPads.

We milled around the park for nearly two hours making frequent stops. We stopped at the Devil’s Watchtower on the way out of the park which I’d recommend. All-in-all, we saw something truly remarkable together and my wife and I felt like we checked off a big “This is good for you and you’ll thank us later” parenting checkbox.

The next day the kids rode back with the grandparents to Phoenix while my wife and I took a short detour to go see Sedona. All these years visiting Arizona and I’d never been. We don’t buy into all the energy crystal woo-woo the town advertises, but it’s a beautiful and inspiring piece of America with incredible vistas and sculpture-like red stone mountains. I’d like to spend more time there.

We had a couple days in Phoenix to hang with cousins and celebrated my great-nephew’s second birthday. He’s a cool dude. Mid-week we headed back to Austin to send the kids to summer camp. That week could have been a great one for my wife and I to enjoy an empty house, but I ended up (over-)working all week.

Trip to San Diego

The day after the kids got back from summer camp we packed our bags again and headed to San Diego with my wife’s entire family. The next four days were beach days; digging holes, playing guitar, hitting the smashball, dozing off to books, and chasing a toddler around. I stayed in my solar fortress most of the time to avoid my enemy: The Sun.

But it wouldn’t be a Rupert Family Vacation without some calamities! On the second day my son got the worst sunburn of his life; no blisters, just red. He’d survive… but he didn’t know that. I sympathize because I had tons of sunburns as a kid. When it itches, it sucks.

And then there’s my daughter…

At the end of the week we tagged on a couple more days and visited Austin friends who spend the summer in Encinitas. Our daughters who have been besties since daycare slotted right back into their brand of silly lip sync routines and giggling. To soak up more beach time, we hiked down the cliff to Beacons beach and set up some chairs in the rocks while the girls boogie boarded their hearts out having the time of their life until…

My daughter comes to us holding her arm crying. When she reached for the loose boogie board leash she slammed her hand down and said she felt something fold over her arm and sting her. We walked over to the lifeguard stand and got the bad news, “That looks like a sting ray.”

The untold irony here is all week long my daughter was telling anyone who would listen that her two greatest fears about the ocean were: getting caught in a rip current and getting stung by a stingray. We tried to diffuse those fears but she kept talking about it. And here we were, the prophecy came true.

“I can call a lifeguard truck to meet you at the top of the hill but you have to take care of it now.” Uh-oh. That’s when I knew we were in a serious situation. We said no to the lifeguard truck but needed to submerge her arm in 115ºF water (hot tap water) for 30-90 minutes to neutralize the proteins in the venom. We hiked back up the cliff and walked the three blocks to the house. Tears the whole way.

After a couple hours everything was sore but stable. She’s a tough kid and that was a difficult situation. What a champ.

We survived: A skunk attack

Late one night my daughter (who has a sensitive smeller) said “Something smells like skunk!” I caught a faint whiff of it and thought “It’s probably some neighbors smoking weed” and opened the back door to assess the situation and in rushed my two mutts, one of them covered in skunk juice! Yikes!

We did our best to corral them to the garage where we washed them with an internet-recommended concoction. I can’t even describe the degree to how awful this was. The smell infiltrated our house and sulfur burned in the eyes and nose all night long. We spent the next day Fabreezing and disposing of any rogue object the smell might have transferred to: the backdoor mat, collars, one kids sandal, the dead skunk near the trash… Ah, gross.

A skunk attack is not a situation you can control (dogs being dogs) but it’s not one I want to relive any time soon.

Another school year begins

This week we strap ourselves into the bobsled and push the sled downhill on an out-of-control course where the breaks do nothing and it sends us crashing into Christmas. Feeling optimistic about this year, but there will be more homework for both our kids which is historically not a strength we operate in as a family. Lord help us.

Stats

Here you go, number perverts. All the dopamine deep-dives and drive-thrus I collected over the summer.

🧠 Learning

  • Sovietology - Based on a space race analogy I heard at work I made a deep-dive on the Soviet space program which led me to Sovietology and trying to understand how the Soviet central planning system (“cybernetics”) failed its fellow comrades.
  • ADHD - Been watching a lot of videos on ADHD and trying to understand it more
  • Minimalism and decluttering - ADHD videos lead me into minimalism and decluttering videos and it makes a difference if you view clutter as stimulus. If I could just get the rest of the family on board…
  • Drawing - I’d like to be good at drawing, so I spent a lot of learning about shapes, perspectives, sketching, and more
  • Studio Setups - Because ShopTalk has a YouTube now, I’ve become a little bit obsessed with optimal YouTube setups but I haven’t done anything… yet
  • Budgeting - After all our summer trips and feeling spent (physically and fiscally), I sat down one weekend and did some budgeting and ingested a lot on the subject.

❤️‍🩹 Health and wellness

A lot of updates here but still untangling the Gordion knot of stress, anxiety, weight, and ADHD. I’m talking to doctors and making some changes and I believe they are helping even if it’s not fully realized yet.

📝 Blogging

Over a dozen posts over two months with some vacations in there, that’s about all you can ask for.

📖 Reading

Behind pace for the Book-a-Week Club and that’s fine with me.

System CollapseThe Wrong StuffSpace Battleship YamatoRed PlentyADHD and UsA Different Kind of PowerDungeon Crawler CarlMoral AmbitionWin Every ArgumentThe Dawn of Everything
  • System Collapse ★★★ - The last book in the Murderbot Diaries. This one was a slog, to be honest. The action at the end was good but the crescendo right before that, the big group project… was disappointing.

  • The Wrong Stuff ★★★★★ - A great book about the relative failure of the Soviet Cosmonaut program compared to NASA even though the USSR had many “firsts” they did so without regard to the safety and stability of their program and rockets.

  • Space Battleship Yamato ★★★½ - Got this from Kinokuniya to satiate my retro space manga obsession. It delivered on the space opera promise but had a lot of the early-days manga pitfalls. That wasn’t a deal-breaker for me but could be for some I’m sure.

  • Red Plenty ★★★ - A historical fictional narrative about site managers and scientists under Khrushchev’s rule. It paints a nice picture about the economics (“cybernetics”) and central planning of that time, but sometimes the narrative was too thick (like Dostoyevsky thick). Reaffirming I’m a non-fiction guy.

  • ADHD and Us ★★★★ - A good book for people in a relationship where one or more partners are neurodiverse. Recommended by my psychiatrist.

  • A Different Kind of Power ★★★★½ - Jacinda Arden’s autobiography is a bit hard to read because of how calm, cool, collected, and capable she seems compared to her American contemporary Donald Trump who was nothing but chaos and incompetence.

  • Dungeon Crawler Carl [In progress]

  • Moral Ambition ★★★★ - I enjoyed Bregman’s other books more, but this book certainly is challenging. It asks you to consider how you can make the biggest, moral, positive change and adjust your life towards that goal. That certainly tugs at my heartstrings but is a tough call to action in uncertain times.

  • Win Every Argument ★★★★ - Former MSNBC anchor Medhi Hasan shares some Oxford debate club knowledge on how to convincingly argue your point and back it up with receipts.

  • The Dawn of Everything ★★★★½ - A wonderful book that really reprogrammed a lot of inherent biases I had about “uncivilized” cultures. I never viewed Native Americans as “savages” like the history books and cowboy movies want you to believe, but… primitive? I’m almost embarassed to admit that this is what I thought anyways until I read this book and realized they were quite civilized and more advanced than us on many levels (civically and emotionally), operating on a different rule book entirely. It makes you wonder if society, without its kings, could function differently.

📺 Media

Saw some good movies this period… which is rare.

Movies

  • 28 Years Later - Good movie. Lots of zombie dong, or… it’s more accurate to say one notably huge alpha hog.
  • Superman - I enjoyed a DC movie; a Superman movie! Unbelievable. Has James Gunn saved the DC cinematic universe? Hopefully.
  • K-Pop Demon Slayers (Netflix) - An wonderful animated film and you can see the foundation of fun from the creative and technical teams come out. Great job Sony Animation.
  • Fantastic Four: First Steps - The art direction in this movie is incredible… fantastic even. A real cinematic feat. Worth seeing in theaters.

TV

  • Welcome to Wrexham S4 (Hulu) - Up the town. Unreal ending.
  • Murderbot (Apple TV) - Loved the books… and uh… you can watch the show, if you want to, it’s fine I guess.
  • Mythic Quest S5 (Apple TV) - Not for everyone but feels algorithmically generated for me.

Streaming

  • Game Changer S7 (Dropout) - This season of Game Changer has managed to outdo itself and that’s an incredible a feat.

Anime

  • Mobile Suite Gundam Gquuuuuux (Prime)

Podcasts I purged my podcasts and abandoned some of my favorites (like The Adventure Zone), but I think I’m better for it. Now I can focus on the ones I enjoy.

  • If Books Could Kill…
  • Maintenance Phase
  • Living Planet
  • ATXplained

🎙 Recording

ShopTalk

🤖 Gunpla

This hobby isn’t dead yet! I’ve got five or so in the backlog but three of them are practice kits for a larger project I have in mind. In service to that project, I tried my hand at anime cel-shading an Entry Grade RX-78-2. I tried half-a-dozen application techniques and didn’t find a way that I liked. I need to do more research and keep trying.

🌱 Digital Gardening

  • Made my homepage tie-dyed for funsies. It’s based off the accent color and changes a bit every day.
  • Built some automation for my vibechecks, will hopefully post more later.
  • Added more pentatonic scales to Pentablaster… it’s in a messy state right now but I wanted to play with Ethiopian scales. I have plans to fix it up.
  • Regenerated cover images for my stories page using Midjourney. I think I did better this time around.

👾 Video games

Mostly puzzles, but I did go reopen the door to a city builder.

  • Cities Skylines - I hooked up SteamLink to play my PC games from the shed inside the house on my Mac. Trying to play enough Cities Skylines 1 to justify buying Cities Skylines 2.
  • Balatro - The joker addiction continues. Feel like if I beat one more stake I’ll be happy and can quit.
  • Clues by Sam - A daily caper! If you’re not playing this you should be.
  • Stars - A sudoku-like puzzler from Inkwell Games
  • Fields - A difficult pattern game from Inkwell which I first thought was impossible but now feel like I’m getting the hang of it.

From: Buzzmachine

Len Tow

We have lost a most generous soul. I have lost a benefactor, mentor, and friend. Leonard Tow died Sunday at age 97.  Len held a PhD in economic geography from Columbia and taught at Hunter and Columbia before deciding to leave for business, first in theater and then in the infant industries of cable TV […]

The post Len Tow appeared first on BuzzMachine.

From: Stuff & Nonsense

Podcast: One Footer in the Grave Episode 17: A possible logo emergency

Andy, Jon, Marcus, and Paul are back for another silly episode. They talk about Paul’s new caravan, Andy’s semi-retirement, and Marcus giving up beer. But the episode is interrupted in a dramatic fashion when Jon is involved in a serious logo emergency. If you haven’t listened for a while, this one’s a belter!

Listen to the episode

From: Meyerweb

Infinite Pixels

In which I push browser engines to their finite limits using infinite values.

From: Dave Rupert

All the concerns that make you a boring developer

I was thinking this morning about how once you understand that your technology choices have security, performance, and accessibility considerations you become a much more boring developer. Acknowledging those obligations can sort of strips the fun out of programming, but we’re better for it.

I decided to pull on that thread a little more and come up with a list of all the concerns you might have as an engineer/developer that ultimately compound to make you a boring, wet blanket of a person to be in meetings with.

  • Security - Make sure you’re not opening the door for hackers.
  • Privacy - Don’t leak personal information. Or don’t collect it in the first place.
  • Performance - Can the software work on low-end devices? Can you deliver the large bundle over bad internet? Those are your problems.
  • Inclusion/Accessibility - Are you allowing people the dignity to use your product? No? Oof. You should probably do that. Ideally because you are an ethical person, but also because it’s a legal liability.
  • Scalability - If a thousand people show up in the next minute, does your software still work? You have 100 users now, but how does it work for 1000? 1 million? 1 billion?
  • Maintenance - Ship a new feature? Great. Expect to spend at least 40% of cost/time to maintain a feature over its lifetime.
  • Testability - Did you write the code in a way that’s easy to test to make sure bugs don’t show up in production?
  • Deliverability/Distribution - How do people get or use your software?
  • Adoption/Onboarding - How do customers or partners use your software? How do they get familiar?
  • Documentation - Email and DMs is probably not the most efficient form on knowledge transfer.
  • Ecological - Does your app burn through GPUs in Iowa? What are you doing about that?
  • Financial/Cost - Servers and GPUs cost money, did you build this in such a way that it costs as little as possible to run?
  • Monetizability - Good idea but does it make money or cost money?
  • User feedback - What are customers or partners saying about this? Does that impact how or what you write?
  • Stakeholder feedback - Like user feedback but everyone freaks out like their job depends on solving the problem that day regardless if its a good idea or bad idea.
  • Organizational - How to get your co-workers onboard with the plan plays an outsized part in software engineering. Welcome to the world of office politics!
  • Staffability - There’s not a lot of Haskell developers out there. Or the inverse, people over-optimize on technologies that are “easy to hire for” and now you have a billion lines of Java in your application.
  • Support matrixes - For websites, of course we support major browsers and the latest 2 versions? Do we need to go back further? Weirdo browsers? Should we make native apps? Which ones? What devices/CPU architectures do we support there? Niche Linux distros? The list goes on.
  • Political - Some say “all tech is political”, and I tend to agree, but ask yourself: Did you put a politics inside the code? You did, didn’t you?
  • Geopolitical - Rare, but happens. See: Facebook Myanmar genocide
  • Localization/Internationalization - Uh-oh, your UI doesn’t work in German or Arabic. Also all your images and icons are offensive to a particular country’s monarch. Are you ready to cross the borders? Get ready for VAT tax tables, ughck.
  • SEO/Crawlability - Cool website you made, can robots get to it and index it? Now LLMs are coming and slurping up your content and traffic. Uh-oh!
  • Adjacent competitors - What your competitors are doing will always play a role in engineering. Looking better than them is good, being cheaper is good too, but one rule is the most important: never be slower. See: Platform adjacency theory
  • Throughput/Velocity - How fast can you and (more importantly) your team ship an idea from conception to production. What about turnaround times on bug reports?

If you ever ask a developer if an idea is possible and their brain lags out with a little loading spinner over their head, it might be this enormous pile of concerns they’re mulling over. That can be an issue, but I’d be more concerned about the developer that instantly says “Yes” to everything. And if you’re tired of developers saying “No” all the time, ask your developer about ways to put them in situations where they can say “Yes”.

From: Zeldman

Staying relevant

“And in their place came acceptance.” Staying relevant in your profession as you age and technology changes.

The post Staying relevant appeared first on Jeffrey Zeldman Presents.

From: Dave Rupert

Theater UX

I saw this summer’s Marvel movie in the theater on Sunday. A bit of a last minute idea so we ended up going to the “legacy” movie theater across the highway. Before I continue, It’s important to understand my local cinema dynamics. We have two theaters here in Austin: The Alamo Drafthouse and All Other Cinemas.

The best place to see movies in Austin is at the Alamo Drafthouse. If you’ve never been to an Alamo, I’m sorry. It’s a movie theater for people who love movies by people who love movies. They craft the entire art house experience from end-to-end. From the custom pre-screener of thematically topical clips, to the strict no late arrival and no texting policies, to custom food and drink options that match the latest blockbuster movie. A waiter brings you food, drinks, and refills so you don’t have to leave your seat. The trailers are a tight 15 minutes announcing new releases and special events where they bring back old movie classics (set to an era-appropriate soundtrack, of course). Every year they have an indie movie festival to showcase the weirdest films the industry has to offer. Going to the Alamo is a thoughtful experience through and through and they sell out nearly every show opening week. You pay more going to the Alamo of course but I think everyone would agree it’s worth it for most movies unless you’re looking for a quick n’ dirty alternative.

Contrast that to the “legacy” theater. I call it the legacy theater because this was the nice, brand new theater when I went to college 25 years ago; one of those big 24-screen nationwide chain movieplexes with a four-machine arcade and stadium seating. Six plexiglass teller windows tell the history of how popular this destination was in its time. It’s flagship theater is an enormous 4D IMAX. It of course (like the Alamo) has the push button recliners and swivel food trays. The nicest thing about the “legacy” theater is that there’s always open seats and that’s where the problems start to reveal themselves…

The first thing you notice at the “legacy” theater is that no one occupies the teller windows anymore. Instead you go inside to meet a greasy teenager who scans a QR code for the ticket you have to buy online. You go to the snack bar and load up on enormous free refill tubs of popcorn, drinks, and overpriced candy; it’s almost certainly a $50 stop. Then you go to the nearly empty theater and wonder if you walked into the wrong theater by accident. Before the movie starts you sit through the hokey pre-screen trivia and local ads and when the start time hits… you watch 35 (!!!) more minutes of ads with a couple trailers mixed in. And after all that you’re out of snacks and the movie starts.

The user experience contrast between the two couldn’t be more stark. One is thoughtful and compounds the experience at every turn and the other is enshittified with ads. One keeps you wanting to come back and the other makes you wonder why you came here in the first place (or worse, it makes you want to leave). At least its clean, I guess. One sees attention as precious and not-to-be-disturbed, the other sees you as captured by sunk costs and a pair of monetizable eyeballs. One will sell you a fresh pizza, a popcorn, and a couple refillable sodas for $50 and the other will sell you day-old popcorn, an impossibly large cup of soda, and some Sour Patch Kids for $50… after you do the math, the better experience isn’t any more expensive so it’s not even competing on price.

It’s no wonder why the “legacy” theater is always empty. I bet its owners would love to see all the seats full again. It all comes down to UX. One works hard creates a vibrant scene and fosters a culture1 for people who like films, the other is real “death of cinema” vibes. People (sometimes thousands!) put so much effort into these films to make the best film possible, only to have that experience ruined in the last mile. It’s tragic and I guess I’ll just catch it when it comes to streaming.

In related news, last year Sony Entertainment acquired Alamo Drafthouse. I’m not sure if that makes it more or less probable that you’ll be able to experience an Alamo in the future. We’ll see where it goes from here. Hopefully they can continue their relentless focus on the user experience.

  1. I’d be remiss if I didn’t call out the #metoo and union busting issues that were happening behind-the-scenes at Alamo and revealed in 2022. While Alamo has done a lot to create immense cultural capital here in Austin, that ascent has not been without enabled bad behavior. Similar issues plague Hollywood too.

From: Dave Rupert

A modest proposal for new holidays to manage your digital life

The cost of being online is getting too damn high and I’m tired of pretending it’s possible to fit these tasks into a normal life. That’s why I’d like to share a modest proposal for a new set of holidays to manage our digital lives:

(Ahem.)

  • A day to clear out your inboxes
  • A day to reset your passwords and delete old accounts
  • A day to fix your calendars
  • A day to cancel online service subscriptions
  • A day to manage the tags on your website
  • A day to switch out any critical apps
  • A day to backup your computer and phone
  • A day to organize your photos
  • A day to organize your music collection and playlists
  • A day to setup your new phone/computer
  • A day to try out a new app or major piece of software for your primary workflow
  • A day to delete old text messages

All I’m asking for is 1/30th of a year that we end up cramming into other days. I’m willing to trade some of the B-tier holidays (Easter, Thanksgiving, etc) for this. If you work in the government please call me, it is URGENT.

From: Dave Rupert

A fiscal recalibration

After all our summer trips I buckled down last weekend and did some budgetting and I’ve realized I have to update the spreadsheet in my head. Here’s how much things cost in my outdated DaveBrain 2000 operating system:

  • Fast food -$5/person = $20/family
  • Snacks - $2.50/person = $10/family

That –as my bank account is telling me– is super incorrect. The real numbers are much more like:

  • Fast food - $12.50~$15/person = $50~$60/family
  • Snacks - $5~$7.50/person = $20~$30/family

And groceries have gone up too. Woof. Hard times in the concrete jungle.

We’re updating the database and cutting back on these obvious financial vampires. And we know when/why we tend to rely on them to get us through the week. So that’s good. But when you have kids –snack-reliant kids at that– introducing austerity measures like this is hard, because being a penny-pinching dick about money all the time probably isn’t good for them either.

Don’t worry about me though. I’m lucky to have a great job and two kidneys, I’m sure I can sell one of them for a decent amount.

Namaste.

From: Dave Rupert

The Economy? He died five years ago.

I hold a conspiracy theory the global economy died five years ago during Covid. It’s been on life support through stimulus checks and flash tech hype cycles ever since trying to keep the dormant heart beating. You sense it too. There’s no beating heart. There’s no thumping energy. No vein of excitement. Tech and knowledge work seems to be suffering the most.

The death of the Economy started long before Covid if I’m honest. Since the iPhone it feels like everyone has been waiting for the next big hit, the next new shiny, the next money-maker. It’s like an endless distracted boyfriend meme looping year over year. And I regret to inform you that the investors are at it again. Today it’s LLMs, before that crypto and the Web3 Metaverse, before that VR, before that the gig economy, before that smartwatches, before that smart-homes, before that 3D televisions, before that…

The phalanx of tech billionaires behind Trump at the inauguration is an image seared into my memory and it’s taught me a lot. It taught me that these companies are desperate. Desperate to win favor. Desperate to avoid regulation. Desperate to keep their government contracts. Because without the preferential treatment, the lawlessness, and the humongous contracts, they’re financially and morally bankrupt.

(To be fair –why do I feel the need to be fair to tech billionaires!?– from a Friedman doctrine perspective their job is to create value for stakeholders. Kissing the ring of the petty, easily-aggrieved, fascist, man-baby tyrant is probably the most surefire way to avoid unwanted scrutiny in uncertain fiscal times. I understand that part of their job. But I’d wager the long-term outcome will be that they set themselves up for future embarrassment, exploitation, and extortion while simultaneously selling out all the immigrants, queer people, and furries who keep their empires running on a daily basis.)

That scene in the rotunda reinforced my belief the economy was already dead. If Big Tech is clinging to government contracts and quid pro quo perks, then we must be out of ideas. Every time the winds of fortune change, everyone points their boats in the same direction. In a healthy, living economy shouldn’t there be more than one lake to fish in? Instead of asking “What doesn’t exist and would be useful?” and investing in that, it’s about “How can I extract the most money from hot new tech?” Instead of “What’s quality?” and chasing that, it’s “How can we move fast and make breakable things?”

An aside: What if there are no new ideas? What if the internet accelerated knowledge sharing to the point we’ve made all the software and we’re literally out of ideas!? There are no more worlds left to conquer, Alexander! Help!

I doubt that though. I bet there’s good ideas out there. I bet they’re not on Mars. I bet they’re inside people you already know. Impractical ideas that don’t scale well to billions of users but could have an incredible impact on a local economy and community (RIP Gowalla). Ideas that solve actual problems and create actual utility or connection. Small-scale ideas that when combined can breathe new life into a dead economy.

The definition of a healthy economy is actually one problem I had with the Biden administration. Liberals do a terrible job communicating economic accomplishments even though they outperform Conservative administrations by a large margin. When they do communicate it’s always in lagging indicators like GDP, the stock market, non-farm jobs, consumer price indexes, or low-unemployment numbers. Those are all well and good, but to me it all comes down to a single question: If I lost or quit my job today how easy would it be to find another similar job? To me economic mobility is the true sign of a healthy economy, the ability to have options. To be free.

I’m trying to stay optimistic, but the realist in me knows it’ll be some time until the economy comes back again. At a minimum, we’ll have to restart investments in science. Especially weird science. Even more weird than what you’re thinking right now. I’m talking super weird. And then that weird science takes 20 years to become practical applications. Through that public good is how we get the foundations like the Internet, WiFi, and GPS that have built the society we know and are dependent on today. It’s how we build the pipeline for tomorrow’s economy. But those innovations are on a decades timescale and –math-wise– I’m not sure I have that in me.