Building with AI · Part 1

Building the Wrong Thing, On Purpose

Posted November 30, 2025

Fifteen months ago I made the first commit of what has turned into a small fleet of applications sharing one template. Looking back at the trail from here, it reads like a plan. It wasn't. It was building the wrong thing, learning from it, and building the next thing slightly less wrong. Since the fleet just survived its first runtime migration in one sitting, this feels like the right moment to write down how it got here.

The first commit was PowerShell

In August 2024 I was just a DBA who wanted to work more on the application side of things. I had picked up JavaScript long ago, but hadn't touched it in years. I didn't know React or any other modern frontend frameworks. The last web application/SaaS I worked on regularly was in the iHTML/ColdFusion/PHP/Perl CGI era ('97-'05) and things had moved on. A lot.

I knew PowerShell, though, because I used it every day to keep SQL Server estates alive. So the first commit was a PowerShell web server - Pode - with htmx for interactivity and Tailwind for styling. 78 commits later, I had something. It wasn't pretty, but it was a start.

Starting with what you know gets you further than waiting to learn the "right" tool. I stand by that. The site was clunky and the paradigm was limiting, but it shipped, and the patterns it forced me to invent (route handlers, partial rendering, a data layer kept separate from the presentation layer) seeded everything after.

By September I'd extracted those patterns into Podex, a reusable Pode+htmx framework, and shipped a browser extension (htmx-debugger, Chrome and Firefox, seven releases in three weeks) to prove I could put real software in front of real users. Google's extension review rejected it repeatedly until I'd stripped every permission I couldn't justify. An involuntary education in permission minimization.

The one decision that keeps paying rent

By October 2024, I'd started work on Deeper, a SQL Server tool I'd been dreaming of for a while, as my first real product attempt. 67 commits of Pode + htmx + JWT auth + Docker. The UI wasn't pretty. The architecture contained what I now think is the most load-bearing decision I've made in this whole run:

Collection and presentation are separate concerns. The PowerShell thing that talks to SQL Server is not the thing that serves the web UI.

Thirteen months later, that collector is still running, unchanged, while everything above it has been reworked, re-platformed, and experimented on more than once.

Good architecture is the part you don't have to rewrite.

Finding the ceiling by leaning on it

2025 was the year of wearing the paradigm out on purpose. Heystack, a file-monitoring app, was the fair test: CRUD, scheduled scans, dashboards. It passed, up to a point. Simple views were pleasant. But the moment I needed what a DBA actually needs - multi-panel dashboards, drill-downs, live metrics, filtering across dozens of columns - htmx fought back. Every interaction that would be a few lines of React state became a careful arrangement of swap targets and DOM IDs.

So in May I ran the fairest test I could construct: TodoMVC on Pode + htmx. Spec-compliant, 39 commits, accessibility and all. It worked. And my notes from that day say it plainly: the code worked, but it wasn't simple. Proving the paradigm was capable proved, by the effort it took, that it was the wrong paradigm. I knew I didn't want to continue down that path, but wasn't sure which way to turn.

Bringing out the machete

Two days later I started a project on Supabase for a hackathon. The point of this one was particularly focused on AI-assisted development which I hadn't really explored before outside of auto-complete features in my IDE.

The Supabase era got out of hand fast. My first project idea, Idiomate did 174 commits in a week, 93 of them on June 1 alone while my second, astrid.chat, did 423 commits in four weeks: multi-model AI chat streaming GPT-4, Claude, Gemini, and Grok in parallel. This felt like the bottleneck had moved from "how do I build this?" to "what should I build next?" It turns out that was a cute assumption on my part, once I started looking under the covers. I mean it worked pretty well but AI is not going to be replacing me anytime soon.

It also delivered the period's most instructive pain: debugging Supabase row-level security, where a policy rejection and genuinely-absent data both return the same silent zero rows. I lost hours to JWT claim mismatches that showed up as empty results, and came out of it with a durable preference for auth simple enough to debug - JWT in HTTP-only cookies, no third-party relay. That went straight into the template later.

These apps weren't the goal, they were just practice and a learning experience. I learned that Supabase is not the right fit for me.

Continuing this pattern of learning through building, I moved on to Convex for a few weeks (mostly because of Theo), building three proof-of-concept apps to test the waters.

After those, I built KeyStrike, a competitive multiplayer typing game. First commit July 30, v1.0 in production August 7. Eight days. That was THE turning point: React clicked in a way htmx never had. The meta-lesson mattered more than the framework: use technologies the way they were designed to work together. Convex had felt awkward strapped to htmx and effortless under React, because one of those pairings was fighting its own design.

In August, I scaffolded eight throwaway projects in one day - every permutation of React + Hono/Express + Convex/self-hosted - to settle the stack question for good. The answer: React frontend, lightweight self-hosted backend, SQLite. Eight throwaway projects cost far less than committing to the wrong stack would have.

Spernakit: extract from reality

By mid-September I had rebuilt the same auth, user management, and CRUD boilerplate three times in one week (OttoBoard, RePortal, SkedMan) and got fed up. On September 22 I extracted the pattern into Spernakit - SQLite, Prisma, Express, React, Node - a full-stack template with auth, CRUD scaffolding, and security hardening out of the box.

The template philosophy formed there and hasn't budged. I built the same thing three times, got frustrated, and extracted the pattern.

October was the peak so far: twelve releases, five derived apps, each one finding sharp edges that got smoothed in the next release. And two weeks ago the whole fleet migrated from Node to Bun in a single session. The runtime wasn't the interesting part. The interesting part was that a template change propagated mechanically to six applications. The template pattern holds at fleet scale.

It's also visibly done, or close to it. Every v1 technology choice (Express, Prisma, Winston, DaisyUI) was made for familiarity, and at v1.8.0 the accumulated friction says so. Express middleware that doesn't compose. Prisma's codegen overhead. Winston's heavy API. I can feel a rewrite coming, and this time I'd choose for fit.

Where this leaves me

Fifteen months in, here's the rub: a fleet generates more well-defined work than one person can type. The backlogs are specific, the template makes the work mechanical, and my typing speed is now the bottleneck. If a template change can propagate mechanically to six apps, maybe a backlog can be worked mechanically too. AI is getting more compelling, and unavoidable, but it's still very rough around the edges and requires a lot of hand-holding. I'm considering ways to keep them in line.

We'll see. It's not getting any shorter.