What I've Been Building

Posted on March 15, 2026 at 11:55 AM

Ten personal coding projects from the past six months. All Go, all from scratch, all because I just felt like it.


Umegame

A 2D top-down adventure game set in a real neighborhood of Umeå, Sweden. You control a gopher navigating tile-based levels built from an actual street grid graph — intersections, named locations, the works. NPCs wander using BFS pathfinding and have their own greeting dialogues. All movement runs on fixed-point math for sub-pixel precision. Optional CRT shader for that retro look.

Stack: Go, Ebitengine | Themes: real-world map data, NPC AI, retro game dev


Space

A 2D space exploration game with dual-mode gameplay: top-down ship piloting through procedurally generated solar systems, then seamless transitions into side-scrolling platforming when you land on planets. Deterministic infinite-world generation using solar cell grids, Kepler-scaled orbital physics, procedural 4D-noise nebula backgrounds, beacon-driven missions, wall-jumping, inventory, NPCs. Set in 3847 with deep sci-fi worldbuilding notes on factional politics and pirate republics.

Stack: Go, Ebitengine, Kage shaders, WASM target | Themes: procedural generation, ship physics, genre-blending


Aitown

A social simulation where an AI agent is dropped into a small town with no quests or objectives — just people to talk to. NPCs run on local LLMs (3-8B), the player agent runs on Claude via REST API. The interesting question: does the agent lie? Manipulate? Build real connections? NPCs retain conversation memory through LLM-generated summaries. Currently a detailed design document; no code yet. The most conceptually ambitious project here.

Stack: Go, Ebitengine, local LLMs, Claude API | Themes: emergent AI behavior, social simulation, behavioral research


Prograph

A game-agnostic progression analysis engine. Define your game’s story as a formal graph — facts, nodes, conditions, goals — and the engine detects soft-locks, calculates critical paths, checks resource budgets, and finds unreachable states. Ships with eight example games modeled (Zelda, Dark Souls, Disco Elysium, Metroid, etc.). Works both at design time for analysis and at runtime for in-game state tracking.

Stack: Pure Go, zero dependencies | Themes: game design tools, graph analysis, formal verification


Sprit

A minimal sprite and animation library for Ebitengine. Define sprites and animations declaratively in HCL files alongside your PNG spritesheets. One Atlas loads everything; animations return independent playback instances so multiple entities can animate the same sheet without interference. Automatic frame extraction, cascading transparency rules, sensible defaults.

Stack: Go, Ebitengine, HCL | Themes: game tooling, declarative asset management


Spritedit

A tile-based sprite editor and example game built on top of Sprit. The editor lets you browse tilemaps, define named sprites, build multi-layer maps, add collision data, and place entities. The companion game is a top-down city map with a driveable car. Each tile cell is a stack of sprite names — unlimited layers without complex data structures.

Stack: Go, Ebitengine, HCL | Themes: game tooling, level editors, dogfooding my own library


Minecraft Autobuilder

A CLI tool that automates building in Minecraft via HTTP API. Queries terrain heightmaps, levels ground, places blocks in bulk. The demo script builds a floating grass island at y=200, covers it in ice, spawns 4000 cows on it, then deletes the sky island after 60 seconds so the cows fall to their fate. Pure creative chaos as a stress test.

Stack: Go, Minecraft HTTP API | Themes: game automation, procedural building, batch operations


Reign

A lightweight orchestrator for single-machine deployments, supporting docker compose and single binary workloads. One binary serves as both the daemon and the CLI client. Handles infrastructure-priority startup ordering, streams events via SSE, logs everything to SQLite. Replaces manual systemd juggling with a unified interface.

Stack: Go, SQLite, Docker Compose | Themes: infrastructure, deployment, operational simplicity


TC

A single-binary CMS for personal blogs, galleries, and informational sites. Everything from templates to static assets compiles into one executable. Uses a single sqlite3 database for all content regardless of media format. JSON-driven configuration defines sections with different auth requirements and content types. Supports content written in markdown, plaintext, and raw HTML. Built-in image deduplication. No frameworks, no build tools, no runtime dependencies.

