dth by Joshua Wood

This blog is a web page

JAM Stack is so hot right now. :fire: Like many others, I’m exploring frameworks like Gatsby, Next.js, and Nuxt.js, but not on this blog. My goal for this blog is to get JAM stack performance without the JAM stack.

Instead of Gatsby or Next.js, I’m using a Ruby static site generator (Jekyll) with HTML, CSS, and minimal JavaScript for progressive enhancement. My litmus test for this blog is that you can still comfortably read it if you disable JavaScript1. With JavaScript enabled, this blog should feel very close to a single page app.

Here’s the stack:

  • Jekyll
    • Generates static pages
  • Webpack w/ PurgeCSS
    • Bundles both CSS and JavaScript
  • Turbolinks
  • Font Awesome
    • I’m considering ditching this because it’s a lot of overhead just for the handful of icons I use.
    • Currently using the SVG kit, which remotely loads the individual icons (so not bad performance)
      • This is still dependent on JavaScript which I’m OK with, except there is a flicker on initial page load.
    • Ideally I would like to include a subset of icons via CSS or direct SVGs.
      • Is there an easy way to include a subset of icons via CSS?
        • css.gg has this, but doesn’t have the brand icons I want
        • Fontello doesn’t support Font Awesome 5 (and is missing a few icons I use)
  • Netlify
    • Web host
  • OpenGraph image generation API deployed as Netlify function
  1. Idea: add an option to disable all JavaScript.

Why I don't pick stocks

For the past 12 years, I’ve been preparing myself for the next big downturn. With the markets falling to pieces over the past month, that event may finally be here–the lasting economic impact of COVID-19 will be heavy.

Meanwhile, my automated investment plan has been doing its thing. While it has been nerve-racking to watch my account balances plummet, I appreciate the test of resolve.

As short-term investors have dumped stocks in recent weeks, I’ve been feeling increased pressure to take greater advantage of the resulting discounts. At one point, I even had a basket of companies that I was considering buying directly over the next few months.

That’s when Daniel Kahneman slapped me back to reality, via Jason Zweig:

Years ago, the psychologist Daniel Kahneman told me that one of the keys to investing is having what he called “a well-calibrated sense of your future regret.”

Jeff Bezos has a similar approach to making big decisions, which he calls a regret minimization framework.

After checking the stock quotes for the Nth time on Friday morning, I decided to apply a regret minimization framework to stock picking:

  1. I will never risk enough in individual stocks or even ETFs to make any real money in them. I’m too risk-averse. That means that:
  2. If I do buy stocks, it will be a small amount, for fun.
  3. If those small investments do exceptionally well, I’ll probably regret not irrationally putting more into them.
  4. I don’t want to regret acting rationally. If I don’t buy individual stocks at all, there will be nothing to regret.

Immediately, a huge weight lifted. I don’t speculate, not even for fun. Picking stocks is an unproductive distraction, and I’d rather spend my time on other things.

In the next hour, the market jumped 10%, and my discarded basket of stock picks did pretty well. I don’t regret not buying them.

F*ck-that money

This post originally appeared on the Honeybadger Developer Blog

I’ve met some hugely successful people. Some of them are happy. Some of them… aren’t. I’ve noticed some things about the ones who aren’t:

  • They’re obsessed with their careers
  • They spend a lot of time at work
  • They aren’t fulfilled by the work they do
  • They aren’t content with what they have

In many circles, these people are way more successful than most of us. They probably have better networks. They might have fancier job titles. They certainly make more money.

The Silicon Valley meme goes, “start a company and sell it for so much money that you can say ‘f*ck you’ to anyone in the world.” Or maybe an alternate career path is to climb the corporate ladder at Google until you’ve banked that privilege.

So much toxic bullshit stems from that line of thinking.

I’d rather have f*ck-that money—e.g., a moderate amount of money that empowers you to live a meaningful life. F*ck-that money isn’t about being a pretentious asshole; it’s about keeping your priorities straight. For example:

  • Miss your kid’s soccer practice to catch up on emails? F*ck that!
  • Power through lunch? F*ck that!
  • Skip the gym? F*ck that!
  • Work over the weekend? F*ck that!
  • Save that side project for when you have more free time? F*ck that!
  • You get the idea…

