My website, the one you're reading now, is statically generated using Metalsmith, hosted on Netlify, with all its source code and content living in a private git repo on Bitbucket. I don't track page views or user behavior at all, and I think my site plays well with screen readers (or at least it looks okay in lynx).

I've tried some alternatives, and this setup works best for me. It took some setting up at first, but I don't have to worry about server uptime, maintenance, or even for paying for a hosting provider (Netlify is free). My site is automatically built and deployed every time a commit is pushed to my master branch, and writing in Markdown has become second-nature to me.

I've been asked a few times about how my site is built, so I thought I'd give a primer on how I've been doing it.

I manage my site's content with Metalsmith and git.

I set up a starter repo to illustrate what the structure of my website's code and content looks like: https://github.com/ryannjohnson/metalsmith-nunjucks-starter.

All my writing is in Markdown files in the src/ directory. When I want to publish a new article like this one, I go into the terminal and type:

$ vim src/writing/2019-11-02-how-my-personal-website-is-built.md

I write everything in Markdown with Vim. I love writing with Vim because it's distraction-free and it doesn't make me nervous that I'll lose my work if my browser quits or loses its internet connection.

I keep two other terminals open for building and serving my site so I can preview my work. One runs a simple HTTP server on localhost:8000 with Python:

$ cd build
$ python3 -m http.server

The other is used to manually build my site whenever I want to update the local build with new changes:

$ make

Then I refresh my browser to see the changes.

I find I'm better at detecting typos and weird language when I read what I've written in the browser. I revise, make changes, and repeat.

When I'm done, I commit it, push it, and Netlify builds and deploys it to production automatically:

$ git add src/writing/2019-11-02-how-my-personal-website-is-built.md
$ git commit -m "Add how-my-personal-website-is-built writing"
$ git push origin HEAD

# Wait a minute or two

$ firefox ryannjohnson.com/writing/how-my-personal-website-is-built/

All my CSS is plain and in a single style.css file. I was using SASS for a while, but I've really pared my site down over the years and found a preprocessor to be overkill. With CSS custom properties and the minimalistic design I've arrived at, I really don't miss SASS at all for this project.

All HTML is in the layouts/ directory, and all static assets are in the public/ directory.

My Bitbucket repo is private. I have two main reasons for this: 1) I run experiments all the time, some of which don't pan out. I happily leave those ones behind in my deep, dark, private git repo history, and 2) I save drafts to git between writing sessions as a backup. Nobody needs to read my half-written articles.

Building my own custom pages and post "types" has been super easy.

One of my experiments that I ended up keeping was my gratitude section. The source directory for this section looks like this:

src/gratitude/
├── ...
├── 2019-10-23.md
├── 2019-10-27.md
├── 2019-10-30.md
└── index.html

Each YYYY-MM-DD.md file has only Markdown in it with no Frontmatter. All these files get collected and spit out into a directory with a small Metalsmith plugin I wrote that looks similar to this one. The result is a directory tree that looks like this:

build/gratitude/
├── ...
├── 2019
│   ├── ...
│   └── 10
│       ├── ...
│       ├── 23
│       │   └── index.html
│       ├── 27
│       │   └── index.html
│       ├── 30
│       │   └── index.html
│       └── index.html
└── index.html

There are doubtless web applications and plugins out there that do this already, but finding them and modifying them seems daunting compared to the relatively small amount of code I had to write to make this work from scratch.

As somebody who knows how to use git and code, I don't feel like I'm missing out on features from a conventional content management system.

The systems I compare my setup to in my head all have a content management system (CMS) that make adding content through the browser easy. This is the case with Wordpress, Ghost, Wix, Squarespace, and even Contentful. Adding images and audio to written posts is a drag-and-drop operation on these platforms, and I could see how managing authors' permissions would be especially important within an organization of people.

As a single person who understands development tools and languages, I'm willing to forego these benefits and instead gain the decentralization and control that git and command line tools can offer. I'm not tied down to any particular vendor, and my production data is available everywhere that my codebase is. I know how all my site's features and content are laid out in code, so making tweaks is trivial for me. If I really, really need a web interface to update my content with, I can still update my site through Bitbucket's website if I need to.