Archive for the ‘Uncategorized’ Category


Thursday, August 11th, 2022

We decided to move to tankless water heating at our house. So rather than a huge drum water heater that I’ve had in every home of my life, we have these small wall-mounted rectangles.

We have a kinda weird half-sunken crawl space on the side of our house where our water heater and HVAC live.

Part of our original impetus was that we’d have “instant” hot water. Which… turns out isn’t really a feature of tankless water heating directly, so, derp. There are some actual advantages though:

Modern features like being “smart” (e.g. connected) and sending you a message when they need repair and such. Another modern feature is that some of them have a “recirculating pump” built into them, and that is actually the feature that buys you the “instant” hot water.

Ours didn’t have the recirculating pump(s) built-in, so we added that separately. And! Wait for it! It doesn’t work that well. Our main shower is as far away from these heaters as you can possibly be: across the house and up a level. I haven’t done anything scientific, but it maybe bought us a minute or two of speed. What took 5 minutes to heat up before now takes 3? Better, but it ain’t instant.

I still feel pretty good about the change though. Not because of any of the standard features though, but because:

Those are important things to me. I like to know if anything goes wrong there is an obvious, established, guaranteed path toward resolution.

Scaffolding as a Good Way to Get Started

Wednesday, August 10th, 2022

I’ve noticed that a lot of my commit messages the last few months, especially on new branches, simply say scaffolding.

I usually mean it in a very general sense. Not necessarily using some kind of framework or CLI scaffolding, like the famous rails generate scaffold or the generic Yeoman generator, but in a general sense. Just thinking things through and creating/updating files to sketch out the work ahead.

I may or may not know exactly how I’m (we’re) going to do what we plan to do in this branch, but I can put some code into place that applies a bit of structure around it, and that feels useful to me.

For example, say the job is to augment an existing API. It’s going to require a variety of work, like altering the schema, writing business logic to fulfill the requests, dealing with permissions, and fiddling with the database and database methods to get/set the data you need. Scaffolding this job means instead of doing all that work up front, you touch all the files you expect will matter in this work. Perhaps you write nearly-empty functions that talk to each other the way you expect they will. Maybe even pass around fake/mocked data. Make sure the types are happy. Make sure the function signatures feel logical. That kind of work should go fairly quickly, and help do the things I mentioned in those two bullet points above.

Once you have that scaffolding in place, you can think out smaller parts and make them work in the whole you’ve already thought out.

This doesn’t even have to be coding work!

You could scaffold writing by jotting down bullet points or a heading structure.

You could scaffold design by drawing some base rectangles or laying out a nested component structure.

If it is coding work, it also doesn’t have to adhere to the scope of a pull request. You could scaffold out a single function if you needed to.

