Minimal Viable Blogging

On HackerNews today, there were two articles very relevant to my journey in building out my website.

  1. The Minimum Viable Blog
  2. Why can't html alone do includes?

I was heavily inspired by articles like #1 to start blogging (not this one in particular given the date), but I made it my mission to not reach for Django, Rails, Astro, or really anything outside of HTML. I did not cut my teeth by building webpages, so I wanted to use this opportunity to learn how to do as much as possible with just HTML and CSS.

It did not take me very long to run into the problems listed in article #2. After writing only one blog post, I wanted to refactor out the common header and footer elements to their own templates.

Nope, you can't do that with just HTML.

However, I did find a solution using Caddy's built-in features as I detail in my earlier posts. I saved myself from Django or Rails, but I guess I did end up writing a bit of Golang.

¯_(ツ)_/¯

Sorting files in reverse order

This one had me scratching my head for far too long. How do you render a list of posts in reverse order? I knew to make it easy, I would name files to ensure they are sorted in order on the file system.

I thought all I had to do was reverse (listFiles "./posts/") in my Caddyfile. This worked just fine on my machine, but when deployed, my post order would be wildly incorrect.

What I ended up doing was: reverse (sortAlpha (listFiles "./posts/")) which leverages the sortAlpha string list function from Sprig.

Moral of the story: Read the f___cking Manual

Styling code blocks with Chroma

I have always found it difficult to properly style my code blocks when using just HTML. My last attempt used a bit of Javascript to generate it on the fly which led to terrible layout shifts on first load.

Caddy uses Chroma for handling tokenization of code blocks within a markdown file and provides styles. A fully static approach is exactly what I was looking for, but I struggled to get the styling to work.

What I had to do was generate the styles via the Chroma CLI tool and add them to my CSS file.

brew install chroma

chroma --html-styles -s catppuccin-latte | pbcopy

A list of styles can be found here

I fully believe there is a way to generate the styles inline, but this worked just fine for my needs

Anatomy of a Post

Before diving into the template that drives the feed itself, let's break down what a post looks like and the magic of the splitFrontMatter function..

The file driving a post is laid out like so:


---
title: My title
date: 2025-04-25
tags: helpful, tags
description: SEO description
---
{markdown content}

splitFrontMatter will automatically parse out everything between the --- marks and uses each key as an entry to the Meta dictionary. We can then use these keys in our HTML template.


{{ $parsed := splitFrontMatter $content }}
{{ if $parsed }}
  {{ $title := $parsed.Meta.title }}
  {{ $date := $parsed.Meta.date }}
  {{ $tags := $parsed.Meta.tags }}
  
  <section class="blog post-item">
    <h2><a href="/post/{{ $file }}">{{ $title }}</a></h2>
    <div class="post-meta mono">
    <time datetime={{ $date }}>{{ $date | htmlDate }}</time>
      {{ if $tags }}
        <span class="post-tags">{{ $tags }}</span>
      {{ end }}
    </div>
    <div class="post-content">
      {{ markdown $parsed.Body }}
    </div>
  </section>
{{ end }}

I was surprised with how intuitive it was to get things set up once I discovered the proper functions to do so. Caddy is made with Golang and comes with a variety of helpful packages for template rendering:

  • Caddy itself: Contains most of the functions for manipulating files
  • Sprig: Contains the functions to format strings & dates, reverse lists, and much more
  • Golang text/template package: Necessary reference for the syntax driving the templating engine

Hello World

After many futile attempts to start blogging, I decided to start small with link posts and a more freeform feed.

I became a fan of Simon Willison's blog and was inspired by his post on how to run a link blog

Of course, before I could get started, I had to ask myself how I was going to manage this feed a.k.a procrastinating on the hard task of actually writing.

Since I already knew a bit about Caddy's templating system, I was aware of the possibilities of building the feed without using Hugo, Gatsby, Python, etc. So with a bit of help from Aider (not as much as I would have liked, it got most of the functions wrong), I finally have my own link feed.

My first series of posts will focus on how the techniques I used to set it up in case you want to do it yourself.