I usually try to avoid navel-gazing too much, but a few folks have asked me how this blog is built and maintained. This also would be a good time to talk about the why.

This blog post covers the Principles, Technology, and Process behind this blog.


I apply three principles to decisions around how this blog is built and maintained.

  1. Make reading posts a great experience.
  2. Make writing posts frictionless.
  3. Don’t sharecrop.

Let’s dive into each briefly before getting to the technical setup. Without the above, it will be difficult to discuss the technical setup.

1. Make reading posts a great experience

Many sites looking to turn a profit need to extract something from the user. They need some impressions on ads or signups to a newsletter. Thankfully, this blog does not need to turn a profit.

As such, the experience can be kept pure. Ads aren’t required and getting signups on the newsletter is a nice-to-have but not a requirement.

To make the experience of reading great, I try to use as few technologies possible. The writing should speak for itself.

2. Make writing posts frictionless

It’s hard enough to keep a regular cadence of writing. Writing is much like product development: you can guess what might be popular, but you’ll never really know. As you write more, you develop a better muscle. Still, you can’t predict the future.

It’s for this reason that I keep writing posts as frictionless as possible. Writing is one of those things where biasing toward more quantity can also improve the quality.

3. Don’t sharecrop

This blog used to be on Tumblr. Before that, it might have been on Blogspot or Blogger. Today, it could be on Medium.

I’ve gotten to the point where I don’t write on these other platforms. It’s not that they aren’t nice, it’s that they often conflict with the above 2 principles. Things usually start out well enough, but those companies have a business to run. Many times, the needs of their business run counter to my interests.

I’ve recently begun cross-publishing a few posts on Medium, but other platforms are never the home for posts.


Alright, enough of the hand-wavy. Let’s get down to it. This blog uses the following technology:

All of this technology tied together keeps the site snappy. Google Analytics reports an average page load time of 2.67 seconds with an average page download time of 0.04 seconds. That average page load time skews high, it’s 1.28 seconds in the US.

Some unscientific hand-testing at home shows the initial HTML document loaded in 20ms, DOMContentLoaded events around 150ms, and Load events at 300ms. I view speed as a crucial part of the experience.


I find Markdown the most ergonomic for me. Sometimes I’ll drop into HTML to accomplish something, usually around images and adding captions.


Jekyll is a Ruby-based static site generator. It gives you some of the convenience of other CMS systems (reusable partials and layours) while providing a bare bondes simplicity. Not many things are faster than serving flat files.

For how I have Jekyll configured, please take a look at the Boilerplate section below.

Amazon S3

Amazon S3 is the workhorse of the web. Because Jekyll crunches your site into static files, they just need a place to live with no extra logic. S3 works well for that, but so could any other blob storage system.


s3_website is a simple Ruby gem used for publishing static files to Amazon S3 in a simple fashion. It takes care of the create vs. write vs. delete of objects in buckets.

Amazon Cloudfront

While S3 is the workhorse, it’s not particularly designed for speed. Amazon Cloudfront is the “good enough” CDN for this site. It works well with S3 and provides some nice things like automatic certificate rotation for making HTTPS easy to maintain and now also has limited HTTP/2 support.

As a footnote, I’m also using Route 53 for DNS.

Google Fonts

My design eye often needs some work. For this blog I use Montserrat for headlines and Crimson Text for body text. Both of these are served from Google Fonts.

If you have any suggested tweaks or have a better font pairing in mind, please let me know.


I use imgix for making sure the images are the best size for the device they are being served to. This is done by using srcset and sizes attributes for each image I embed on the blog. I wrote about the approach in the post Boiling the Ocean with Markup.

Any diagrams I create are usually done with OmniGraffle. Diagrams are exported at a high resolution and then crunched down as necessary by imgix.


I used to use Tinyletter, but now I use Buttondown. The experience is much better.


Now for the things that tie all of this together. I’ve got 2 scripts that help me to write and publish: bin/serve and bin/deploy. These are simple shell scripts that help me not remember the Jekyll incantations required to do what I want to do.

I’ve modified the stock Jekyll layouts a bit to handle drafting functionality. Blog posts are better when they’ve been read by a few people first, so drafting is a core part of my workflow.

imgix doesn’t quite have everything I needed in their jekyll-imgix so I’ve forked it.

If you want to see all of this in action, please take a look at the GitHub repo.


I keep a running list of potential blog posts that I want to write in Apple Reminders. The list is sorted and reordered depending on how I’m feeling, how past posts perform, and what the current weather is. The list currently has 23 potential posts.

Generally, the process of writing a post is the following:

  1. Pull off a post from the backlog.
  2. Write a draft of the post.
  3. Take an editing pass at the post.
  4. Circulate the draft for feedback by soft publishing the post. (You can only get to the draft with a URL, it’s not listed on the front page.)
  5. Collect and incorporate feedback.
  6. Publish the post.
  7. Mention the post on Twitter. Maybe also LinkedIn and Facebook depending on the content.
  8. Send out a newsletter mentioning the post

All in, each post takes somewhere between 4-8 hours of work to move through this process. The process is spread out over a few days or weeks.

As with any creative endeavor, there are false starts. Just because something makes it to a certain step doesn’t guarantee the following steps will occur.


Hopefully this is useful for you as you write your own blog. I’m happy to answer questions about this set up on Twitter or via email.

Again, check out the GitHub repo if you want to see how this is set up from a technical perspective.

Special thanks to Asia Hoe, Edward Bramanti, Justin Duke, Iheanyi Ekechukwu for providing feedback on early drafts of this post.