Jim Nielsen’s Blog

You found my HTML feed — I also have an XML feed and a JSON feed.

I HTML

Subscribe to my blog by copy-pasting this URL into your RSS reader.

(Learn more about RSS and subscribing to content on the web at aboutfeeds.)

Recent posts

Estimated Reading Time Widgets

View

Beware ye who enter, here be personal opinions.

I’ve never understood reading time estimation widgets. Why did these get so popular? Is it because they’re easy? I mean, you can grab one off npm no problem.

Screenshot of a large number of search results from npm for the keyword “reading-time”.

Baldur suggests a theory in his piece about estimated reading times:

At some point a programmer read in a study that the average person read 233 words per minute and decided that this would be a great way to estimate reading time for everybody on the fucking planet.

The “reading time” for an article always felt so personal to me. As Baldur also points out, it can be affected by so many variables, such as:

  • Word count or length
  • Writing style
  • Design (formatting, typeface, etc.)
  • Individual physical factors
  • Vocabulary
  • Medium

Because I’ve always seen reading time as such an incredibly personal thing, I’ve never once paid any heed to these widgets. In fact, I’ve been slightly perturbed a service would presume to know how quickly I could read an article.

That’s to say nothing of the fact that if I come to a text to understand it (or merely enjoy it for that matter), speed is the very last thing on my mind.

I’ve always viewed any service that sticks a “reading time” widget on its articles as the literary equivalent of fast-food: you’re not here for quality, but for expediency.

Personally, I think they devalue a text more than they add to it.

But hey, I’ll grant that’s just like, my opinion, man.


Reply

The Ruthless Edit

View

Rick Rubin gives this advice about working in the studio with artists when making an album:

[Let’s say] We’ve recorded twenty-five songs. We think the album is going to have ten. Instead of picking our favorite ten, we limit it to: “What are the five or six we can’t live without?” [So you] go past the goal to get to the real heart of it, and then you say: “Ok here are the five or six we can't live without, now what would we add to that which makes it better and not worse?” It puts you in a different frame when you start with building and not removing.

I love this! So often in design, engineering, or product, you’re faced with this decision: how do we pare down what we have to something that feels like a cohesive whole?

The impulse is to ask, “Well what do we have to cut it down to?” Then, knowing the limit, you pick your favorites until you hit it.

But that impulse overlooks the fact that things don’t exist in isolation. They exist in relation to each other. So if you’re merely picking your favorites up to an arbitrary limit, you’ll be left with a whole whose individual pieces are great but don’t sum to anything greater.

This particular course of action creates a mindset where there is no more “creation” only “deletion”. You go from a mode of “creating” to a mode of “editing” but you never look back to creating.

Instead, Rick recommends this idea of a “ruthless edit” where you go beyond your initial limit, then shift back to “creating” mode.

If the limit is ten, you choose five. Then you switch from editing back to creating begin asking: how can we add back in a way that elevates the whole? This encourages you to not merely selecting things based on their individual merits. Rather, you select a core set of things that carry the thrust of what you’re trying to do and then you add complementary things around that core to bolster the very things you loved so much in the first place!

An Illustration

This can all sound a little theoretical with words alone. Let me try to illustrate with an example.

Let’s say you have roughly twenty five things.

Twenty five seeminly random black circles scattered on a white background.

And you’re told the limit is ten, so you single out your ten favorites.

Twenty five seeminly random black circles scattered on a white background, with ten random circles highlighted in red.

Then you cut away everything else, so you’re merely left with your favs. How well do they stand together as a whole?

Ten seeminly random red circles scattered on a white background

Contrast this with a scenario where you follow Rick’s advice.

You’re told the limit is ten, so you start with five of your absolute favorites — the ones you know you can’t live without.

Twenty five seeminly random black circles scattered on a white background, with five random circles highlighted in red.

Now you can ask important questions about building back up to ten. How do these five relate to each other? How do they relate to the remaining options? How can I choose five more that build on these core five favorites and produce something whose sum is greater than the individual parts?

