← Back to posts

3,704 Commits Later: From create-next-app to Production as a Solo Dev

· 10 min read

The Commit That Started Everything

On March 11, 2025, I ran create-next-app and pushed the result. The commit message was exactly what you’d expect: “Initial commit from Create Next App.” The second commit added CDK. The third added ElectroDB. Three commits in, and the skeleton of what would become a multi-portal utility marketplace was already taking shape - even if I didn’t fully know it yet.

Fourteen months later, on May 4, 2026, the platform went live. Between those two dates: 3,704 commits, 99% of them mine. The other 1% split between a Cursor agent (13 commits), an OpenCode assistant (6), some Nx Cloud bot noise, and a Tessl bot. This is the story of what that journey actually looked like.

The Shape of the Thing

The product is a marketplace that connects companies needing utility infrastructure work with accredited contractors who can deliver it. Think of it as the connective tissue between “we need gas pipes installed” and “we’re certified to install gas pipes.” The platform handles project submissions, contractor matching, quoting, contract signing, job tracking, and payment reconciliation.

That translates to five distinct web portals: an admin portal for internal staff, a developer portal for companies submitting work, a partner portal for contractors, an ops portal for operational tooling, and a marketing hub. Each has its own auth flows, its own data model concerns, and its own user expectations. It’s not one app. It’s five apps sharing a backend.

The Monthly Heartbeat

The commit history tells its own story:

PeriodCommitsWhat was happening
Mar-Jun 202547Exploring. Next.js, CDK, basic data models. Slow, deliberate.
Jul 202515The auth provider roundtrip. Cognito to WorkOS, back to Cognito.
Aug 2025109Explosion. Monorepo tooling (Turbo then Nx, same day). Cursor AI enters.
Sep-Nov 2025474Sustained build. Cycled through AI tools. Core features taking shape.
Dec 2025163Backend hardening. DynamoDB patterns solidifying.
Jan 2026458Something clicked. Velocity doubled.
Feb 2026309Self-hosted runners. Infrastructure maturing.
Mar 2026742Rust lambdas written and torn out. The sprint begins.
Apr 20261,145The final push. 38 commits per day average.
May 1-6242Launch and immediate post-launch.

That April number is insane. 1,145 commits in 30 days. I was averaging 38 commits a day, and that’s not gaming the count with atomic commits for vanity metrics. That’s real work - features, fixes, infrastructure, CI pipeline fixes, more CI pipeline fixes, and the occasional “why did I break this” revert.

The Architecture That Survived

The stack at launch looks nothing like what I started with. Almost every major technical decision was revisited at least once:

Frontend: Started with Next.js, ended with React + Vite across all five portals with Mantine UI. The SSR story for Next.js didn’t justify its complexity for what are essentially authenticated SPAs behind login walls.

Auth: Cognito, then WorkOS, then back to Cognito. The WorkOS detour taught me what I actually needed from an auth provider, which turned out to be “less than I thought.” I’ll write that story up properly - it’s a good lesson in over-engineering.

Monorepo: pnpm workspaces, then briefly Turbo, then Nx (on the same day as the Turbo attempt), then back to Turborepo eight months later. Nx is powerful but the configuration surface area was enormous. Turbo’s simplicity won out, especially once I got the remote cache working and sorted out the BODE pattern.

Backend: AWS CDK from day two. Lambda functions on Node.js 22, DynamoDB single-table design, EventBridge for async workflows. This is the part that barely changed. CDK had its sharp edges - the CloudFormation export lock incident cost me a day - but the core bet on serverless was correct for a solo developer. No servers to manage means no 3am pages.

The Rust detour: In March 2026, we wrote six Lambda functions in Rust. I decided they were solving a problem I didn’t have, and we rewrote them all in TypeScript within three weeks. Classic premature optimisation dressed up as “doing it right.”

CI/CD: From manual deploys to fully automated continuous delivery, including self-hosted GitHub runners on AWS. The runner infrastructure alone was a significant sub-project. Spot instances, auto-scaling groups, AMI pre-baking, OIDC authentication across 8 AWS accounts managed by org-formation. The CI story is really three stories: making it work, making it fast, and making it reliable.

The ops surprise: The most unexpected piece was the AI-powered ops portal. An agent with persistent memory backed by Bedrock (Claude Haiku) and LanceDB for vector search, connected to WorkMail for email handling. It started as an experiment and became genuinely useful for operational tasks. Event-driven audit logging feeds it a stream of everything happening in the system.

The AI Tools Question

I’ve used AI coding tools for the entire build. Cursor from August 2025. Then a parade of alternatives - Kiro, OpenSpec, OpenCode, BMAD - each promising something slightly different, each falling short in its own way. I’ll write the full comparison separately. Where I landed: Claude Code with a carefully curated set of workflow skills and Tessl for library management.

Here’s what I’ve learned about AI-assisted development over 14 months:

It doesn’t replace thinking. Every time I let the AI drive without clear direction, I got code that looked right and was subtly wrong. The auth provider roundtrip? Partly caused by trusting an AI recommendation without interrogating the reasoning. The Rust detour? Same pattern. “This is a Lambda function, you should write it in Rust for performance” sounds smart until you realise your Lambda processes 12 requests per minute and the CI penalty of compiling Rust on every build costs more than the execution time you save.

