This site is intentionally boring. The goal is a small, durable personal website that’s easy to maintain for years, easy to write in, and easy to deploy. No runtime backend, no database, no request-time rendering: just content and a predictable build.

Core decisions

Static generation with Jekyll

The site is built with Jekyll, a Ruby-based static site generator.

  • Content is written in Markdown.
  • Templates are simple HTML + LiquidJS.
  • Output is plain static files (fast, cacheable, low attack surface).

Posts are written as dated Markdown entries (with front matter) and become URLs like:

  • /posts/YYYY/MM/DD/title/

The exact URL shape is controlled by a permalink setting in the site configuration.

Markdown-first authoring (with HTML allowed)

Everything important is Markdown:

  • Posts: dated writing (the blog)
  • Pages: evergreen content (about, links, quotes, etc.)
  • “Books” / notes (optional): longer-lived reading notes or summaries

Markdown keeps content portable and diff-friendly, and Jekyll’s Markdown engine allows inline HTML when needed.

Content management: Decap CMS + Git Gateway

To keep editing convenient without adding a backend, the CMS is Decap CMS (Git-based). Content edits happen via /admin/ and are committed into the repository.

Authentication + Git operations are handled by Netlify Identity + Git Gateway:

  • Netlify Identity: login / user management
  • Git Gateway: lets the CMS write to your Git repo without requiring the editor to have an account on your Git hosting provider

The CMS is configured with a YAML file that defines collections (posts, pages, etc.), their fields (title, date, tags), and where media uploads go.

Deployment: Netlify

The site deploys to Netlify:

  • A build command runs Jekyll via Bundler
  • The output is a static site directory
  • A Netlify config file defines the build settings and ensures the admin UI routes correctly

Because the output is static, deploys are quick and rollbacks are easy.

To avoid complexity, the site uses one taxonomy: Tags.

Implementation detail: one built-in front matter field is treated as the site’s “tags” list, and tag archives are generated automatically.

Automatic tag pages

Tag pages like:

  • /tags/engineering/

are generated via the jekyll-archives plugin and rendered with a simple tag-archive layout.

Feeds, SEO, and other “boring but important” features

The plugin set is small and standard:

  • jekyll-feed: generates /feed.xml for RSS readers
  • jekyll-sitemap: generates /sitemap.xml for crawlers
  • jekyll-archives: generates tag archive pages

This keeps the build predictable and avoids custom generators.

Local development

Local dev runs in Docker for consistency:

  • A compose file runs jekyll serve
  • A Makefile (or a few documented commands) wraps common tasks like “serve” and “rebuild”

This avoids “works on my machine” Ruby version issues.

Styling philosophy

Styling is CSS-only and content-first:

  • Clean typography and a readable measure
  • Strong defaults for code blocks (developer blog)
  • Minimal UI chrome (header/footer don’t compete with content)

One CSS file does almost all the work. The emphasis is on good defaults: typography, spacing, links, and code blocks.

Summary

The stack is deliberately minimal:

  • Jekyll for static generation
  • Markdown for content
  • Decap CMS for editing
  • Netlify + Git Gateway for deployment + auth

The result: a site that’s fast, maintainable, and easy to publish to—without a runtime backend or a JS framework.

If you want to recreate this site (human- or AI-generated)

Here’s a concise “spec” you can hand to another AI (or use as a checklist) to generate an equivalent repository.

Site goals

  • A personal site + blog with excellent readability and fast load times
  • No client-side framework requirement (plain HTML/CSS output)
  • Write content in Markdown with front matter
  • Simple navigation: home, posts index, about, links, quotes, tag index

Content model

  • Posts: dated Markdown entries with title, date, and tags
  • Pages: Markdown pages for about/links/quotes (and optional books/notes)
  • Tags: one tag list per post, plus auto-generated tag archive pages

URL structure

  • Posts at /posts/YYYY/MM/DD/slug/
  • Tag archives at /tags/<tag>/
  • A posts index at /posts/ and a tag index at /tags/

Templates & layouts

  • A default layout with header + footer and a centered, readable content column
  • A post layout that renders title/date/tags and the post body
  • List layouts for posts and tag archives

Styling requirements (CSS-only)

  • Comfortable type scale, line height, and measure (roughly 65–75 characters)
  • Good defaults for headings, lists, blockquotes, and links
  • Code blocks styled for developer writing (monospace, padding, horizontal scroll)
  • Mobile-first spacing and typography
  • Decap CMS served at /admin/
  • Netlify Identity + Git Gateway for authentication and Git writes
  • CMS collections for posts and pages, including media uploads

Deployment & dev environment

  • Netlify deploy with a single build command (Bundler + Jekyll)
  • Local development via Docker to avoid Ruby version drift
  • A couple of convenience commands (Makefile optional)

Resources