As you look at these relationships, a new, underlying pattern reveals itself which you hadn’t seen before. So you choose five more which support your initial core selection, making the overarching whole better and more cohesive.

Twenty five seeminly random black circles scattered on a white background, with ten circles highlighted in red revealing an undelying structure and pattern to their arrangement.

What you’re now left with, once you remove everything else, is something that reveals a unified, pleasing whole.

Ten circles on a white background in a structured grid.

This all comes about by changing the process through which you make edits. Editing becomes a process where you ruthlessly select a core then switch back to “creating” mode and build something around that core to create something amazing!


Reply
Tags

Seeing Others in Data, But Not Ourselves

View

Stanford psychologist Emily Pronin and her colleagues came up with an interesting study in human behavior.

Subjects were given incomplete words and asked to complete them with the first word that came to mind.

For example, you’re given the fragments B__T and CHE__ and you write BOOT and CHESS.

Afterwards, subjects were asked to explain what they thought their responses revealed about themselves: their interests, motivations, and character.

Then they were shown responses by other participants and asked the same question: what do these answers reveal about this person?

What happened is fascinating and simultaneously not surprising. Here’s author Kathryn Schulz’s summary:[1]

the same person who characterized her own choice of words as "happenstance" and felt that they revealed nothing about her inferred the following from another person's choices: ”I think this girl is on her period ... I also think that she either feels she or someone else is in a dishonest sexual relationship.”

People saw their own word choices as mere happenstance, while the word choices of others served as a kind of mirror reflecting the inner-most self of others.

Looking at their own word choices, one participant said:

I don't agree with these word-stem completions as a measure of my personality.

But looking at someone else’s, they surmised[2]:

I get the feeling that whoever did this is pretty vain, but basically a nice guy.

I think this is a fascinating study of a trait that, to be quite honest, I know operates in my own mind.

We believe other people can be known from the outside based on their words and deeds. However, we believe we can only be known from the inside — that’s how we know ourselves — and our words and deeds are not a fully accurate representation of who we are.

I wonder how much this phenomenon operates in the software industry as we pour over troves of user data looking for patterns that can lead us to generalized statements about behavior — statements we would make about others based on their outward behavior (as measured by data), but knowing inwardly we would never conclude the same thing about ourselves.

In other words: we believe data is a reflection of others, but not ourselves.

For example:

  • Seeing others: “They clicked on that banner ad, they must be interested in buying the product!”
  • Seeing ourselves: “lol, look at this thing! Who would ever buy this? I gotta click to see how ridiculous it is…”

Or:

  • Seeing others: “When prompted to leave a review, they clicked 1 star, so they must not like our product!”
  • Seeing ourselves: “I was too busy to leave a review when that thing popped up, so I just clicked 1 star because I couldn’t give a real assessment in good conscience and needed to get on with what I was doing.”

Or:

  • Seeing others: “They dismissed the banner offering them 50% off. They don’t like our sale!”
  • Seeing ourselves: “This random banner popped up while I was simultaneously clicking somewhere else and it immediately disappeared, so I never actually read what it said.”

I’m probably wandering too deep into the intersection of human psychology and science, so I’ll stop here.

But the general idea, as pointed out in Being Wrong, still stands: each of us live with our own intricate, internal reality. Our moods, emotions, and thoughts fluctuate in a complex way we ourselves don’t even understand. It’s easy to feel no one can draw conclusions about our true nature without access to this inner world. But do we extend the same courtesy to others?

Neither you nor I can be truly known by the data we leave behind.


Footnotes
  1. This story comes from Kathryn Schulz’s book Being Wrong which I’ve been reading (shout out to Mandy for the recommendation).
  2. Want to read how funny some of these contrasting characterizations are? Check out my photo from the page in the book.
Reply

Personal Websites Are As Vulnerable As Us

View

I look at some people’s personal websites and think, “Stupendous! If I ever reach that zenith of personal web design, I will call it quits.”

Then I read a post by them later and they say something like, “Gah! I just really don’t like where I’m at with my personal website.”

And in my mind I say, “WHAAAAAATTTT??!?!?”

To me, they’re living the personal website dream! But they don’t feel that way. They seem to feel…well the same way I feel about my personal website.

