Hello, World — Welcome to My Blog

The obligatory first post: what this blog is, what I'll write about, and how I built the engine behind it.

Why another personal blog?

After years of reading other people’s technical writing and thinking “I should write that down”, I finally did something about it. This blog exists as a place to think out loud — about systems programming, compilers, language design, and whatever rabbit hole I’m currently deep inside.

The engine

This blog runs on a small Go HTTP server I wrote from scratch. Pages are pre-rendered at startup into an in-memory cache, so every request is essentially a hash-map lookup.

Here’s the core render loop:

cmd/server/main.gogo
if err := renderer.RenderAll(store); err != nil {
    log.Fatalf("pre-render: %v", err)
}
log.Printf("Pre-render complete")

And the cache lookup in the HTTP handler:

internal/server/handlers.gogo
func serveFromCache(w http.ResponseWriter, r *http.Request, cache *render.PageCache) {
    page := cache.Get(r.URL.Path)
    if page == nil {
        http.NotFound(w, r)
        return
    }
    if match := r.Header.Get("If-None-Match"); match == page.ETag {
        w.WriteHeader(http.StatusNotModified)
        return
    }
    w.Header().Set("ETag", page.ETag)
    w.Header().Set("Content-Type", page.ContentType)
    w.Write(page.Body)
}

Syntax highlighting

The renderer supports a wide range of languages. Here’s a Zig comptime example:

zig
fn fibonacci(comptime n: comptime_int) comptime_int {
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

const fib10 = fibonacci(10); // evaluated at compile time

And a Rust one:

src/main.rsrust
use std::collections::HashMap;

fn word_count(text: &str) -> HashMap<&str, usize> {
    let mut map = HashMap::new();
    for word in text.split_whitespace() {
        *map.entry(word).or_insert(0) += 1;
    }
    map
}

Shell commands too:

docker build -t patrickchodev/blog:latest .
docker run -p 8080:8080 \
  -v ./content:/content:ro \
  patrickchodev/blog:latest

Image support

Images render as <figure> elements with captions, just like Medium.

Standard image with caption:

A Go gopher standing on a mountain of code
A Go gopher standing on a mountain of code

Wide image (slightly wider than the reading column):

The Go team at GopherCon 2024
The Go team at GopherCon 2024

What’s next

Posts I have in the queue:

  1. Writing a Markdown parser from scratch in Zig
  2. How goldmark’s AST extension system works
  3. Nomad vs Kubernetes — a practitioner’s perspective

Subscribe via Atom feed or RSS.

By PatrickChoDev

You might also like