At Honeybadger, this mindset has led us to turn down acquisition offers and investors—to stay small and grow naturally. We’re not in this business to be rich; we’re in it to be free.

Regret the best years of our lives?

Fuck that.

Cold Showers

Next time you rinse off, do this:

Standing right under the showerhead, gradually increase the hot water. When you can’t handle it anymore, turn the temperature all the way to cold (and brace yourself). Wait to stop hyperventilating before turning the water off.

Do this every day. Not only is it refreshing, but it’s also a daily reminder that for many things, getting past the initial resistance is the hardest part. 🚿

Bribe your customers (they'll love you)

At Honeybadger, we’ve found that when paired with the right offer and some self-aware humor, playful bribery can be a fun and rewarding way to nudge your customers in the direction you’d like in the buying process.

One such example is such a hit that it’s now a regular source of paid conversions: 10% of qualified trial users who get this email add their credit card before their trial ends. Let’s walk through it.

After you set up your first project in Honeybadger (which tells me you’re serious), you’ll receive an email:

Inside, I’ll introduce you to our favorite gift: an exquisitely designed super-badger tearing through the chest of an expensive tri-blend tee.

Modeled by an enthusiastic customer showing off the shirt I sent them on Twitter, it’s the kind of garment you’d spend your own money on.

“S/O to the guys at @honeybadgerapp for hooking me up with the dopest shirt I have ever had⚡️”

Midway through the email, I’ll make you an offer: if you’re enjoying your Honeybadger trial so far, would you enter your credit card early? When you do, I’ll send you a shirt of your own–for free.

I’m super excited you signed up for Honeybadger and reported your first error. I’m trying out this thing where I send new trial users some swag (our famous “Ship It!” t-tshirt–featuring a badass Honeybadger, and some stickers) when they enter their payment information early, and you’ve been selected!

If you enter your payment info now, we won’t charge you until the end of your trial, and you can cancel any time before then. The only difference is that you’ll have an awesome, one-of-a-kind t-shirt to wear while you decide if Honeybadger is right for you. :)

What do you think?


PS: Reply to this email after you enter your payment info and I’ll send you a link to choose your size and shipping address.

Would you take me up on that?
(Of course, if you sign up for Honeybadger, you really can… ;))

Entering your credit card is a critical step in the buying process. If you do nothing by the end of your trial, you become a customer–a choice you made in a quality exchange that added some whimsy to your week.

The offer must be something people want, which means spending money–this won’t work for everyone.

That said, if your customer lifetime value is high enough, consider bribing your customers. It’s worth it, they love it, and it’s just good fun.

Drive the speed limit

I have always had a bad temper. It’s how I’m wired. I’ve learned to control it in many situations, but sometimes my anger blinds me, making it difficult to reason.

One thing that gets me is unfairness; especially when someone asserts themselves at the expense of others. I’m often blindsided by this while driving.

When some people get behind the wheel, they change. They merge with the machine. They try to dominate the other vehicles. That used to be me.

Someone would tail me; I’d brake hard. Someone would pass too close; I’d edge them out. When I’d see a car being abusive to someone else, I’d chase them down just to give them the finger.

One day, after a particularly heated incident, I resolved not to be that kind of driver anymore. I decided to reinterpret my relationship with the road.

When you make a “snap judgment,” what you’re really doing is interpreting the situation using mental patterns that you’ve previously stored in memory. When you have an interpretation that fits with experience, you respond accordingly.

Reinterpretation is a mental trick that helps you change your interpretations of the past—essentially rewriting memories. It works because of the way the brain works. In The Personal MBA, author Josh Kaufman explains:

Reinterpretation is possible because your memory is fundamentally impermanent. Our memories aren’t like computer disks-every time we recall a memory, it doesn’t simply re-save to the same location in the same state. Every time we recall something, the memory is saved in a different location with a twist: the new memory will include any alterations we’ve made to it.