It’s like our personal websites are a mirror to ourselves — a place where the mind’s eye must reconcile with the optical eye’s perception of reality.

It’s a torturous affair, to be sure.

And yet, people still publish those personal sites, those redesigns, those half-baked ideas.

There’s something vulnerable about publishing a personal website for the whole world to see, like standing up before a big crowd.

And there’s no bigger crowd than the whole internet.


Reply

Sanding UI

View

One of the ways I like to do development is to build something, click around a ton, make tweaks, click around more, more tweaks, more clicks, etc., until I finally consider it done.

The clicking around a ton is the important part. If it’s a page transition, that means going back and forth a ton. Click, back button. Click, right-click context menu, “Back”. Click, in-app navigation to go back (if there is one). Click, keyboard shortcut to go back. Over and over and over. You get the idea.

It’s kind of a QA tactic in a sense, just click around and try to break stuff. But I like to think of it as being more akin to woodworking. You have a plank of wood and you run it through the belt sander to get all the big, coarse stuff smoothed down. Then you pull out the hand sander, sand a spot, run your hand over it, feel for splinters, sand it some more, over and over until you’re satisfied with the result.

With software, the fact is that sometimes there are just too many variables to know and test and smooth out. So I click around, using the UI over and over, until I finally cannot give myself any more splinters.

Just the other day, I was working on a list of radio options, pretty standard-fare stuff:

  • Create a <label> with an associated <input type="radio">.
  • Put them on the same row, center align them with a gap between the control and the label.
  • Etc.

As an oldie who used to leverage floats in CSS, I’m still amazed when I can use flexbox to do this stuff — it’s so easy!

<div class="container">
  <label for="control">Foo</label>
  <input id="control" type="radio">
</div>

<style>
    .container {
      display: flex;
      flex-direction: row;
      align-items: center;
      gap: .5rem;
    }
</style>

As I was doin’ my thang — clicking around a bunch, trying to get some splinters — I realized there was a dead spot in the UI, a place between the radio and the label where clicking didn’t toggle the control like I expected.

Animated gif of some radio inputs where the space between the control and the label doesn’t select the radio grouping.

“What the?” I thought. “I’ve got my <label> and <input> and associated for attribute, why isn’t this working?” Then I thought, “gap in my flex display must be the culprit!”

Screenshot of Chrome developer tools where an item has a flex layout with a CSS gap in between a label and an input.

Sure enough, it was. While flexbox had made it super easy to add some visual spacing between the control and its label, that spacing had become a dead zone of interaction even though it wasn’t my intention!

There’s probably a million different ways to solve this problem — because CSS is awesome — but I just removed the gap and added some padding to my label, then voilà!

Screenshot Chrome developer tools with a label that has a left padding.

Putting padding on the label, instead of the containing flexbox, made the whole thing clickable without a deadzone.

Screenshot of the Chrome developer tools where an element has a flex layout but no gap.

A bunch more clicking around and things were working as expected.

Animated gif of some radio inputs where the space between the control and the label can be clicked and it selects the entire radio grouping.

It’s a small thing, but lots of small splinters lead to an agonizing experience.

So my recipe is: sand it, feel the grain, get a splinter, sand again, and repeat until smooth.


Reply

The Humble Link

View

I was joking on Mastodon about how the zeitgeist has changed over the years, but its pattern is revealing itself: an acronym which merely drops letters. The Next Big Thing™ is clearly going to be “A”.

  • 2010: Everyone needs an "API"
  • 2020: Everyone needs "AI"
  • 2030: Everyone needs "A"

So I just need to figure out what “A” is and I’ll be rich!

Annie came back with this response that won’t get out of my head:

<a> the magic we already have

On snap. Mic drop right there.

It’s pretty wild that so many of the power struggles going on in tech stem from what is ultimately a fight over linking to something.

  • The app store & steering provisions: you cannot <a> to an outside website
  • AI: it won’t <a> to anything and cite its sources.
  • Social media: you only get one <a> (“link in bio”)

That Tim-Berners Lee really threw a wrench in things when he made the humble <a> tag.

