There’s this annoying tension between personal and public that comes with personal websites. Are they a home or a gallery? a personal record or a public document?

On the one hand, it feels like it would be fun to have a massive index of everything you’ve done, thought, or written about, all in one place. On the other, this makes it harder for people to find the bits that might be worth reading.

Equally tempting is the idea of perfectly designed templates for each section of your site. I have accepted that I will never do it as well as Aaron, and it’s allowed me to be at peace with tasteful minimalism instead.


Despite the rumors, I do indeed have a few.


This site is fast. Ridiculously fast, even for a static site.

It uses one web font, and only on non-Apple devices. There is just one 800-line stylesheet. There is no JS-based rendering. This page weighs less than 15kb. Images are compressed to within an inch of legibility, and Netlify’s CDN ensures a low time-to-first-byte. I also have an script running to make cross-page navigation even faster.

Everything is a static asset, everything is cached locally. Yes, even the HTML, it just has a refresh period of one hour. The result is a website that crushes all the important speed metrics, and is a comfortable member of the 250KB club.


This site is perfectly readable on a variety of viewport widths. It is perfectly readable without any CSS. It is perfectly readable without any Javascript. It acknowledges the pace layers of the web. It uses semantic HTML for almost* all it’s elements.

* Except sidenotes, because there isn’t a native tag for that yet.


If you aren’t already, you should seriously consider using a static site, built on a foundation of Markdown and Git. It frees you from being reliant on a private company to keep your site alive, and you can switch hosting with ease. It lets your site degrade gracefully.

You’re also free to pick how you want to build your site, instead of being limited to one default method (JS Handlebars for Ghost sites, PHP for Wordpress, etc). I use Hugo because it lets me write my templates in plain HTML, and has lots of useful pre-defined functions.

The fewer special styles and element names I have to remember, the better. The stylesheet for the site is three times smaller than the last version of this site, and I use a grand total of two special elements, sidenotes and masonry-style blocks. No shortcodes, no MDX, no Tailwind.

The important consequence of this minimalism is that writing a new post is simple as opening up a new markdown file, adding a title to the front-matter, and starting to type.


It’s 2023, and web hosting has never been cheaper. Other than the $10/year that I pay for the domain, it costs me nothing to put this website online. I don’t need to rent a server to host pure static files, and Github provides free storage.

GithubHosting and version control
NetlifyDeployment and CDN provider
Google DomainsDomain provider with the most transparent pricing, and excellent UX.
PorkbunMoved my domains here ever since Google announced that they’re selling to Squarespace

The site itself is generated with Hugo, which I like because it’s really fast and provides a bunch of of sensible defaults that frees me from having to fiddle with plugins.


Why purple? Because Frank Chimero said it was hard to make purple work in a design and I couldn’t resist the challenge. Also because I got bored of black and white, so #2F2182 is what we’re going with.

In style and spirit, this site takes after One theme color, an index on the homepage, simple styling for common elements, and fairly wide variety of writing.

I love weird personal sites and near-unreadable layouts. I’ve even designed some myself. But for better or worse, this version of my site seems to have unconsciously adopted the brutalism code of practice.

Brutalist Web Design

If you’re a web designer or front-end developer, I will help save you from yourself. To help you put fancy to one side. I am going to offer you a brutalism code of practice:

  1. Don’t be influenced by tools
  2. Use a system font and only one
  3. Write clean code
  4. Write your own CSS
  5. Don’t use Javascript (if you can avoid it)
  6. Don’t hack the scrollbar
  7. Don’t create custom cursors
  8. Don’t use an effect just because you can (especially fade effects)
  9. Have as little design as possible
  10. Make navigation obvious or not at all
  11. Be practical rather than pretty
  12. Don’t use gradients or shadows
  13. Use high contrast colours
Carl Barenbrug

I might change my mind eventually, but for now this simple set-up suits me well. It means I’m actually writing words on here instead of endless fiddling with stylesheet files. The layout also translates well between mobile and desktop, which is the part I usually find most frustrating.

Why isn't there a dark mode? Because you probably shouldn't be reading in the dark, you should be asleep instead.


My typography notes contain the rules that I use for arranging the text you’re reading right now. I chose box-shadows over borders, and have only one stylesheet across all pages.

On iOS/MacOS, this site uses Avenir, a delightfully crisp font that ships with all Apple devices. For body text, I use Mulish, on of the best sans fonts I’ve found.

Unfortunately, it had no true small-caps variant. Instead, headings use Montserrat. Both fonts, have been converted to WOFF2 and subsetted down to mere 19KB and 35KB respectively. Font-smoothing is set to sublixel-antialiased on Webkit browsers.


I’ve attempted to arrange content with the minimum amount of scaffolding. And my rule of sticking to semantic HTML means that I try to as much mileage as possible out of simple elements like headings and blockquotes, instead of complicated <div> tags and classes. Even elements like the expandable sections are just regular <details> elements with a little extra styling.


There are still multiple ways to implement sidenotes on the web (Gwern has a whole list) and this JS-free solution is particularly neat, but is limited to inline elements. Great for text, not so nice for images and multiple paragraphs.

Mine are just absolute positioned <aside> elements. I respect the desire to have them exist on all screen sizes; but sidenotes are, by definition, not an essential part of the main content. And so, I’m fine with them being invisible on mobile as long as they can contain anything I want them to.

Table of Contents

Hugo does come with it’s own function for creating a ToC, but it was based on directly turning the contents of header tags into the text in the table. This meant that headers that had link tags within them would render two <a> tags within them; one to the in-page header, and another to an external page.

So, instead, I use a modified version of this snippet to generate the ToC. Like sidenotes, the table is only visible on desktop screens.


The double column sections use column-count: 2 and provide just the right amount of density to my lists.

There are many fun ways to use <footer> elements on the web. You could add a changing quote, or a ticking clock. I chose to write short sentences instead of singe-word links.


There are three only pieces of Javascript on this site.

The first one is responsible for showing you a fullscreen view for images when you click on them. Second is the code from, which begins loading a page in the background whenever you hover over a link to it.

More about

It uses connection.effectiveType to check what internet speed the user's device is running at, and avoids fetching anything if it's on data saving mode, or on a 2G network. It also has a configuration for mobile that loads links as they scroll into view, instead of fetching them on hover/click (this is similar to what quicklinks does).

It's one of the many things you can do to get SPA-like performance on a regular site. I use an inlined version of the code to avoid the need for an additional fetch reqeust.

The third bit is the JS-powered search function present on every page, accessible through CMD + K or CMD + /, two-finger tap on mobile, or just visiting the Search page.

None of these snippets are essential to the core experience of browsing this site. Even the Search page contains a complete index of all the site’s pages and tags.


Basic stats are collected by Umami, an open-source, self-hosted analytics platform. Hosting fits comfortably into the free tiers on Netlify and Supabase.

It seems like every site that mentions the existence of an analytics script does so with an overly-apologetic “I don’t actually care about numbers, I just have this for such-and-such completely benign reasons”. It’s your site dude, you don’t need to feel guilty about it.

As for my own numbers, I rarely check them, but it’s nice to have some idea of how people use this site. It helps me figure out what pages should make it into the “popular” section, and if an incomplete page is getting enough visits for me to bump it up my to-do list.