It’s transformative for the boring middle. The gap between “I know exactly what this should do” and “it’s done and tested” is where AI shines. Boilerplate. Migrations. Test scaffolding. CRUD endpoints where the pattern is established and you’re just varying the entity. I could not have maintained this velocity alone. 3,667 commits from one person in 14 months is not normal human output.

The workflow matters more than the model. The jump from “use AI to autocomplete code” to “use AI agents in worktrees with structured task management” was bigger than any model upgrade. Having agents that understand your codebase conventions, that check their own work against acceptance criteria, that operate in isolated git worktrees so they can’t corrupt your main branch - that’s the real multiplier. The model is table stakes. The workflow around it is the edge.

Trust is earned through automation, not vigilance. Early on, I reviewed every line before committing. That doesn’t scale. What scales is investing in automated testing and CI/CD that catches problems before they reach production. Once you have a pipeline you trust, you can let the AI move faster and focus your review time on the things that matter: architecture decisions, security boundaries, and the occasional “why does this exist?” moment. The goal isn’t to read every diff. It’s to build a system where you don’t have to.

The False Starts

Honesty time. Not everything was a clean arc from problem to solution:

  • WorkOS (Jul 2025): Migrated to it. Migrated back within a month. Cost: ~2 weeks of total effort.
  • Nx (Aug 2025 - Apr 2026): Eight months. It worked, but the configuration complexity was a constant tax. Every new package meant 15 minutes of boilerplate.
  • Rust Lambdas (Mar 2026): Three weeks to build, three weeks to replace. Net value: I learned some Rust.
  • eSignatures.io (launched with it, replaced Apr 30): The contract signing service worked until it didn’t. Replaced with an in-house signing ceremony four days before launch. That was a fun weekend.
  • Three different AI workflow tools (Sep-Nov 2025): Kiro, OpenSpec, BMAD. Each installed, evaluated, and discarded. The pattern that worked was building custom skills on top of a capable base model, not adopting someone else’s opinionated framework.

Each of these felt like wasted time in the moment. In retrospect, they were all necessary for understanding what the right solution actually looked like. You can’t evaluate alternatives you haven’t tried.

The Final Sprint

April 2026 was a different kind of month. 1,145 commits. The commit messages tell the story: feature flags going in, smoke tests being written, CD pipelines being hardened, edge cases being found and fixed, that CloudFormation export lock that blocked a deploy for a day. The last two weeks before launch were the most focused engineering work I’ve ever done.

The thing that made it possible was the accumulated infrastructure. By April, the monorepo was clean. CI was fast. Deploys were automated. Feature flags via GrowthBook meant I could ship incomplete work without risking the live system. The investment in infrastructure wasn’t paying dividends before - it was paying them now, all at once, when velocity mattered most.

On May 4, production went live. The deploy was unremarkable. Merge to main, staging auto-deploy, smoke tests pass, production promote. Exactly like the hundreds of deploys before it, except this time real users would see it.

What I’d Tell Someone Starting This

If you’re considering building a multi-tenant SaaS as a solo developer:

Invest in CI/CD early. I wish I’d built the CD pipeline in month 3 instead of month 12. Every month of manual deploys was a month of accumulated friction and deployment anxiety. Automated deploys aren’t a luxury - they’re what let you ship 38 commits a day without losing your mind.

Single-table DynamoDB is worth the learning curve. The access pattern thinking it forces on you pays off enormously. No migrations. No connection pool management. Predictable costs. It’s not right for everything, but for a multi-tenant SaaS with well-defined access patterns, it’s ideal.

Feature flags from day one. I added GrowthBook late. Every feature shipped before flags was a feature shipped with a prayer. Now nothing user-facing goes out without a flag. The peace of mind is worth more than the implementation cost.

Don’t optimize prematurely, in any dimension. Not performance (Rust lambdas). Not abstraction (Nx’s project graph for 8 packages). Not auth features (WorkOS’s enterprise SSO for a product with zero enterprise customers). Solve the problem you have today with the simplest thing that works.

AI tools are a force multiplier, not a replacement. They multiplied my output by maybe 3-5x on good days. They also introduced bugs I wouldn’t have written myself. The net is strongly positive, but only because I maintained the discipline to review everything and understand the system deeply enough to catch the subtle mistakes.

3,704 Commits Later

The platform is live. Real companies are submitting real projects. Real contractors are quoting on real work. The system I built processes actual transactions in a regulated industry.

It’s not done. Software is never done. But the gap between “Initial commit from Create Next App” and “production system handling real business operations” has been closed. Fourteen months, one developer, a lot of AI assistance, and more wrong turns than right ones.

The next post in this series will be about the auth provider roundtrip - the full story of why I moved to WorkOS, what I learned there, and why I moved back to Cognito. It’s a good case study in how “better” isn’t always better when you factor in integration complexity and actual requirements.

For now, I’m going to enjoy the quiet satisfaction of a production deploy that just works.