Links are incredibly powerful. The web’s reputation is often that it’s playing catch up. However, when it comes to links, that original invention is still transforming the world.

Meme of Boromir from the Lord of the Rings where he’s holding the ring with wonderment. The ring is overlaid with an anchor tag and the caption “tis a strange fate we whould suffer so much feat and doubt over so small a thing”


Reply

Notes from Pen & Teller’s Masterclass

View

I quite enjoyed Pen & Teller’s Masterclass (paywall, sorry!). I learned some practical card tricks that came in handy while we sitting in the airport waiting for a connecting fight with restless kids.

I also really enjoyed Pen & Teller’s reflections on the art of their craft. Here are a few points I wanted to write down.

Magic is a Playground For Determining What’s Real

One fundamental question we all have to ask ourselves is: how can I know what is and isn’t real?

Our eyesight is often our primary tool here — “I see it, therefore it is”.

But magic, as Pen & Teller note, makes you realize that what you see with your eyes may not always be true.

Teller notes that how we determine what is and isn’t real has profound implications in our day to day lives. For example, you have to determine whether the bus you see hurtling towards you is actually a bus or not. If you can’t determine that quickly, you’re dead. So: how do you determine what is real?

Magic is the playground for that. Where you can explore that idea without getting hurt. I like how Pen put it:

Magic is the heaviest philosophical ideas you can possibly have, dealt with in the silliest way

He later notes that someone who plays with how we ascertain what’s real might actually be the best person to point us at what is, in fact, real:

The reputation of magician is honest liar. You are someone who experiments with what the truth is. And I believe if you do it right, you can be known as someone more concerned with truth and honesty than the people you’re working for. Someone that’s really explored how we ascertain what’s true and how we lie.

Magic Is Relational

Pen calls magic “anti-solipsistic”, i.e. the opposite of self-centered.

So many art forms can be enjoyed by yourself.

For example, you can write music for yourself. You can write poetry for yourself. You can write software for yourself.

But you cannot do magic for yourself because you are clued in on the deception.

Magic requires you to reach out, beyond yourself, to another human who you can perform for, and in this way it necessitates empathy, storytelling, and other practices from a rich variety of disciplines.

While much art is meant to be made for others, magic requires it.

We Are All Active Participant In Our Own Deception

If you know their show, Teller’s magic is mute. But he elucidates why he likes to try and do a trick without saying anything: it’s a challenge.

The magician enables the audience to tell itself the story that ([the magician]) wants to tell. It’s very hard for them to convince themselves of what they’ve constructed, and that’s much more convincing than when you try to force the meaning on them.

In other words, you expect a magician to tell you a lie while performing a trick. But if they can get you to misperceive something without actually telling you what to think, that��s a whole other level — and it’s way more convincing. (Reminds me of the movie Inception where they plant ideas in people’s subconscious, but in order for those ideas to have real staying power the person must think it was their idea and not planted there by someone else.)

The Joy of Magic

Teller notes that “art gives you the sense of a miracle”. It can be listening to Bach, or looking at Rembrandt, or watching magic. You experience it and you are mystified, because what seemed impossible was materialized as possible by another human being. He says:

(for me) the fundamental quality of a work of art is a sense of the impossible for a moment seeming to be real

Pen says that, “One of the things that makes life worth living is giving other people joy.” Magic is a subset of that.

I can testify to that. After watching this Masterclass on a long flight, then being stuck in an airport terminal on a five hour layover with three kids under 10 years old, I took one of the simple card tricks I learned in the video and performed it for my family and the marvel in their eyes was priceless.


Reply

New Workflow for Publishing Notes: Content in Dropbox, Code in GitHub

View

I recently changed my workflow around authoring and publishing my site notes.jim-nielsen.com. Here’s the rundown.

Before

Pretty standard JAMstack type stuff. All my notes are markdown files in a git repository that live alongside the code generating the website, e.g.

package.json
notes/
  note1.md
  note2.md
  note3.md
src/
  index.js
  styles.css

I author new notes in iA Writer. When I want to publish them, I move the file to my git repo, commit, and push to Netlify which builds and deploys the site.

