-
Building Embedded Discourse Comments with Rust and WASM
An experiment in creating a drop-in comment widget for static sites using Rust compiled to WebAssembly, talking to Discourse's REST API.
-
Running VPS Infrastructure with Systemd
Declarative VPS infrastructure using systemd services. Running Gitea, Woodpecker CI, Scrob, and GoatCounter with automated deployment scripts.
-
Building Scrob: A Self-Hosted Music Scrobbling Server
Built a self-hosted scrobbling server with Rust and PostgreSQL to track listening history without relying on Last.fm, featuring public profiles and automated deployment.
-
2025 - A Review
A reflective look back at 2025 as a year of integration: building durable tools, writing in public, and aligning technical work with sustainability, creativity, and a calm, long-term pace.
-
Building LLM-TUI: Never Lose Context Again
Built a terminal AI chat that remembers everything. File context persists across sessions, tools execute with confirmation, and you never lose your place.
-
JOBL and SRG: Building Resume Tools I Actually Want to Use
Building a TOML-based resume format and static generator after layoffs reminded me to keep my options open. Sometimes the best response to uncertainty is building something you control.
-
Skin Shedding, Not Bikeshedding
On letting go of endless debates and just building things to see what works.
-
Date-Ver: A Formal Spec for Date-Based Versioning
I created a formal specification for date-based version numbers because nobody else had. Now both Ubuntu and yaml-janitor are officially valid Date-Ver.
-
Building yaml-janitor: Solving the Comment Preservation Problem
How I built a YAML linter that preserves comments, validated 1,736 production files, and published it to RubyGems
-
Like a Pig in Shit: Why I Love AI "Slop"
I'm having the time of my life building projects with AI assistance. Call it slop if you want - I'm too busy shipping to care.
-
vimdeck.nvim: Markdown Presentations in Neovim
Rewrote vimdeck for Neovim using Treesitter. No Ruby, no temp files, just native Lua and clean slide rendering.
-
Invite Tree to Invite Stats - How A Simple Tree Flourished Into A Full Moderation Plugin
How a simple visualization plugin evolved into a moderation tool.
-
Visualizing Discourse Invite Trees
A simple Discourse plugin that visualizes who invited whom as an ASCII tree, inspired by Lobsters.
-
Shelltrax Part 2: Footer, Tests, and CI
Fixing footer playback progress, implementing unit tests, and setting up GitHub Actions CI for the Rust TUI music player.
-
Replacing MessageBus Pub/Sub with REST APIs: Fixing Production Outages
Converting postgres-manager from fire-and-forget MessageBus to synchronous HTTP APIs to eliminate message replay issues and gain operational visibility.
-
Building The Guest Spot: Part 2 - Two Refactors
Two major refactors: custom model to Topics, then custom feed to plugin outlets. Less code, more features, better maintainability.
-
Building The Guest Spot: Part 1 - My First Community
Building an Instagram-style showcase for tattoo artists using Discourse. My first attempt at helping build a community from scratch.
-
How I'm Using Claude Code for Daily Development Work
Real-world AI pair programming: what works, what doesn't, and how to avoid the traps
-
Building Yaks: A Virtual Currency System for Discourse (Part 4: Custom Titles and Earning System)
Implementing custom user titles and the Yaks earning system. This post covers serializer overrides for titles and building a complete earning system with rate limiting, trust level requirements, and real-time balance updates.
-
Building Yaks: A Virtual Currency System for Discourse (Part 3: Advanced Features)
Implementing topic-level features and user customization in the Yaks virtual currency plugin. This post covers topic boosting with global pinning and custom avatar flair.
-
ChatGPT assisted Changelog - 42/52
A week of creative experiments and follow-ups -- from launching a live transit board inside Discourse and polishing your AWS SDK Ruby series, to debugging GoatCounter exports and exploring privacy-friendly tools on GrapheneOS.
-
Building Yaks: A Virtual Currency System for Discourse (Part 2: Features and Expiration)
Part 2 covers implementing topic pinning, building a modular service architecture, and creating an expiration system with background jobs.
-
Building Slumprutt: A Random Route Generator in Under an Hour
Built a complete random route generator app with TypeScript, Svelte, and OSRM to find new walking and cycling routes in my neighborhood.
-
AWS SDK Ruby Part 3: When "Working as Intended" Means "Broken by Design"
The conclusion to the AWS credential chain saga, where maintainers close a valid bug report, the feature remains broken, and we learn about the politics of backward compatibility in open source.
-
Building Yaks: A Virtual Currency System for Discourse (Part 1: Backend Architecture)
Building a virtual currency plugin for Discourse. Part 1 covers the backend architecture: wallets, transactions, features, and the service layer that ties it together.
-
ChatGPT assisted Changelog - 41/52
A quieter but productive week focused on publishing the Discourse transit tracker post, analyzing GoatCounter data across 37 countries and six continents, and continuing open source contributions to the AWS SDK for Ruby.
-
Building a Live Transit Departure Board with Discourse
Experimenting with Discourse as a live transit departure board - blending GTFS data, aviation APIs, and forum topics into one real-time display.
-
My First Official Contribution to Discourse
A small but satisfying first PR to the Discourse core codebase.
-
Going off the Rails on the AWS Credential Chain
Uncovering a deeper architectural issue in the AWS Ruby SDK where credential chain precedence prevented role assumption from working correctly with environment variable source credentials.
-
ChatGPT assisted Changelog - 40/52
Weekly topics spanning Czechia residency planning, Anki language learning setup, Framework 16 NixOS troubleshooting, Discourse plugin ideas, and practical logistics for international relocation.
-
ChatGPT assisted Changelog - 36-39/52
A ChatGPT-generated summary covering Prague travel notes, Czech visa preparation, camera research, Discourse experiments, desktop tooling, email deliverability, and personal logistics from weeks 36-39.
-
First time in Europe: One week in Prague
Field notes from a first-timer: a castle, smooth city transit, and tattoos.
-
Reverse Engineering A Unique Data Structure - Part 3, Course & Course Details
Decoding deeply nested course data by resolving schema maps within schema maps to extract readable information about disc golf courses including layouts, holes, and amenities.
-
Reverse Engineering A Unique Data Structure - Part 2, Search
Discovering and using search endpoints for places and courses that return well-formed data, making it easy to find specific locations and query disc golf course information.
-
ChatGPT assisted Changelog - 35/52
Weekly updates on cashctl budgeting tool development, Zola site improvements, AWS SDK contributions, and resume refinements for showcasing open source work.
-
Reverse Engineering A Unique Data Structure - Part 1, Courses
Uncovering how a Remix-based disc golf app encodes course data in obfuscated arrays using index maps and schema maps, then writing TypeScript to parse it into usable objects.
-
Contributing to the AWS Ruby SDK: When Documentation and Implementation Don't Match
Discovering and fixing a missing credential source implementation in the AWS Ruby SDK where documentation promised Environment support but the code didn't deliver.
-
ChatGPT assisted Changelog - 34/52
A week balancing travel research for Europe, Shelltrax autoplay debugging, Discourse logo design experiments, and technical problem-solving across multiple projects.
-
ChatGPT assisted Changelog - 32+33/52
Two weeks of NixOS troubleshooting, node-postgres-exporter development, Framework 16 hardware configuration, and preparation for upcoming European travel.
-
ChatGPT assisted Changelog - 31/52
Weekly progress on Nix package development, NixOS Wi-Fi setup on Framework 16, Git commit signing, Hyprland keybinds, and exploring privacy-focused smartwatch options.
-
Hyprland Tricks - Close Window Keybind With Confirmation Window
Adding a simple Wofi confirmation dialog to Hyprland's window close keybind to prevent accidentally closing important windows with a quick Yes/No prompt.
-
NixOS as a daily driver or Zero to Nixty, part 9/? - Enabling Wi-Fi
Troubleshooting and fixing Wi-Fi on a Framework 16 laptop running NixOS by loading the Intel AX210 driver, enabling firmware, and configuring NetworkManager with wpa_supplicant.
-
ChatGPT assisted Changelog - 30/52
First week at Discourse covering Waybar configuration, Nixvim setup, Kolide agent deployment, TUI music player fixes, and various NixOS system troubleshooting.
-
Today is my first day at Discourse!
Celebrating the start of a new role at Discourse as a software engineer on the infrastructure team, working on open source software with an async, remote-first company.
-
NixOS as a daily driver or Zero to Nixty, part 8/? - Modular Config
Breaking down a NixOS configuration into reusable modules organized by host and common settings, making it easy to deploy consistent environments across multiple machines.
-
ChatGPT assisted Changelog - 29/52
Refining NixOS setup with modular dotfiles, exploring Framework laptop RGB customization, researching task managers, and planning for NixCon 2025 attendance.
-
NixOS as a daily driver or Zero to Nixty, part 7.5/? - Trial by Encrypted Fire
A detailed account of struggling through manual LUKS encryption setup on NixOS, hitting multiple roadblocks, and ultimately succeeding with the graphical installer after three failed attempts.
-
ChatGPT assisted Changelog - 28/52
Publishing NixOS daily driver posts, fighting encrypted disk installation issues, playing disc golf, continuing Swedish language studies, and garden updates.
-
NixOS as a daily driver or Zero to Nixty, part 6/? - Dev environment
Introducing NixVim for declarative Neovim configuration and exploring nix-shell for creating reproducible, project-specific development environments without global installs.
-
NixOS as a daily driver or Zero to Nixty, part 5/? - QoL enhancements
Configuring keyboard remapping with Interception Tools to make Caps Lock act as Escape when tapped and Control when held, plus setting up hypridle and hyprlock for automatic screen locking.
-
Fairway Client Not Fair Enough for MyFrisbee
The story of building an open source library to access public MyFrisbee data endpoints, receiving a takedown request despite working with user-submitted information, and the disappointment that followed.
-
ChatGPT Changelog - 27/52
Week of NixOS and NixVim work including caps lock remapping, Starship integration, PipeWire setup, MyFrisbee reverse engineering takedown, woodworking projects, and job offer celebration.
-
ChatGPT Changelog (fka Weekly Summary) - 26/52
Refining NixOS workflow with nix-shell and Flakes, progressing GitVote CLI with GPG signatures, continuing blog writing, and maintaining Swedish language learning streak.
-
NixOS as a daily driver or Zero to Nixty, part 4/? - dotfile/config management
Using Dotter to manage NixOS configuration and Hyprland settings in version control with symlinks, making it simple to deploy and reproduce your setup across machines.
-
How I accidentally wrote my first Neovim plugin
A journey from regex-powered single-line rewrites to a fully tested Neovim plugin for formatting JavaScript and Rust imports, learning why simpler solutions sometimes beat powerful tools like Treesitter.
-
Introducing Shelltrax - Or how I vibe programmed my way to a TUI music player
Building a terminal-based music player in Rust from scratch to learn the language through real-world challenges like TUI rendering, audio streaming, metadata parsing, and concurrent state management.
-
Building a Fully Decentralized Voting System Using Just Git and Pull Requests
Creating a transparent, auditable voting system where Git commits are the ledger, pull requests are ballots, and CI validates every vote without any centralized servers or databases.
-
The Accidental Complexity of Doing The Right Thing or The Pain of Setting Up Privacy-Focused Analytics (2025 Edition)
The frustrating journey of setting up GoatCounter for privacy-respecting analytics, encountering broken Docker registries, build failures, and tooling friction that makes ethical software harder to deploy.
-
node-postgres-exporter — A Lightweight, Configurable PostgreSQL Prometheus Exporter
Building a flexible Node.js-based Prometheus exporter for PostgreSQL with multi-database support, dynamic custom metrics via JSON configuration, and production-ready fault isolation.
-
ChatGPT Changelog (fka Weekly Summary) - 25/52
Weekly accomplishments including Shelltrax TUI refinements, MyFrisbee API decoding progress, node-postgres-exporter release, NixOS configuration improvements, and Swedish study milestone.
-
ChatGPT Changelog (fka Weekly Summary) - 24/52
Introducing ChatGPT-generated personal changelogs covering MyFrisbee blog series, PostgreSQL exporter deployment, NixOS Hyprland configuration, and ongoing Swedish language learning.
-
Typing åäö in Hyprland: A US, Mac-style Keyboard Guide
Configuring Hyprland to type Swedish characters using a US keyboard layout with Right Alt as a modifier, perfect for learners who want proper typing practice without remapping keys.
-
Weekly Summary - 23/52
Accomplishments in reverse engineering MyFrisbee API, TypeScript module publishing, static site improvements, NixOS blog series, Gitea self-hosting, and reaching 179-day Swedish streak.
-
NixOS as a daily driver on a late 2011 Macbook Pro, part 3/? - user, WM, tools
Setting up a non-root user with sudo access, installing Hyprland as a window manager, and configuring essential daily driver tools like Neovim, Git, and Librewolf on NixOS.
-
NixOS as a daily driver on a late 2011 Macbook Pro, part 2/? - Installation, Basic Configuration
A step-by-step guide to installing NixOS from a minimal ISO, including partitioning with EFI, formatting drives, generating configuration files, and completing the first system build.
-
How Vulfmon Inspired Me to Learn to Weave
Discovering a beautiful weaving in a Vulfmon music video sparked a new creative journey, resulting in six handmade pieces inspired by Jack Stratton's aesthetic.
-
Weekly Summary - 22/52
A productive week focused on API inspection and blog writing, continuing Swedish language studies for 172 days, and sending out 13 job applications.
-
Deploying a Zola static site to a custom domain with Github Actions
Setting up automated deployment for a Zola-based static site using GitHub Actions to build and publish to GitHub Pages with a custom domain and DNS configuration.
-
Weekly Summary - 21/52
Celebrating RockPro64 revival, continuing Swedish studies, starting API inspection work, and solving NixOS Hyprland boot issues.
-
NixOS as a daily driver on a late 2011 Macbook Pro, part 1/? - What and why?
An introduction to Nix and NixOS, explaining purely functional package management, declarative system configuration, atomic rollbacks, and why this approach makes for a powerful daily driver OS.
-
Weekly Summary - 20/52
Starting a weekly reflection series covering site deployment, Raspberry Pi revival, Rust learning with blockchain and TUI projects, woodworking, and job hunting progress.