It’s possible to change your beliefs and mental simulations consciously by recalling and actively reinterpreting past events. (p. 206)

To reinterpret the kind of driver I am, I needed a new story to tell myself. Before the change, I was a crusader out for citizen-justice, enforcing my view of “how things should be.” Break a rule of the road? Feel my wrath. You will not push me–or anyone else–around.

My new story is this: I used to be a hothead, but now I drive the speed limit.

Driving the speed limit lets me cruise in the slow lane. When someone tails me, I move over. When someone cuts me off, instead of chasing them, I shrug: I can’t catch them anyway–they’re speeding. There are fewer hotheads in the slow lane.

Reinterpreting the kind of driver I am helps me keep calm when I’d otherwise lose my temper.

I used to be a hothead, but now I drive the speed limit.

In case you noticed I'm no longer on social media

The first rule of quitting social media is not to talk about quitting social media, at least not for 30 days. :)

That said, know that I didn’t leave because of you. I plan to continue the relationships I’ve made online, hopefully, more substantively. If you’d like to catch up, talk shop, ask questions–whatever, I’d love to hear from you: josh@joshuawood.net.

If you still want to follow what I’m up to:

See you around!


Don't let modern be the enemy of good

The new generation of JavaScript developers calls what they do “modern JS”. As an old guy, that got me thinking about the difference between my front-end worldview and theirs.

In my experience, front-end development is a battle of competing standards and compatibility across platforms. Remember developing for IE 6? I do. “I’ve seen some things, man…” [eye twitches]

Browsers are good at rendering HTML, and servers are good at generating HTML; doing things client-side—while often necessary—was tedious and brittle at best.

Things are arguably better now, but client-side still comes with a cost. Fully embracing modern JS (in the form of a static single-page app) usually means rejecting the traditional paradigm.

Given the complexities of modern development in general, it still seems silly to move everything client-side just for the hell of it when there are well-established standards and patterns to build on.

“You can’t build a lot of apps without modern JS.” That’s true, but there are many types of apps, and in my experience, good development is all about managing complexity.

“Single-page apps perform better than traditional web apps.” OK, but at what cost?

When I look at the tooling that is necessary to reap all the benefits of “modern JS”, I really begin to wonder why you would subject yourself to that if you’re not building a Slack or a Notion.

The DHH/Basecamp/Rails full-stack approach still makes sense for a lot of people. Laravel and Phoenix are great too. As a small team, skipping hype cycles and shipping is one of the best things we’ve done at Honeybadger.

What about devs who haven’t spent 20+ years battling JS in the browser? To them, JS has always been cross-platform, it’s always been in a state of constant improvement, and “everyone does it this way.”

I think it’s great that JS has come so far. For the first time in my career I actually enjoy working with JavaScript, thanks to the hard work of everyone who has invested in it.

The simplest solution is usually best, and if everyone’s first and only choice is to build a “modern JS” app, we’re all maintaining a lot of needless complexity. Use modern JS; just do the math first, and use what you can afford.

Don’t let modern be the enemy of good. The End. </👴>

Wrapping Up ElixirConf 2018

This post originally appeared on the Honeybadger Developer Blog

I’m on the 6:10pm Amtrak Cascades out of Seattle, scheduled to arrive in Portland at 10:00pm. After two intense days in Bellevue, I’m exhausted, but wired. A group of young guys two rows up are loudly discussing their favorite AWS services; I wonder if they’re also returning from ElixirConf, but then I remember that this is Seattle—half the city works in tech.

An older guy across the isle from them has his feet propped up on the unoccupied reverse seat in front of him. He’s wearing slip-ons, crew socks, Levi’s, and a striped polo shirt. He eventually strikes up a conversation with the kids (who work at Amazon), and I eavesdrop that he’s with Microsoft. Half the city works in tech. He says he works on “a big hardware team”, but conspicuously won’t say which one.

