CSS Dark Mode

MacOS Mojave introduced Dark Mode, which allows MacOS users to enable a darker interface. According to Apple:

In Dark Mode, the system adopts a darker color palette for all windows, views, menus, and controls. The system also uses more vibrancy to make foreground content stand out against the darker backgrounds.

In Safari Technology Preview 68, they’ve also added support for websites to add support for Dark Mode with a new media query:

@media (prefers-color-scheme: dark)

I’ve added support to my theme, which now looks like this in the latest Safari Technology Preview if you’ve got Dark Mode enabled:

Core Data & Concurrency

It’s been a while since I last worked on any mobile apps, so I thought the last couple weeks of sabbatical would be a good time to get caught up on iOS and specifically to learn Swift, which didn’t exist last time ?. For the most part, it was pretty easy to pick up and I was able to move fairly quickly on some apps I had been thinking about.

One of the only problems I ran into was related to Core Data concurrency. Specifically, if two different threads are reading and writing data, you get errors like 'NSGenericException', reason: Collection <__NSArrayM: 0x7fabb400> was mutated while being enumerated.

The solution is private queue contexts. I won’t do a full explanation of queue contexts here, but the Apple Developer Documentation has some good information. The idea is to create a private context to operate on while we’re doing background work.

For this to work as expected there are a few things that need to happen:

  1. Set context.parent. In order for the changes to eventually be written to disk, we have to associate the new, private context with the main context by setting newContext.parent = oldContext.
  2. Use context.object(with: objectID) to make core data relationships. We need to get a reference in the current context to any objects that were created outside the context.
  3. After saving, we also need to save the parent context to commit the changes to disk. To make it thread safe, we use oldContext.perform or oldContext.performAndWait depending on whether is should be asynchronous or not.

I put together a gist to demonstrate:

The following articles were especially helpful to understand how to fix this problem in my case:

  1. Apple’s Core Data Programming Guide > Concurrency
  2. Core Data Concurrency & Maintaining a Silky Smooth UI


This summer I took a sabbatical that included five weeks in Europe. We stayed in 10 cities in 8 countries and took some day trips that pushed the total number of cities to 12 or 13. Needless to say, it was a lot of travel. I don’t know if I would do something quite like it again, but would absolute recommend it if you have the chance.

I didn’t bring a laptop and basically just had my phone, camera, a few books, and my clothes. Here are some of the photos. 


I’ve been running Pi-hole, the “black hole for Internet advertisements” for a while now. It started out as an excuse to get a Raspberry Pi, but I consider this a somewhat important security appliance now. One of the nice things about Pi-hole is, like Ghostery, it’s easy to see what’s being blocked. Unlike Ghostery, though, it works for the entire network. So things like the Xbox and smart TV are included. For example, I noticed that TCL TVs track what you’re watching even if you “Limit ad tracking”.

I also run Unbound on the Raspberry Pi, which forwards to Cloudflare and OpenDNS over an encrypted connection. The Docker configuration I use for Unbound is on Github.

5 Years

This week is five years since I started working at Automattic. In some ways, it doesn’t seem like it could possibly be that long. We’re growing fast — over 80% of the company started after me. At the same time, my job has changed a lot and when I think of everything I’ve worked on, I don’t know how it all fits into five years.

500 Automatticians at the 2017 Grand Meetup

In a few weeks I leave for a three month, paid sabbatical — a perk everyone is eligible for after five years. I’ve been getting advice from colleagues. Unplug. Take time for yourself. Travel. I’m excited for the opportunity.

People are often surprised to hear that I’ve worked at the same company for this long. Apparently five years is a long time in tech. Or maybe it’s because I’m a millennial. Regardless, they usually want to know why I’ve stayed for so long. The sabbatical is a big, exciting thing to talk about, but the day-to-day flexibility is the real reason. We have an open vacation policy, I get to set my own hours, and I can work from anywhere with an internet connection. The list goes on. This can be an adjustment for most people — especially not having a central office to work in, but after you’re used to it, the alternative sounds worse.

Lots of people tell me they’ve tried working “remote” and they don’t understand how I do it — or how we run a company of over 700 people this way. I’ve learned this usually means they’ve had an opportunity to work from home a few days a week. It sounds like the same thing, but it’s fundamentally different from what Automattic does. The main difference is communication. If you work in an office, you’re naturally worried about missing out on what’s happening in the office. As a fully distributed company, communication is all online and there are no office meetings that you never hear about. We have a saying, “P2 or it didn’t happen”, which means if you don’t post notes to an internal blog, you can’t expect anybody to know about it. And everyone does because it’s the primary way we communicate.

I’m excited to take a break and unplug, but I’m equally excited to come back this fall because things are moving fast around here and there are some exciting changes ahead.

If you’re interested, we’re hiring at Automattic and on VIP 🙂