This works fine, but I’ve never loved that the content and code for the site live in the same git repository, which requires a git tool for pushing new content or updates (much more cumbersome on a mobile device).

Now

All my notes are markdown files in Dropbox. I author them using iA Writer and Dropbox takes care of syncing everything.

When I want a new deploy of my site, I use a Shortcut that does a POST to a Netlify webhook and triggers a build/deploy.

Netlify runs my build process which, as part of the build, reaches out to Dropbox and gets a copy of all my markdown files, then processes them and turns them into a website.

Perhaps a diagram is worth a thousand words:

Diagram showing iA writer saves files to Dropbox, and running a Shortcut triggers a build in Netlify which pulls files from Dropbox (and code from GitHub) and produces my notes website.

I really like this workflow for a few reasons:

  • Content and code are separate. My git repository holds the code and I edit that with VSCode, while my markdown files are just plain-text files on disk and I edit those with my favorite writing app iA Writer.
  • I can easily make spelling corrections or publish a quick post from any device. iA Writer + Dropbox are available as apps on mobile, and the Shortcuts app can run from any Apple device.
  • I like to forever tweak my workflow and tools. Sue me.

It’s worth noting that under the hood I changed my build tool from Metalsmith to Web Origami: a fascinating tool for building small/medium websites from Jan Miksovsky. I want to write more about why I like this tool — especially the Dropbox integration piece — but I’ll have to save that for another post. If you want to poke around, the code is on GitHub.


Reply
Tags

Netlify Public Folder, Part V: Now With an Image CDN

View

On ShopTalkShow no. 628, Chris and Dave got to talking about s3/r2 and hosted media solutions. Dave graciously gave a shoutout to my Netlify “public folder” workflow, which reminded me of something I’ve been meaning to write about.

Chris mentions how he prefers being able to drop a large resolution image on a CDN as his “source” and then request transformations of that image on-demand as necessary, e.g. “I’ll upload my 3000px JPG source image and then reference it on my website as a 800px modern image format (AVIF, WEBP, etc.)”

That makes perfect sense to me. You really only want to keep the best image you have, then easily reference, transform, and serve it on your website.

And that’s what I’ve been doing with Netlify’s new image CDN in combination with my “public folder” workflow. All I need to enable this functionality is a few lines of code to properly configure redirects on my site to leverage Netlify’s image CDN.

The Results

I took a file and dropped it in my folder, synced it to Netlify, then requested various versions of it. Here’s what I got.

The original image, no transformations or optimizations. Exactly as it is on my computer:

  • /sample.png
    • PNG
    • 1024x1024
    • 220kb

An “optimized” version. Netlify’s image CDN optimizes and transforms the image as they see best given the user agent making the request:

  • /sample.png?optimize=true
    • AVIF
    • 1024x1024
    • 16.6kb

An “optimized” version resized to my own specifications:

  • /sample.png?optimize=true&w=64
    • AVIF
    • 64x64
    • 5.0kb

How It Works

My first thought in making this work was to create a special path prefix for everything that’s in my folder, e.g. /$/, and then I can append whatever image CDN query params I want:

[[redirects]]
  from = "/$/*"
  to = "/.netlify/images?url=/:splat"
  status = 200
  force = true

For example, a “public folder” like this:

public-folder/
  avatar.png
  2024/
    my-image.jpg

Would map to these URLs:

cdn.jim-nielsen.com/avatar.png
cdn.jim-nielsen.com/2024/my-image.jpg

This would would serve the original images as they exist on disk. You request an image and it’s 3000 pixels? That’s what you get.

If I wanted to transform or optimize any, I could prefix each URL like this:

cdn.jim-nielsen.com/$/avatar.png?w=64
cdn.jim-nielsen.com/$/2024/my-image.jpg?w=800

The problem with this kind of path-based redirect is that those URLs can break over time because they don’t represent a 1:1 mapping of file-on-disk path to URL path.

If I moved off Netlify one day but I had a bunch of <img> tags linking to some path prefixed with /$/ I’d have to deal with that (or even just serving files locally without using Netlify’s netlify dev tool).