This was my 3rd ElixirConf. I remember how striking the growth in attendance was between 2015 in Austin and 2017 in Bellevue—the conference seemed to double in size (I skipped 2016 due to becoming a parent). This year felt more established, with good attendance, but not noticeably larger (excluding the addition of Aaron Patterson). Maybe it’s just that everything felt familiar being in Bellevue for a second year.

The general vibe I got this year was that Elixir is stable, and investing in the long-term. DockYard announced some ambitious 5 to 10-year goals of running BEAM on WebAssembly, and getting Elixir into the top 10 most popular programming languages in the world. Boyd Multerer (speaking of secretive Microsoft guys) released the library that he’s been quietly building for the past several years—a client application framework for embedded and IoT devices, called Scenic (it’s truly impressive). Chris McCord announced Phoenix.LiveView, a way to develop rich client-side applications without JavaScript.

Deploying Elixir is still the topic of the day, but the discussion is maturing. According to Jose Valim, Releases in Distillery 2.0 (recently released) are still the best way to deploy Elixir today, and they will eventually include a trimmed-down version of releases in Elixir itself. Some Elixir-focused PaaS offerings are also beginning to appear (I heard a lot about Gigalixer). In his talk, “Docker and OTP: Friends or Foes?”, Daniel Azuma showed us how it’s possible to blend the good parts of OTP and Cloud Native to reap the benefits of stateful processes and distributed OTP applications on Docker/Kubernetes.

Daniel’s talk felt really important to me; he pointed out that Elixir is split over ideology of deploying OTP applications. Purists want to squeeze every last drop of performance out of their hardware, which naturally resists virtualization. On the other hand, the industry at large is currently diving into containers (the Google results for that phrase are funny), which are built on multiple layers of virtualization. His call to action was rather than embracing one at the expense of the other, let’s work together to create tooling which is new and unique.

There’s still a lot of work to be done, but as my friend Derrick recently wrote on Twitter, the future of Elixir is bright. ElixirConf 2019 will be in Aurora, CO. See you there!


I’ve been hanging out on Mastodon lately. Mastodon is kind of like Twitter, but without the politicians, the outrage (🤞), or the algorithms. It’s also open source and decentralized, meaning that one person or company doesn’t control it. Instead, Mastodon is made up of many different servers (called “instances”) which are managed by different people; this is sometimes called the “Fediverse”.

Since anyone can create their own Mastodon instance, there are many different instances to choose from. Many people join a general-purpose instance such as mastodon.social or mastodon.xyz. Others join one or more topical instances, such as ruby.social (an instance for Ruby developers!). There’s a full instance list here.

Oh yeah, and carrying on the whole proboscidea theme, instead of “tweets”, status updates on Mastodon are called “toots” (yeah it’s cutesy, deal with it).

Mastodon for Developers

If you’re a developer, check out Mastodon’s source code: it’s open source and built with Ruby on Rails and Sidekiq (with React front-end).

Mastodon is an implementation of a new web protocol called ActivityPub (which is itself inspired by an older protocol called OStatus). The W3C Recommendation for ActivityPub is here (read it—it’s super interesting to learn how federation works).

If you’re into Elixir, there is also an ActivityPub implementation built in Elixir and Phoenix; it’s called Plemora.

In fact, since ActivityPub is an open standard, there can be many implementations. Keep up to date with the ecosystem that is developing around ActivityPub here.

Recommended follows: @cwebber@octodon.social (one of the co-editors of ActivityPub), @Gargron@mastodon.social (the creator of Mastodon).

Mastodon for Ruby Developers

Imagine a place where people politely discuss — yeah, that rules reddit out — nothing but Ruby all day. James Adam runs ruby.social, a Mastodon instance and community for Ruby developers. If you’re interested in Ruby, I highly recommend joining.

I had some fun giving out around 75 Honeybadger t-shirts to promote the instance when it first launched.

OSS Contributions

My first pull request to Mastodon was merged in November 2017! I added a keyboard shortcut legend, which in the web interface you can check out by typing ?.

Additional Reading