Category: Developer Life

  • Building in the Margins

    It’s 10:14pm on a Tuesday. My daughter is asleep. I left the office at five, was home by six, and the next three hours were the kind of time that doesn’t really belong to anything — dinner, transition, the parental handoff from day mode to whatever this is. By nine the scattered part settles. By ten I’m actually in it.

    I open the Nitro 5. Three windows arrange themselves the way they always do: the editor on the left, the terminal on the right, Tower’s remote session in the corner. Tower is a Dell OptiPlex running in the spare room, accessible via Tailscale from anywhere, always on. I don’t have to be at a desk for this to work. The infrastructure runs whether I’m in front of it or not.

    That’s the whole point. But we’ll get there.

    What the Margin Actually Looks Like

    People talk about building on the side like it’s a schedule problem. If you just blocked out two hours every night, protected it, treated it like a meeting — the implication being that discipline is what’s missing.

    That’s not the problem.

    The problem is that the two hours exist inside a container of everything else. The day job ends at five. Home by six. The window between six and nine isn’t free time — it’s transition time. Dinner. Kid. The mental decompression that has to happen before any real cognitive work is possible. You can’t shortcut that window. Trying to work in it produces the worst of both: you’re not present for the evening, and you’re not producing anything worth keeping.

    The margin starts at nine. That’s the real number. Nine to midnight, on a good night. Less when the day was hard. More, sometimes, when something is working and stopping feels wrong.

    What’s actually in front of me at 10:14pm: a PrivyBot directive that needs reviewing, a VoidDrift bug that’s been sitting in my mental backlog since Thursday, a blog post inventory with titles and no drafts, and three ideas I had during the commute home that I texted myself and will probably misread later.

    The warrior session is navigating that. Picking one thing, closing the other tabs manually, and going.

    The “Mostly” Energy Problem

    There are two kinds of late-night sessions.

    The first kind: you sit down with actual focus. Something in the day charged you up — a problem you solved, a thing that worked, an idea that clicked — and that energy carried into the night. These sessions are disproportionately productive. You find the bug in twenty minutes that you’d been describing to yourself for a week. You write a post in ninety minutes that would have taken three hours on a Saturday. The hour is sharp.

    The second kind: you sit down because you’re supposed to. Because you told yourself you would. Because the project is real and the timeline matters and stopping is not an option. The energy is what I’d call “mostly” — mostly there, mostly functional, mostly able to hold a thought from one line to the next.

    Mostly sessions are expensive. Not because nothing happens — things happen. Code gets written. Commits get made. The progress bar moves. But the output quality is lower in ways that aren’t immediately visible. The function that works but doesn’t quite fit the architecture. The directive that’s slightly under-specified and will need a revision pass. The blog post that says what it means but not as precisely as it could.

    Mostly sessions create technical debt. Not the obvious kind — nothing breaks. The subtle kind, where everything is slightly below the standard you’d hold yourself to with sharp energy, and you don’t notice the gap until you’re looking at it two weeks later wondering why this feels off.

    I’ve stopped trying to fight this with discipline. The mostly sessions still happen — you can’t always wait for the sharp ones — but I’ve learned to route them differently. Mostly energy for low-stakes work: reading, organizing, light review, scheduling. Sharp energy for anything that sets the architecture for what comes next.

    You can’t manufacture sharp. You can stop wasting it on tasks that don’t need it.

    What the Constraint Produces

    Here’s the thing nobody says about building in the margins: the constraint makes you better at scoping.

    When you have eight uninterrupted hours, scope creep is easy. There’s room for the interesting detour, the refactor that would be nice to have, the feature you weren’t asked to build but that seems like it might be useful. You follow threads because you have time to follow threads.

    When you have ninety minutes, you don’t. The session has to have a goal that’s achievable in ninety minutes or the session fails. That forcing function produces a discipline that I genuinely don’t think I could have learned any other way.

    My directives are precise because they have to be. An under-specified directive doesn’t get discovered until the agent has gone sideways and I’ve lost forty minutes of a session I don’t have. My test floors are real because I can’t afford to discover a fake floor later. My scope tables are explicit because I’ve paid the price of implicit scope too many times with time I couldn’t recover.

    The constraints trained me. Not intentionally. Just through repetition and consequence.

    The Cost Nobody Talks About

    There’s a tax on this mode of working that I want to name directly, because the discourse around “building on the side” tends to skip it.

    The tax is continuity.

    Every session starts with a reconnect. Where was I? What was the state? What was I about to do when I had to stop? If I left clean notes, this costs five minutes. If I didn’t — if the session ended because my daughter needed something and I just closed the laptop — it costs twenty, and some of that twenty is actually reconstructing decisions I already made and don’t need to make again.

    This is why I started writing state files. docs/state/current.md on every project, updated as the last act of every session. Phase. Floor. What’s next. Not for posterity — for 10pm-me three days later who needs to get up to speed in the time it takes to read four lines.

    The other part of the cost is the solo problem. There’s no one to rubber duck with at 10pm. No team standup that catches the thing you’re about to do wrong. No architecture review. The accountability for decisions is entirely internal, which means the feedback loop on bad decisions is slow. You make the choice, you implement the choice, you live with the choice for two weeks before you see whether the choice was right.

    This is partly why the Director → Directive → Agent structure matters to me as much as it does. Claude as the architectural layer isn’t just an efficiency tool — it’s a thinking partner in a mode where thinking partners aren’t otherwise available. The directive is the rubber duck session. Writing it forces the decision to be explicit in a way that internal monologue doesn’t.

    What This Mode Is Building Toward

    I want to be clear about something: I’m not trying to grind indefinitely in the margins.

    The goal of the sessions is to build things that eventually don’t need sessions.

    PrivyBot runs on Tower autonomously. RALPH — the persistent overseer — fires on its own, runs tasks, monitors things I’d otherwise have to check manually. ContentPipeline records, transcribes, assembles, and schedules content while I sleep. TeleseroAdmin2026 runs its own loop during business hours without me watching it. The DNC automation is on Cloud Run, stable, handling compliance checks I used to do manually.

    Every system I’ve built in the margins has reduced the number of things that require me to be present. That’s the compounding. The warrior sessions are deposits. The autonomous systems are the interest.

    The consulting angle I’m building toward is the same logic applied externally: I’m not selling my time, I’m selling systems that reduce the need for my time. The pitch I’m developing isn’t “I’ll do this for you” — it’s “I’ll build this for you once and it will run without me.”

    You can’t make that pitch credibly without having built it for yourself first.

    The Honest Frame

    I’m not writing this to make the margins sound romantic. They’re not. The mostly sessions are real. The continuity tax is real. The isolation is real. The constraint that my daughter’s stability comes first — that certain risks don’t get taken, certain opportunities don’t get chased, certain all-in bets don’t get made — that’s real too.

    But the margins are where I have, and I’ve stopped waiting for better conditions before building seriously in them.

    The three-window setup at 10:14pm is not the setup I’d design if I were designing from scratch. It’s the setup that exists. Tower in the corner, Nitro 5 on the desk, the terminal showing a floor that’s real because I ran it myself.

    It’s enough to build something from.

  • The grammar of what’s possible

    There’s a Yu-Gi-Oh game on PS1 where you can fuse two cards together. The result isn’t random. There are rules. But you don’t know the rules yet — you just know that two inputs produce a third thing that neither input was, and that the third thing surprises you even when it shouldn’t.

    That’s the hook. Not the surprise alone. The realization underneath the surprise that the system has depth. That there’s a grammar to what’s possible, and you can learn it.

    I’ve been building toward that feeling ever since.

    Jade Cocoon does the same thing with monsters — merge two creatures, watch the result carry both parents in its design. Dragon Quest Monsters runs on fusion too. Yu-Gi-Oh Forbidden Memories taught me that combination-as-discovery is its own mechanic, separate from any theme it wears. Everything Is Crab is the roguelike version: you absorb what you fight, you become it, you discover what you’re becoming one encounter at a time. No Man’s Sky showed me that procedural generation has finally caught up to what those PS1 games were reaching toward — creatures that feel like they emerged from a system rather than a designer’s hand.

    The mechanic isn’t genetics. Genetics is just the implementation I keep reaching for. What I’m actually trying to build is a machine that produces controlled emergence — outcomes that surprise you within a system deep enough to eventually master.

    Pure RNG is a slot machine. You can’t get better at it. Pure determinism is a calculator. You can solve it and put it down. The games I keep returning to live between those poles: consistent enough to reward learning, deep enough to keep producing novelty.

    TurboShells was an attempt at this. Turtles whose bodies expressed their genomes at render time — shell radius, leg length, color emerging from a sequence. The faster ones bred. Over generations you watched the population drift. The system had rules. The outcomes still surprised you.

    SlimeGarden chose basic shapes deliberately. If the creature is simple enough, even small variation reads as meaningful. The shape IS the information. You can see the grammar in the design.

    The version I haven’t built yet is closer to Jade Cocoon meets Dragon Quest Monsters — creatures with traceable visual lineage, combination mechanics with real strategic depth, the initial surprise and the eventual mastery running in parallel. Everything Is Crab proves the roguelike format can carry it. NMS proves the procedural layer is tractable.

    I’m still building toward it. Every system I’ve made in this space has been a step closer to understanding the grammar well enough to write it myself.

    The hook was a PS1 card game in the late nineties. The project is still open.

  • Zero Wasn’t Zero

    My design reviewer had been poking the same hole in my strategy for weeks. Small gaps, pointed out one at a time — the analytics weren’t catching traffic well, the numbers I was quoting didn’t have the resolution to support the decisions I was hanging on them. So one night I finally sat down to actually read my Google Analytics dashboard, instead of glancing at it and feeling vaguely behind. The goal was real details. Another step in the right direction.

    Eight active users for the week. Four of them from Council Bluffs, Iowa.

    I don’t know anyone in Council Bluffs, Iowa. Google does, though — it’s the site of one of their largest data centers. Half of my “users” were crawlers pinging my site and getting logged as people. So my real week was three, maybe four humans. Organic search: zero. Qualified leads: zero. Converted leads: zero.

    I run a consulting intake form on that site. Multi-step wizard, dialer platforms, pain points, contact info — the funnel’s entire bottom end. And here’s the part I have to be honest about: when the work to wire it into analytics finally started, and the agent running the directive stopped cold to report that the intake page had never loaded the analytics tag at all — not one recorded page view, ever — I wasn’t shocked. I’d been told it probably wasn’t tied in. I half knew. The stop report wasn’t a discovery. It was confirmation of a suspicion I’d been carrying around for weeks instead of spending ten minutes to check.

    That’s the actual lesson, and it’s less flattering than “I found a bug.” Some projects get real developmental commitment. My website isn’t one of them — it gets passing attention, and known holes survive a remarkably long time in projects that only get passing attention. I prefer a clean repo the way everyone prefers a clean kitchen, and like everyone, I have a room I just don’t go in.

    What surprised me wasn’t the hole. It was noticing what the zeros had been doing to me anyway. I *knew* the instrumentation was suspect — and the row of zeros under “leads” still read like a verdict every single time I glanced at it. A gauge you know is broken still lies to you, and you still flinch. “Nobody wants this” and “you never measured it” produce the exact same dashboard, and even when you suspect it’s the second one, your gut reads the first.

    The fix took one evening once it stopped being deferred: tag on the page, a `generate_lead` event on successful submission, fallback paths so analytics can never break the form itself. The funnel now reports both of its ends — views and submissions — so the two failure modes finally look different. Views without submissions means the page doesn’t convert. No views means nothing sends anyone there. Opposite problems, opposite fixes, indistinguishable until this week.

    Instrument the conversion point before you judge the funnel. And if you suspect a gauge is broken — confirm it today, because you’re going to keep reading it either way.

    Data starts now. The next zero on that dashboard will be a real one. Weirdly, I’m looking forward to it.

  • A side effect of a side effect

    In 2016 I uploaded a review of Hybrid Animals to YouTube. It got 353 views. Then I stopped.

    I was in phone sales. Still a bachelor. I liked the idea of being a content creator — it looks cool, it sounds cool — but I knew pretty quickly it wasn’t really for me. Making videos was work, and the work wasn’t interesting enough to justify itself. I wanted to play games. I didn’t want to make content about playing games.

    So I stopped.

    Ten years later I have a YouTube channel publishing daily Shorts across six different games. I didn’t change my mind about content creation. I changed what content creation costs me.

    ContentPipeline records the session, transcribes it with Whisper, identifies the moments worth keeping, generates the captions, assembles the video, and schedules the upload. I play games. The pipeline does the rest. The channel exists because I removed the friction, not because I developed a passion for it.

    The clips are a side effect of playing games. The channel is a side effect of building a pipeline. Any revenue from it would be a side effect of a side effect.

    That framing used to feel like an admission of something. Like I wasn’t taking it seriously enough. Now it feels like the honest version of what most creators won’t say.

    Most YouTube advice is about optimizing for the channel. Titles, thumbnails, posting frequency, audience retention. I don’t think about any of that. I think about whether the pipeline is producing good clips and whether the games are interesting. The channel takes care of itself.

    The goal I’d actually care about is streaming — not because of the audience but because of the engineering challenge. Building a live pipeline, managing the session, making it work technically. That’s the interesting problem. The viewers would be incidental.

    I’m not a content creator. I’m someone who plays games and built infrastructure. The YouTube channel is what the infrastructure produces.

    There’s a version of this where the channel grows, the clips find an audience, and the side effect generates real income alongside the consulting work, the games, and everything else running in parallel. That would be a quiet bonus. A small thread alongside many others.

    I’d rather be the developer who has a YouTube channel than the YouTuber who also codes.

    The pipeline makes that possible. I just play games.

  • I built the same game for 20 years without knowing it

    I want a world that doesn’t stop when I do.

    I didn’t know that’s what I wanted until recently. But it explains every project I’ve shipped for twenty years, and it started with a browser RPG I played in middle school during summer school.

    Lands of Hope is still live. You can play it today. Deep content, crafting queues, a community that made the world feel like it mattered. What hooked me wasn’t any single mechanic. It was the feeling that the world kept going without me. Things set in motion with consequences I had to wait for. Other people in it, doing things alongside me, making it real.

    I was thirteen. I didn’t have language for what I wanted. I just knew how it felt.

    TurboShells came first. Turtle racing where every turtle’s body assembled from its genome at render time — shell radius, leg length, color expressed from a genetic sequence. The turtles raced. The faster ones bred. The slower ones didn’t. Nobody played TurboShells. But I built it anyway, because something about setting a breeding pair in motion and waiting for the result felt right in a way I couldn’t explain.

    rpgCore next. A thousand tests. A proper ECS architecture. Genetics, lifecycle, dispatch — everything composable, everything persistent. SlimeGarden put it to work: breed slimes, dispatch them, see what comes back. OperatorGame pushed the dispatch loop into squad tactics. VoidDrift stripped it down to its core: drones go out, mine asteroid ore, return, station inventory updates, repeat.

    Every project had the same shape underneath. Something goes out without me watching. Time passes. Something comes back changed.

    The recognition came slowly. I was writing VoidDrift’s Scout dispatch system one night — drones leaving the station, doing their work autonomously, returning with ore — and I stopped. I’d written this before. Not something similar. This exact thing. The same send, wait, return, consequence that the breeding pairs were running. That the slimes were running. That my Lands of Hope crafting queues were running when I was thirteen.

    I opened a list of every project I’d shipped and read it from the top. The dispatch loop was in all of them. Not because I’d planned it. Because I kept arriving at the only mechanic that produced the feeling I was chasing.

    A world that goes on without you. That changes while you sleep. That has consequences whether you’re watching or not.

    ContentPipeline publishes while I’m at work. PrivyBot fires its morning briefing whether I’m awake or not. RALPH ran overnight tasks the first night I deployed it and had results waiting when I woke up. VoidDrift’s drones mine whether the screen is on.

    I haven’t been building games. I’ve been building persistent worlds.

    The surprise was that naming it didn’t feel like a limitation. It felt like a body of work.

    Scattered projects suddenly had a spine. TurboShells wasn’t a side project that went nowhere — it was iteration three on something I’ve been refining since middle school. rpgCore wasn’t over-engineering — it was building the foundation the loop deserved. VoidDrift isn’t just a mining idle game. It’s the clearest version yet of the thing I’ve been trying to make since I was thirteen.

    The struggle was that I couldn’t have named this pattern while I was inside it. Patterns are invisible to the person living them. You need the list, the distance, the moment when you stop mid-implementation and recognize the shape.

    AntColony is next. Same chassis as VoidDrift, same loop underneath — workers dispatching, foraging, returning, colony state updating without you. Different world. Same feeling.

    I know what I’m building now. I’m building worlds that don’t stop when I do.

    I’ve always been building that. I just needed twenty years to see it.

  • From Pong AI to Play Store: How a Childhood Hobby Became a Rust Game Engine

    The first game I wrote with any real ambition wasn’t a game. It was a NEAT implementation that learned to play Pong. I wasn’t trying to ship anything — I was trying to understand how a system could learn to do something I taught it.

    That question has been running in the background of everything I’ve built since.


    TurboShells came next. I took the NEAT studies from PyPong and asked: what if instead of teaching an AI to hit a ball, I bred turtles? Each turtle’s body was drawn entirely from its genes — no sprites, pure math. Shell radius, leg length, color — all expressed from a genetic sequence at render time. They raced. The faster ones bred. The slower ones didn’t.

    Nobody played TurboShells. But I learned something: the genetics loop — dispatch a breeding pair, wait for the outcome, observe the consequence — was more interesting to me than any game mechanic I’d seen. I wasn’t building a racing sim. I was building a system that made things happen without me.


    ChimeraLab was the first time I tried to give the genetics a body.

    Custom 3D creature rendering. SpineComponents — oblongs stacked together, body parts articulated from code. I got a humanoid assembled. I gave it a skeleton. I ran the simulation.

    It fell to the floor under its own weight.

    I never did fix the bipedal problem. But I got it to transition from two legs to four using a slider, and watching that happen — a creature renegotiating its relationship with gravity in real time — taught me more about 3D rendering than any tutorial I’d read. Sometimes the failure is the lesson.


    rpgCore was the foundation I should have built first. A thousand tests. Real ECS architecture. Genetics, lifecycle, dispatch — everything composable, everything verified. SlimeGarden put it to work: an astronaut crash-lands on an unusual planet and finds slimes. Breed them. Dispatch them. See what comes back.

    It sounds simple. It wasn’t. And it pointed somewhere.


    Seven projects in, I was staring at the Google Play Store submission checklist.

    OperatorGame ran on Android. Real Rust, real Bevy, real APK on a real phone. The combat worked. The UI was clean. I’d solved the hard problems.

    The submission required a 512×512 app icon, a 1024×500 feature graphic, and two screenshots.

    I didn’t have any of them.

    I could have made them. It would have taken an afternoon. But sitting there looking at that checklist, I realized the assets weren’t the problem.

    The problem was I had no audience. I was about to pay the Play Store’s attention tax — discoverability weighted toward downloads, downloads toward reviews, reviews toward players who found you somehow — with zero players behind me. I wasn’t Android Store money-ready. I was Itch.io audience-ready.

    Those are different things. Confusing them is expensive.


    Here’s what the journey looked like from the inside:

    PyPong AI taught me how systems learn. TurboShells taught me that genetics loops are more interesting than game mechanics. ChimeraLab taught me that creatures fall down and that’s instructive. rpgCore gave me the foundation. SlimeGarden gave the foundation a story. OperatorGame proved the Android pipeline. VoidDrift took the dispatch loop — Scout mines ore, returns, consequence — and dressed it in something people want to watch.

    Every project is the same loop. Something dispatches. It does its work. It returns with a result. Something changes.

    I’ve been building that loop for years. I just didn’t see it until I looked at the list.


    The lesson isn’t “don’t aim for the Play Store.”

    It’s: know what you’re ready for. The Play Store is a distribution problem you solve after you have players, not before. Itch.io is where you find out if anyone cares. If they do, the Play Store is a next step. If they don’t, you learned that cheaply instead of expensively.

    VoidDrift is on Itch right now. A small audience that keeps coming back. That’s the signal I was missing with OperatorGame.

    When the audience is real, the Play Store assets take an afternoon.


    There’s a story that keeps circling my mind. Someone in a ship, traveling through a black hole, becoming something else. They find a station. What follows is a macabre exploration of self — what survived the transit, what didn’t, what the new thing is capable of.

    VoidDrift is the ship and the void. SlimeGarden is the crash-landing after.

    The loop doesn’t end at the Play Store. It ends when the story does.

    The Scout dispatch loop in VoidDrift is the same loop TurboShells was running — breed, wait, observe — dressed in space mining clothes, nine projects later. Phase 5 is live. The Play Store listing is three PNGs away.

    The story is still circling. I’m still building toward it.