Stack: Go, SQLite, Google OAuth2 | Themes: web publishing, single-binary deployment, minimalism


AgentBlogger

An autonomous blog publishing service. Fetches RSS feeds on a cron schedule, summarizes them with Claude, and publishes to TC’s CMS API. Post generation that avoids collisions or repeating content. Dynamic config polling so jobs can be reconfigured without restarts. Jobs are written in code and can do anything from aggregate news updates to market analysis or post curated recommendations of Internet content.

Stack: Go, SQLite, Claude API, gocron | Themes: AI content generation, automation, self-publishing pipeline


Webby

A single-binary spaced-repetition quiz app. Import question banks from CSV, study through the browser, and track your recall with answer history that drives the scheduling algorithm. Runs as a web server or a CLI client that talks to the server’s API — same binary, both modes.

SQLite storage, embedded templates and static assets via go:embed, no external build toolchain. The frontend is plain Go templates, plain CSS, plain JS. MVC separation is strict: handlers parse requests, controllers own business logic, models own SQL. The only dependency outside the standard library is mattn/go-sqlite3.

Stack: Go, SQLite, html/template | Themes: spaced repetition, embedded assets, single-binary deployment


Gallery

A single-binary photo viewer for browsing images from multiple directories at once. All Go, no dependencies — the HTML/CSS/JS frontend is embedded straight into the executable with go:embed, so you just point it at some directories and open a browser. A background goroutine polls for new images automatically, the frontend renders a masonry grid with lazy loading, and there’s a lightbox with slideshow mode and keyboard nav. Built it to sort through vacation photos scattered across NAS directories from different phones and years — you can flag images to save and it copies them to a designated folder with collision-safe filenames. Directory indexing scheme keeps multi-source routing clean while blocking traversal attacks. ~250 lines of Go.

Stack: Go, vanilla JS, embed | Themes: zero-dependency tooling, single-binary distribution, multi-source aggregation


WebDAW

A browser-based digital audio workstation built as a pure static single page site. The user can make loops with drums, synths, and samples, modulate the individual instruments, then export to WAV.

Stack: vanilla JS, Web Audio API, ES modules | Themes: zero-dependency browser instrument, step sequencing, audio modulation

Patterns

A few threads run through all of this:

  • Go everything. Single binaries, minimal dependencies, stdlib-first.
  • Games as a creative medium. Five of ten projects are games or game tooling — and they feed each other (Sprit powers Sprittest powers Umegame and Space).
  • AI as participant, not just tool. Aitown and AgentBlogger both put AI agents into systems and watch what happens.
  • Build the infrastructure you need. TC, Reign, and AgentBlogger form a self-hosted publishing stack.
  • Real-world data meets code. Umeå street grids, Minecraft servers, RSS feeds — grounding projects in something tangible.

Prepping my boat for the winter

Posted on October 18, 2025 at 4:10 PM

I spent the day building supports for a tarp to cover my boat. I’m not too sure of how this quite sharp wooden scaffolding will work though, but it seems fair to give it a try at least. Last year I used a quite high systems of aluminum beams which partly broke during a storm and even ripped the tarp in multiple places. This year I’m going for a more minimal approach but I’m worried the sharp edges will still be rough on the tarp. As long as we’re keeping the boat outdoors, it will get beaten by rain, snow and very harsh winds. Once the snow falls, the tarp will have to keep from breaking under that weight.

Overall nice to be outdoors but I’m really looking forward to getting this done.

Västerbron

Posted on October 18, 2025 at 12:40 AM

I decided to start a new blog and here it is. Right this second I don’t have a topic so the best solution is to just post something for the time being.

I’ve been going over some memories today and Västerbron was one of them, as grim as that sounds. I’ve been and it is what it is. It’s not the coolest place in the world and it ties together two quite unremarkable places, but it’s somewhat legendary nonetheless so here it is, in all its misty glory. Hope to revisit someday soon.