jq

| 1 min read

I rediscovered jq the other day, a little command line tool to format, read, and transform JSON from the command line.

Jq falls into one of my favorite categories of tools: the “simple and do one thing good” category—the Unix philosophy at its finest.

Pipe any JSON to jq. The first thing you’ll notice is the added syntax highlighting.

A curl request to the GitHub API

A curl request to the GitHub API piped through jq

Then, you can use a path syntax to query the JSON object.

Filtering a JSON object with jq’s path syntax

The path syntax supports arrays and deeply nested objects, and can even map data with a pipe operator.

Transforming a JSON object with jq’s path syntax

Installing jq on a Mac is as easy as brew install jq. Read the docs for further instructions and a detailed explanation of the path syntax.


Consistency

| 1 min read

There are two bike stalls near my apartment. One is right in front of the door, the other around the corner. The one in front of the door is closest, so when I can, I store my bike there. However, most of the time that stall is full, and I need to go around the corner instead.

That’s fine. Until a next morning–when I’m still in a daze because I’m not a morning person–I take the walk around the corner, only to realise my bike was actually in front of the door. The day before was one of those lucky days I could store my bike in front of the door.

I quit using the front stall. The less choices I have to make, the more room I have for important things.

Read more


When to add types and when to infer in TypeScript

| 2 min read

Type inference is the ability to derive types from other pieces of code. TypeScript’s type inference is very powerful, even a minimal amount of typing adds a lot of assertions.

Just because you don’t need to add types, doesn’t mean you shouldn’t. This is how I decide when or when not to explicitly add types in TypeScript.

Read more


Local-first software

| 1 min read

Google went down today. Downtime at this scale doesn’t happen often, but when it rains, it pours. Google going down doesn’t only affect Google products, it also affect products connected to Google. App that require authentication with your Google account weren’t available, unless you were already logged in.

Coïncidentally, I came across a compelling article about local-first software. From a SaaS point of view, before the internet all we had local-first.

Read more


Masonry layouts with CSS grid

Masonry layout support has been added to the CSS grid specification! 🎉

Read more


Embed a web page with a web component and the shadow DOM

| 2 min read

Today, my colleague Freek asked for help embedding the webview of an email campaign in an iframe. He needed it in an iframe because embedding the HTML directly caused layout issues because the website’s CSS clashed with it.

After setting up the iframe, we needed to find a way to dynamically resize it based on its contents to avoid double scrollbars on the page. While possible, it required some icky scripting.

I took a step back. The problem at hand was that the CSS needed to be scoped somehow. While iframes were the only solution for a long time, these days we have the shadow DOM.

Read more


Going deep

| 1 min read

I recently stumbled across an over 5 year old comment on Hacker News about performance.

Lots of people make the mistake of thinking there’s only two vectors you can go to improve performance, high or wide.

  • High - throw hardware at the problem, on a single machine
  • Wide - Add more machines

There’s a third direction you can go, I call it “going deep”. Today’s programs run on software stacks so high and so abstract that we’re just now getting around to redeveloping (again for like the 3rd or 4th time) software that performs about as well as software we had around in the 1990s and early 2000s

Going deep means stripping away this nonsense and getting down closer to the metal, using smart algorithms, planning and working through a problem and seeing if you can size the solution to running on one machine as-is.

The author talks about “high” and “wide” hardware changes, but this can apply to software too. It’s easier to throw a cache at a slow piece of code than going deep and fixing it.

No need to look far, Electron is built on this principle. We’re adding heavy runtimes to support multiple platforms instead of staying close to the metal, and we pay the price in performance.

In general, it’s easier to add than subtract.

Which leads me to Derek Siver’s thoughts on subtraction.

Life can be improved by adding, or by subtracting. The world pushes us to add, because that benefits them. But the secret is to focus on subtracting.

The adding mindset is deeply ingrained. It’s easy to think I need something else. It’s hard to look instead at what to remove.

Adding is often a short-term solution. This isn’t necessarily a bad thing: time and budget restrictions are real problems. Adding often accrues more debt than subtracting, that’s the price we pay. Adding doesn’t save time, it lends time.


BlurHash

Last week, Unsplash added “blurhashes” to their API. Blurhashes are 20-30 character strings that represent a blurred placeholder of an image.

Blurred image placeholders aren’t new, but I was completely stomped to see what kind of gradient maps are generated with only 30 characters.

In short, BlurHash takes an image, and gives you a short string (only 20-30 characters!) that represents the placeholder for this image. You do this on the backend of your service, and store the string along with the image. When you send data to your client, you send both the URL to the image, and the BlurHash string. Your client then takes the string, and decodes it into an image that it shows while the real image is loading over the network. The string is short enough that it comfortably fits into whatever data format you use. For instance, it can easily be added as a field in a JSON object.

Unsplash uses the BlurHash algorithm to generate the placeholders. BlurHash is not a library but an algorithm, and they have 5 first party implementations including TypeScript. There’s also a third party package for PHP.

The algorithm is very simple - less than two hundred lines of code - and can easily be ported to your platform of choice.

Read more about BlurHash on GitHub.


Options, Not Roadmaps

Ryan Singer talked about how they (don’t) deal with roadmaps on the Signal v. Noise blog.

In short: roadmaps are a bad idea because they can create uncertainty, false expectations, and guilt. My favorite argument against long term roadmaps is the uncertainty.

We don’t have a crystal ball. Say we have features A, B, and C we want to build. We don’t know if A is going to work out as planned, and what that would mean for B. We don’t know if we’ll have a eureka in the bathtub one day, and new idea X will suddenly feel much more important than B or C. Or we might start building out B, only to realize that it’s not what we want or it’s harder than we thought and want to bail on it.

That means no explicit promises and no implicit promises either. A list on the wall or in some official strategy document is an implicit promise: “this is what we’re doing next.“ There is no official list of what we’re doing next anywhere in the company.

I strongly believe in not writing down big ideas for a product, because if it really is a good idea it will resurface, preferably multiple times.

That said, client projects are different beasts than homegrown software. Clients expect roadmaps, and there’s less wiggling room for features. You can’t really skip expectations, clients expect them. Mapping client projects is a different puzzle to solve.


How to schedule posts on a static Hugo site with Netlify and GitHub Actions

| 1 min read

If all went well, this post was published automatically. I added the ability to schedule posts on my static blog (built with Hugo). I wrote a short GitHub Action to trigger a build on Netlify every morning.

Read more