OddTurnip logo OddTurnip

A simple philosophy: Claude handles the code; I verify the outputs.

I've spent the last couple of years learning to use LLMs as my primary tool for software development. Part of this is practice and education; the goal is less about the resulting software and more to learn what an LLM-centric workflow can accomplish. As a bonus, it's a great chance to build a bunch of little utility apps that help my day to day tasks, but were never quite worth the effort to build/maintain.

The number one lesson I've learned is that being a good developer now looks a lot like being good at Quality Assurance - you need to be comfortable writing and analyzing unit tests, but you also need to do a lot of manual testing. It's important to do a thorough walk-through of both the happy and unhappy paths, to make sure everything actually works together - and that the LLM understood what outcomes I actually wanted from this application.

A related lesson has been that moving something "in-house" increases maintenance. Now I occasionally have to detour and fix bugs in my text editor, when I had intended to be writing a document. Fortunately, those fixes are a lot faster, so it's still worth the effort to me - but it helps me to appreciate how software isn't just the up-front cost of writing code, and never has been.

Programming experience still matters, though - I can immediately get a feel for a lot of errors in the code simply based on the behavior. These two numbers don't match, which means there's a DRY (Don't Repeat Yourself) violation in there somewhere. Having an intuition for when a build has gotten complex and messy, and pushing the LLM to do an architectural review. Getting a feel for when technical debt is building, and prompting the LLM to go on a bug hunt.

Agile is a great framework, here. Writing a quick prototype to test a concept is exactly where LLMs are ideal. They're great for rapid iteration and playing around with ideas. They never complain about tossing out a week's worth of code to do a tighter rewrite, now that the problem domain is better understood. When I work on TurnipText, it's great being able to try out a silly idea - occasionally one of them turns out better than expected, and the rest are a quick revert.

LLMs drop the cost of exploration to near-zero, and I think that's one of the most overlooked benefits. Once you've proven the concept works, it's a lot easier to fine-tune performance, or even start over entirely with a performance-centered rewrite.

Note from July 2026: the earliest entries below were mostly one-shots, and one-shots have stopped being as impressive - "Claude Opus 4.5 can one-shot generate Tetris" has been eclipsed by "Claude Fable 5 can one-shot generate a Pokemon Red clone". I'm leaving them up because I had fun building them, and they're a stark example of just how fast this technology can move.

TrainTime: a game set on the real Amtrak Cascades timetable

Work the bistro car on the Portland-to-Seattle run, in a game where each round takes 3.4 real hours because that's how long the actual train ride lasts. Real GTFS timetables, and scenery generated from actual geography (OpenStreetMap roads, rivers, and towns).

What I learned: LLMs still struggle a bit with visual tasks, so there was a surprising amount of debugging here. I often just needed to describe the issue or send them a couple of screenshots, but this is still an area where models struggle. Conversely, Claude Opus 4.8 was able to trivially identify and download all of the data sets needed, and was even good at building a single-route model instead of pulling the much larger national datasets. I still want to revisit the graphics on this, as Fable 5 and ChatGPT 5.6 Sol both seem to show impressive aesthetic improvements.

CardCrow: a "Magic: The Gathering" deck builder

Magic: The Gathering is a complex game. Every year sees 7 new sets of cards, totalling over a thousand individual cards to keep track of. It's a lot to keep up with. I've never quite liked any of the existing tools, so I built a website that combines all my favorites. It queries the existing Scryfall databases, lets me track my existing decks, and easily search for new cards to upgrade them or build a new deck. This includes a full LLM-built login/authentication system, running on a self-maintained public server.

What I learned: LLMs are remarkably good at respecting external API policies - I gave them the Scryfall terms of service and let them build everything from there. There were a couple places where they failed to respect API rate limits, but that's why QA is still so important!

Egelbos: self-administered server

OddTurnip uses basic cPanel hosting, which was fine when I was hosting static sites and using github.io and DNS subdomain redirects. Egelbos let me start building more complex applications on my own VPS. Flask apps behind gunicorn and nginx over unix sockets, one systemd unit per service, SQLite databases kept outside the deploy tree, and a JWT login system with invite keys for the authentication API. This gives me a solid foundation for hosting actual data, across multiple users.

What I learned: I've done sysadmin work professionally, and LLMs are surprisingly solid here. I expected I'd need to do a lot of hand-holding, but "build me a secure server" resulted in a pretty similar stack to what I would have gone with. On the other hand, the audit logs were all my idea - LLMs are great about handling the immediate problem, but they don't tend to think "what happens if that fails". In security, that's usually the most important question. That and whether you've actually tested your backups.

Trito: a simple online RPG

This was inspired by one of the earlier open-source RPGs on the internet, "Dragon Court". This was an interesting test of how well LLMs can modernize an older game - preserving the mechanics, but replacing all of the text and graphics with something modern.

What I learned: back in February, this was beyond what an LLM could one-shot, so I got to learn how to play Project Manager. I diligently worked out a full list of game features, then tracked progress against those. I also made sure the game could easily be played via scripted calls, allowing playthroughs to be encoded in unit tests.

TurnipText is a text editor shaped around how I personally work

A small, opinionated writing tool with exactly the features I use and nothing I don't.

What I learned: It's ugly but it works exceptionally well for me. It feels a bit clumsy any time I have to use a non-bespoke Text Editor now. I think in a few years, this sort of bespoke customization will be normal for a wide range of applications - I can ask Claude for a new feature and be using it 5 minutes later.

Toolbox: single-page web utilities

A collection of basic tools like word count, text diff, and some surprisingly capable image manipulation tools. Plenty of similar collections exist, but this one has everything I need and nothing I don't.

What I learned: it's remarkably easy to build simple single-purpose image manipulation websites, and they work much faster than a dedicated multi-purpose application.

WebArcade: a weekend of classic games in the browser

A small arcade of browser games with sound effects, music, and gamepad support. Built in a weekend to see how far Claude could get with minimal one-shot prompts like “create Tetris”, “add support for my XBox controller” and “compose some music and SFX”.

What I learned: with minimal specification, it usually took me a second prompt to actually be fully satisfied with the output, but only Tetris had a bug (a race condition where rotation should allow falling to continue, but it had already “locked” into place - solved by prompting it solely with a description of the behavior). In short, these tools have a surprisingly good sense of context, and understand what sort of features each game should have - high scores, etc.

Gaming tools for my weekly tabletop group

Dice rollers, a SQLite-backed name generator, and digital character sheets for Blades in the Dark, FATE, and a homebrew system - built to solve real friction at our actual game table.

What I learned: I've built these in a few different languages over the year, so I know the perils well. I was quite impressed with the LLM's accuracy here, and especially their ability to build unit tests around random number generators - which tends to require both stubbing the Random function AND being willing to run technically “unreliable” statistical tests. For my personal code base, a one in a million “flaky test” is quite acceptable to ensure everything really does work when a non-mocked Random is plugged in.

Bonus: LLMs are also a pretty solid source for populating a database of random names, and the database / variety helps shake them out of their otherwise slightly eccentric naming tendencies.