function DoTheThing() {
  // Get the stuff

  // Munge the stuff

  // Conditionally do some things

  // Return the good parts

JavaScript Import Sorting

Tuesday, August 9th, 2022

It’s fascinating how the order of imports doesn’t matter in individual JavaScript files. If you start awaiting them and using their methods for things, then it might matter, but those top-level normal imports at the top of so many JavaScript files… the order is largely irrelevant.


import React from 'react';
import classNames from 'classnames';
import styles from './ThisComponent.module.scss';
import { QueryWhatever } from './ThisComponent.graphql';

Behaves no differently than:

import { QueryWhatever } from './ThisComponent.graphql';
import classNames from 'classnames';
import React from 'react';
import styles from './ThisComponent.module.scss';

I know we’re not exactly looking at vanilla JavaScript with the non-standard file formats, but it holds true in vanilla JavaScript as well. Also, I’m sure there is nuance to the order in which they are evaluated and when code inside them executes and such, but again, for the code below these imports, that code doesn’t care.

That doesn’t-matter-ness can lead to, well, a mess. It’s common that a project-wide convention determines how best to do it. “React always goes at the top, even if it’s not alphabetical with other npm imports”. “Styles are always last”. “Group together or library components”. That kind of thing. But it’s not always enforced. In fact, I really don’t like seeing Pull Requests with diffs that contained re-ordered imports, as it feels like confusing noise. And yet, I was guilty of doing it, because I like having all the files share a common logical-to-me order.

I’ve tried to automate this in the past and have failed. Either I couldn’t get it going right or I didn’t like the control I had over the output, or something. I think I tried the ES Lint version of it, and part of the problem is that I prefer the automation to happen on-file-save. It could also be in a pre-commit hook also, but I don’t want it only there. And if you want it on-file-save, that’s Prettier territory generally. You don’t want two different things in your code editor fighting over which does the formatting.

Fortunately, there is a third-party plugin for Prettier for import sorting: prettier-plugin-sort-imports. Shaw on our team implemented it recently. That’s a two-part process:

  1. Get it working
  2. Run it against the whole code base and commit it using a throw-away Git user

Both turned out to be no big deal.

The fact that it supports RegEx in the configuration for setting up ordering meant we could match our existing conventions (huge!). In our .prettierrc.js file:

  importOrder: [
    'react', // React itself
    '<THIRD_PARTY_MODULES>', // node_modules
    '^(cplibrary|cpicons|cputil|cpclient|@cpclient|cpshots).*$', // Workspace packages
    'components/.*$', // React Components
    '^(constants|data|hooks|util|utils)/.*$', // Various helpers
    '^(\\.|\\.\\.)/(.(?!.(css|scss)))*$', // Any local imports that AREN'T styles.
    '\\.(css|scss)$' // Styles
  importOrderSeparation: true,
  importOrderSortSpecifiers: true,
  importOrderCaseInsensitive: true

Those groupings match how our home-grown conventions evolved.

Works great. No more import sorting commit noise and every single JavaScript file sorts the imports in a standardized way, improving scannability.

How nice is this?


Monday, August 8th, 2022

At first I noticed a yard crew over at Jim’s house cutting his grass and trimming the bushes. That’s weird. Jim always did his own yard work. I know because he’s our neighbor right across the street and he was out there a lot. He lived alone.

I always thought it was impressive because Jim had a serious limp. He always used two arm-attached crutches to move around. It didn’t seem to slow him down much. I don’t know all the exact details, but it was some accident quite a long time ago that resulted in rather big chunks of missing flesh from his leg and butt. He pulled down his pants and showed me right in the street one time.

He also told me that he climbed South Sister one time, post-accident, which is very badass. He drove a big orange Harley around in the warm months. He was always nice to all three of us, remembering all our names and offering little jokes and advice. We talked in the driveway once a month or so. He was always rocking classic rock music in the garage. He put up huge holiday light displays that Ruby loved. I don’t think I’ll do it this year, he said back in November. But then he did.

Still hadn’t seen Jim in a while. The house looked fairly buttoned up. Then one day a big moving box showed up in the driveway and there were people I didn’t recognize milling around. Maybe some new owners? We weren’t exactly tight friends, so it wouldn’t surprise me if he up and moved without telling us his plans. It was a pretty big house for one dude. I was gonna walk over there and talk to them, but I didn’t get around to it. Then a big dumpster showed up right next to it, and the people filled it up. I saw Jim’s truck in the garage at that point, which felt like a very bad sign. Then everything was gone.

Without anyone direct to ask, we texted the other neighbors who had known him longer. They texted Jim to see what’s up, but no response.

Turns out Jim had died, way back in April. We just had no idea.

I learned from the obit that he actually had six kids, but lost one of them as well as his partner before his own death. Pretty rough go, that, so I’m happy he looked like he was making the most out of life right up until the end.

Oh, and I write “Jim” because his actual name was Dennis. Somehow I got it in my mind his name was Jim and I called him fuckin’ Jim right to his face for years and he never said anything. 😬. Sorry buddy. RIP.

We’ve run a software company for 10 years — what have we learned?

Friday, August 5th, 2022

Alex and I teamed up for a CodePen Radio podcast presenting our collaborative advice based on what we’ve experienced so far.


Thursday, August 4th, 2022

It can look pretty but it stinks and sucks to breathe.

It was the first real day of smoke here in Bend yesterday. Mercifully, a bit late in the summer compared to previous years. But it’s still here. Just a fact of life now. The west burns in huge swathes every year and we deal with the carnage and poor air quality. Climate change in real-time. I put in a new air filter for the house last night just in time, good thing we have a huge box of them we ordered during the offseason because we knew this was coming.

I put the Breathable app back on my phone so I can use the widget.

examples of the Breathable widget. Circle of colors (green is good, red is bad) and the current status.

It involves signing up for one or two public data services to get an API key to work, both of which I’m glad exist but have awfully janky UI. My APIs keys from last year expired but I was able to re-create both.

AirNow is one of them and it’s also got an interactive map where we can see the fire locations and where the smoke is going:

map interface showing the Deschutes area. Green dots showing good air and fire icons showing active fires).

Bullet Train

Thursday, August 4th, 2022

Miranda and I went to see Bullet Train the other night. We were both in rather uncharacteristically bad moods, especially for a date night without the kid. This movie really turned things around.

I watched the preview and thought it would be a rather soulless/boring action-for-actions-sake romp. But it wasn’t! It was frickin’ good! Funny, intense, interesting, and clever. Under less skilled hands, it could have turned out a mess, as there was a lot going on. Tough to pull off a complex plot, with twists, with flashbacks, with heavy stylizatiion, with jokes, with heart. It may have had a plot hole or three, but it really came together well. Most importantly, it cheered us up.

One of my favorite parts is when we meet The White Death and it’s Michael Shannon (not a spoiler, as he’s credited with that role). I remember watching Take Shelter and being rather captivated by him in that. Now he’s a darn star with stuff like The Shape of Water and all that. Should have known he was gonna be a star with Groundhog Day being his first role.

They Got Aquired

Wednesday, August 3rd, 2022

I talked to Dana Miranda (from my hometown!) about the sale and she covered it for They Got Acquired.

Coyier wasn’t seeking a buyer before DigitalOcean reached out with its offer in January 2022. But he believes the sale came at just the right time.

“They could run [the blog] with more manpower, and I could re-focus on other things,” Coyier said, explaining why he decided to sell after running the business for so long.

He’d split his time between CSS-Tricks and his other company, CodePen, since starting the latter in 2012.

“I was probably a little overextended before, and CodePen deserves more of my time and attention,” Coyier said. “It has more employees and more investment, and it just needs more focus.”

Actually, the San Francisco Typeface Does Ship as a Variable Font

Tuesday, August 2nd, 2022

I was recently fawning over Apple’s recently Expanded San Francisco Typeface. San Francisco really looks nice in both the compressed and expanded1 versions, across all the weights. So I ended with:

Doesn’t this make perfect sense to construct as a variable font and ship the whole kit and kaboodle that way?

Yes, is the answer to that rhetorical.

I didn’t think we’d actually get it. I think variable fonts are super cool but I get the impression that industry-wide they are considered niche still. Perhaps not something Apple wants to deal with supporting, documenting, versioning, etc.

But just yesterday I randomly stumbled across the fact that the built-in San Francisco font (on the Apple devices that have it built-in) is already variable (!!). See, I was derping around with Roboto Flex, and had system-ui as the fallback font, and I was noticing that during the FOUT, the font-variation-settings I was using had an effect on the fallback font, which renders as San Francisco on my Mac. Which… unless I’m daft… means that San Francisco is a variable font.

Using SF

Assuming you have the prerequisites, this will work:

h1 {
  font-family: system-ui, sans-serif;
    "wght" 900,
    "wdth" 700;

I have access to the weight and width axes here, meaning the same font can do some pretty drastically different things:


On my Monterey Mac, it works across Safari, Chrome, and Firefox, as well as on my iOS 15 iPhone. So decent support where you would expect it.


SF will probably never work on the web on a Windows machine. It will probably never work on the web on an Android device. Unless Apple ships it as a .woff2 for anyone to use, which… I wouldn’t hold your breath. You might be able to extract/convert something from the downloads, but I’d be nervous that breaks some kinda implied license.

If you’re interested in using this on the web, you really need to think about fallbacks. I’d call it progressive enhancement, but it feels weird to call not loading a custom font file the enhancement and loading a custom font file the default behavior. But hey, there is a first time for everything. I haven’t looked into how you would test for support.

Best of luck, if you wanna do something really production-y. Lemme know what you do.


So are "wght" and "wdth" the only axes? Those seem like the most useful ones, but it occurred to me that because I have the fonts “installed”, could find the font files themselves.

Typeface 3

Then drop them right onto the ol’ Wakamai Fondue, the greatest named site on the internet. Somehow, it doesn’t turn up wdth, but it does turn up wght and more:

Additionally, there is at least "opsz" (Optical Size from 17 to 28) and "YAXS" (Some kind of weird horizontal thickness thing?? Changing it looks like 🤮 — from 400 to 1000).

Plus, a boatload of “layout features”:

Those you use in CSS like:

font-feature-settings: "ss01";

That particular one affects how a “69” pair is rendered (nice), and the others I tested worked as well.

Variable font indeed!

1 I love how you can just stretch it manually to make the expanded version.

Bosch 800 Series Refrigerator

Tuesday, August 2nd, 2022

We came home a little cockeyed one night this past winter. My memory has it about midnight, but that probably means it was like 8:45pm. I was ready for bed, but of course, fate was not in our favor that night. There was a weird sound coming from the kitchen. Like a hissing. It took a while to track down, but fortunately, we noticed a bit of water under the fridge, and that was it. The fridge had blown a hose, literally split an old dried-up hose, and was pushing pressurized water through the split making the hiss.

We poked at the problem for a minute, and of course managed to entirely detach the hose making the problem five times worse, as the water was now rather gushing. We knew that like a toilet or a sink, there was probably a shut-off valve. But where? The fridge was literally bolted into place and I’d never had the occasion to learn to move it, so that was out. Maybe that was a known issue so the valve was under the sink? Nope. Under the crawl space weird area where our HVAC and water heater are? Nope, but, that area is close to under the fridge, and that’s where all the water was going. Huge sloppy mess of water. At least it was going down there and not flooding the house.

Our next thought was to shut off the water to the house. The main valve, as it were. But… I also didn’t know where that was. It’s never come up and I’ve never noticed it. So we’re in panic mode now, and I manage to find the phone number to the city’s emergency plumbing hotline, which is totally a thing that exists, and a nice fella talked me through some options, and offered to come out. But at the same time, Miranda had an epiphany that the previous house owners left us a packet of information on the house, and it might be in there. Low and behold, a computer-paper-printout of where the house water value is. Found, turned off, immediate crisis over.

Next day-ish, we get an appliance plumber out to deal with it so we can turn the water back on. There indeed is a water valve behind the fridge, but no way we could have gotten to it whilte in the moment. It essentially required special knowledge and equipment to move the fridge. Anyway, he essentially rips out the water features of the fridge for now, and maybe we’ll reschedule a time to repair all that. But we knew it was time for a new fridge anyway.

Hence, the 800 Bosch Series French Door Bottom Mount Refrigerator. Miranda picked it out. I think it’s pretty classy looking, check out how it’s like partially reflective:

looking at installed fridge at an angle, reflecting the stove to its side
Now we need to put a cabinet thing above it, it’s shorter than the old fridge.

I like the cool middle drink drawer thing:

There is no “front” water/ice thing, which I think gives it a classy look. Instead, the water spigot is inside the fridge, giving off the impression the water is extra cold (to my silly brain). And the ice maker just dumps ice into a drawer in the freezer below. Which I kinda like because it means you can quickly scoop out what you need, not press a button, wait for the weird gurgling noises an ice dispenser normally makes, then half a third of it fall and ground anyway.

It’s also a “smart” fridge, meaning it’s connected to WiFi and doing god knows what. It doesn’t try to tell you that you need milk though, basically, it just shoots you an alert when the door is ajar. That happened today and it saved us from a few hours of an open fridge, so worth it so far.

Touch ID for Desktops?

Monday, August 1st, 2022

Apple sells desktop machines (notably three! Mac Mini, Mac Studio, and Mac Pro), meaning bring-your-own keyboard. If you want to use Touch ID, which is awfully nice UX, you’ve got one choice: Magic Keyboard. I’ll get an RSI flareup in half a day of not using an ergonomic keyboard — so that keyboard is out.

Turns out you can get real hackery if you want to.


I can’t do it though. Looks like a fun project, but I ain’t even got time for that.

I’m wondering if things will change though. Apple is releasing Passkeys and they seem, rightfully, quite proud of it. I’m all about it. It’s not some proprietary Apple thing, it’s Apple getting a jump on emerging standards from the “FIDO Alliance and W3C standards”. It’s a really great system and I’m optimistic it’s what will ultimately kill passwords. But I believe it’s seriously hampered by not having Touch ID available (desktops without an Apple keyboard) or Face ID (any desktop or laptop). So maybe if Apple really wants to push this tech (yes please), let’s see a dedicated Touch ID device and/or Face ID come to webcams.


Friday, July 29th, 2022

I got them in white.

KEF LEX II are a pair of bookshelf-sized speakers that I recently bought. Spendy! But nice.

I’ll get to them, but I’m long winded so I gotta do a bunch of blogwords first to set the scene.

I moved to the Mac Studio not long ago. I love it. It’s a great machine. Feels very weird to have gone to a desktop machine, after (counts fingers) all those years. Seems like it is all but assumed developers work from laptops these days. But I was ready. A desktop means to me that I can come to work, sit down, and have a machine 100% ready to go. No plugging anything in whatsoever. Everything is exactly as I left it. I already had a nice monitor that permanently sits on my work desk, after all.

Plus I can commute back and forth to work, usually on a bike, carrying nothing but what fits in my pockets: keys, wallet, and phone.

I still have my “main” Macbook Pro laptop, I still have it at home for computering and for travel. If I had to choose only one, I’d have to choose the laptop.

The Mac Studio has quite a few ports:

That’s a generous amount of ports, coming from a laptop.

So many that I no longer needed my (beloved) CalDigit TS3 Plus Dock. It was almost the perfect amount of ports.

That’s just the back too, there are two more USB-C’s and a SD card slot on the front. Jeez.

Notice no speakers.

I briefly mentioned recently that I was using Apple HomePod Mini’s for computer speakers. I liked the idea at first! You can “pair” two of them for proper stereo sound and connect them as a proper pair. My favorite part is that I could put them anywhere I pleased and there needn’t be any cable directly to the computer. And I could select them like any other speakers, even name them how I liked.

But alas it was just a dream. Two annoying problems:

  1. There was a big delay in selecting them. They never seemed to stay the default speakers. Extra weird on a desktop machine that never moves, right? Re-selecting them would take sometimes 30-seconds to several minutes to connect, and sometimes outright fail. Not tenable.
  2. Even when they are connected, pausing and re-starting sound had a 2-3 second delay. Just a bad feeling to that.

So I got back to desiring a regular set of plugged in speakers.

The Mac Studio does have a little speaker in it, but it is hilariously bad. I actually have a couple of sets of Audioengine A2’s that I very love and considered using here. I’ve used them for various things over the years, including stints as computer speakers. This would have been particularly easy here because of the Aux jack — no dongle or anything needed.

But, as a completely bougie bastard who often makes his desk is 17th hobby, I really didn’t wanna use Aux. If you plug anything into Aux, the sound menu in the main menu bar of macOS will say “External Headphones” instead of “Mac Studio Speakers”. I’m afraid, in my vanity, I could not allow my desktop speakers to be named “headphones”.

So that’s what lead me to the KEF LSX II‘s. Not only are the lovely looking and work well size-wise on my desk, but I watched some pretty glowing reviews. I believe one of the distinguishing features of the model II’s is that it offers USB-C connection, which is exactly what I was looking for. Not a ton of speakers have USB-C ports, in my searching around. By using USB-C…

I think I might have a port fetish.

They also have a million other features I’ll probably never use. Bluetooth of course (ughk), but they’ll take Aux too in case it comes to that, HDMI, Optical, and even Ethernet (not sure how that works).

But the features sprawl from there, including having an iOS app through which you “stream” music to it from the likes of TIDAL, Spotify, and Amazon Music. That’s a big yawn from me. I very much do not want to open your weird little app in order to use my main music service. I’d better be able to connect to the speaker via from the main music service app (which of course you can).

I had a few hiccups worth documenting:

All in all, I’m pretty stoked to welcome them to Team Chris’ Work Desk:

« Older Entries