So I wanted a solution that allowed me to reference the actual path to the files on disk with search params being the means to say “but I want this image optimized this way”. Under these constraints, even if I migrated off any kind of image transformation service, my original URLs would still work.

To accomplish this, I added this code to my netlify.toml file:

[[redirects]]
  from = "/*"
  query = { optimize = ":o", w = ":w" }
  to = "/.netlify/images?url=/:splat&w=:w"
  status = 200
  force = true
[[redirects]]
  from = "/*"
  query = { optimize = ":o" }
  to = "/.netlify/images?url=/:splat"
  status = 200
  force = true

In this solution, the URL paths to my images are a 1:1 mapping of files in my folder to files on the remote server. So even if the image transformation service isn’t working, my images will still show (just un-optimized).

The downside to this is that it requires explicitly handling redirects for each query parameter combination you want to use from Netlify’s image CDN because as soon as you specify one query param Netlify will strip off any others (whereas with a path-based solution, Netlify will pass all query params through).

It’s a tradeoff, but this works for me because longevity of the URL is the most important to me — plus I really only ever use the image width resize param and none of the others. So I only need two redirect rules.

My Full Workflow Today

So now I have this generalized workflow for storing images outside of a git repo and easily syncing them to a remote server for use anywhere across the web. And now with Netlify’s image CDN service, I can not only serve any images in my public folder, I can dynamically transform and optimize them on the fly.

Here’s my workflow today:

  • Save an image to a Dropbox folder (on my laptop)
    • e.g. /new-image.jpg
    • (Dropbox client syncs that folder to its server as a backup)
  • Run a macOS shortcut that deploys that folder of static assets to a website (cdn.jim-nielsen.com) on Netlify
    • Really it “syncs” the folder, because it doesn’t re-upload files Netlify already has from a previous “deploy”
  • All files in that folder are now live at my website in a structure mimicking the folder on my laptop
    • e.g. cdn.jim-nielsen.com/new-image.jpg
  • Add my own query params to resize that image on the fly
    • e.g. cdn.jim-nielsen.com/new-image.jpg?optimize=true&w=64

Reply
Tags

Blog Posts vs. Social Posts

View

From Emil Kowalski’s newsletter (my Feedbin cache for your convenience):

I started writing more blog posts recently. I like it because it's different than X. You get a spike of views when you share something on X, but that dies off quickly. If you provide great value with your posts, people will read it, share it, and talk about it. It's a compounding effect. They also feel more rewarding to me, you have something to look back on and (hopefully) feel proud of.

Yay for blog posts!

Generally speaking, the attention you get with a good post on social media is like a firework: it can light up fast and burn bright, but just as fast it disappears.

On the other hand, the attention you get from a good blog posts can be like a forest fire: it starts small but when it catches fire it rages for some time, burning longer and more intense than any firework.

Maybe that’s a bad metaphor. Here’s another one.

The power of a good blog post is like the power of compound interest: the impact seems minor and insignificant to start, but as time passes the effects compound and become quite substantial.

Here’s a chart depicting what I’m trying to say:

A graph with Attetion on the Y axis and Time on the X axis. Graphed are two lines: 1) a social media post which starts by garnering a lot of attention but quickly drops over time, and 2) a blog post which starts by garneing little attention by grows over time.

Whereas the inertia for a social post quickly losses steam as the algorithm prioritizes novelty, blog posts slowly build steam as backlinks are planted all over the internet driving a long tail of attention.

I rarely, if ever, have a social post from a few months ago that continuously garners attention (likes, responses, etc.) Whereas I frequently have blog posts from years ago that garner bursts of traffic because someone, somewhere (re)discovered it, shared it, linked to it, and drove attention to it.

Blog posts are like these little robot evangelists you release out into the world on your behalf. They work tirelessly, 24/7, spreading your thoughts and garnering attention as time marches forward.

Social posts die with the passage of time, whereas blog posts gain life from it!

Invest in something whose dividends compound with time. As Emil says, it’ll give you something to look back on and feel proud of.


Reply