The foundation of your application is everything, especially when you use agents to write your code.
Everyone talks about garbage in/garbage out with AI and machine learning, but no one really talks about what that means when you hand an LLM an entire codebase and tell it to start building. LLMs are basically just billion dollar pattern matching black boxes. If you give them a well-understood stack with established patterns, lots of documentation, tons of examples, and clear architectural boundaries, they can produce some genuinely amazing results.
If you start with nothing, or worse, start with garbage, they tend to produce garbage.
Yes, Opus 5 and GPT 5.6 Sol produce amazing output. Just take a look at X as a tech enthusiast for any amount of time.
But I don't really want my entire development process to depend on the assumption that I can throw infinite tokens at every problem forever.
I want something I understand, something that I can code manually if I so desire, and something that has amazing and widespread support instead of a custom or semi-custom solution. Plus with the recent talks about massive AI costs - while I don't think my coding agent is going away - it may turn from a token shotgun of coding literally everything I do into more of a surgical tool for tasks I don't really want to do myself.
My job as a developer moving forward is to design a box where the agent will make good decisions with minimal input.
This means choosing something I understand, ideally something popular and well suited to my use case, something that I can deploy quickly, scale easily, and something with minimal devops overhead. I should be able to look at the stack a year from now after the agent produced another 30k lines of code and still be able to read and understand every single line of it.
I'm not going to tell you this is the best stack, but I am going to walk you through how I choose my stacks for each project, what my logic is behind the decision, and why I think its the best option, especially for a solo developer or small team.
What am I building?
The app itself is called lyphe, an opinionated task and life management app that I'm primarily building because I want something that works the way my brain does. At its core it's still a relatively simple consumer CRUD app - tasks go in, tasks get organized, tasks hopefully get completed - but there are a few requirements that make the architecture more interesting. I want iterations for the initial prototype phase to be as fast as possible, so I'm using it as a PWA while I build out features and the UX. I want updates to feel realtime, I eventually want native iOS and Android apps, and native functionality like notifications and widgets is important enough that I don't want mobile to just be an afterthought. I'm also building this mostly by myself with coding agents doing a frankly irresponsible percentage of the implementation work, so whatever stack I choose needs to be something both the agents and I can work with effectively.
That gives us some pretty useful constraints.
Less infra, fewer problems
At my previous job, one of the core principles the CTO and I agreed on is that less is more when it comes to infrastructure. We were a small team of only 4 devs (including the CTO), if we could automate or outsource the infrastructure, we did. It was a crypto startup so Linux servers running Avalanche nodes were inevitable, but our APIs ran on Cloudflare Workers, our database on Supabase, and our NextJS app ran on Vercel. If it could be outsourced, it was.
If you can pay someone to handle your scaling and deployment, especially as a small team or solo dev, you do it.
While this doesn't apply to every product you are building, for example at my current job we build enterprise B2B software with required SOC2 compliance and optional on-prem deployments, its a safe bet when you are building the app for yourself or as a consumer facing product.
Because of that I've become incredibly fond of platforms like Supabase and Convex.
Convex specifically has been a recent favorite of mine, being the perfect combination of NoSQL and structured data. Data structures and tables are defined in Typescript, which are then automatically converted into an API your frontend app can instantly use.
And its not just a normal CRUD API either - its realtime.
So if you are displaying some of the data using the hooks that Convex generates for you, and the data gets changed on the backend, it gets instantly updated on your frontend. All of that for for just using Convex in my app?
Sign me up!!

Source: Stackhawk
There's another advantage here when you're developing with agents: Convex dramatically reduces the number of architectural decisions the agent actually needs to make.
You write your schema in Typescript. Your backend functions are Typescript. It outputs frontend facing API interfaces in - you guessed it, Typescript. And it handles migrations automatically for you.
That reduces what I have to think about, and more importantly, what my agent has to reason about. The opinions that Convex forces on both myself and my agent force us both to simply use it within the rules that it defined, keeping both of our velocities high, and reducing the chances that the agent goes off and decides that it wants to reinvent the REST API.
Authentication is scary
Convex led me into learning about Clerk.
Clerk is an authentication provider very similar to Auth0 and Stytch, however Clerk has a few tricks up its sleeve that made it ideal for a solo developer such as myself.
They are free for your first 50,000 users, which hey if you can't make any money after having 50k users what the hell are you doing?
Plus they offer a billing service via Stripe, which allows you to manage user subscriptions, app features, and billing directly from the Clerk dashboard. This means that you don't need to mess with the Stripe API, just call Clerk and see if the user is paying to gate features. Easy!
Finally, and the main reason I chose them, they have super tight integration with Convex, especially since I actually discovered that Clerk existed while reading the Convex docs on how to integrate my app with some form of authentication provider.
I'm not a big fan of handling passwords.
That's just one more security hole that I have to worry about in the age of cybersecurity breaches.
Could I build authentication myself?
Sure.
Could an agent build authentication for me?
Absolutely.
Do I want either of us to be responsible for getting authentication right when a company whose entire product is authentication will happily do it for me?
Not particularly.
And because Clerk and Convex already have tight integration, that's even code for the agent and I to maintain.
Just use something you know
For a frontend framework, I always default to React or one of its many companion frameworks. I spent 4 years working with NextJS on Vercel at a crypto startup, a stack I was a massive fan of. Automatic deployments and preview links out of the box, with auto scaling since it was serverless. Complete devops win. However since leaving, I've gravitated towards Cloudflare as my primary serverless hosting provider (something I did a bit there as well since I maintained massive serverless Workers-based API). NextJS has a few limitations when running outside of Vercel or a pure NodeJS environment, which is why it was forked into OpenNext. Its a more portable and feature compatible version of NextJS that can be deployed to Cloudflare, Netlify, and AWS Lambda. It uses Cloudflare Workers as its compute method, allowing for both static and SSR pages. OpenNext on Cloudflare would be my frontend framework.
Just use something everyone uses
Ok, that's the database, CRUD API, authentication, frontend framework, and billing already handled. Now we just need some components. The choice a no brainer - use the most popular one. Of course that's shadcn - the current king of component ecosystems. Now I could be boring and simply style the existing components, there's also a plethora of compatible libraries I can use to improve both user experience and animations of the app with zero effort. A good example of this is animate-ui, which I will be making liberal use of throughout this app and the next as it acts as a fully drop-in replacement for many shadcn components, while adding subtile animations that make your app feel unique and premium.
AI makes it cheaper, not free
Finally, the app I'm building will eventually be a mobile app. I don't want to completely rewrite it from scratch, I'm just a guy with an AI agent! Even if I can have agents build everything with vibes, I don't really want to maintain AI generated spaghetti long term.
Yes, agents make rewriting and maintaining large swaths of code cheaper. If I really wanted to, I could have an agent rewrite this entire app in React Native, Flutter, Swift, or Kotlin.
But then I have two repos to maintain. That's more things on my plate I have to handle, more things I have to think about. When a bugs can exist on mobile, web, or both, features need to be ported for parity. Too much I have to deal with.
I'd rather have a single codebase for both my web and mobile apps, in a language that I'm deeply familiar, with a stack that I chose. So that leaves me with two real choices for the mobile port: Capacitor and Tauri.
Capacitor vs Tauri
I'm a massive fan of Tauri. Its what Electron should've been, a super minimal runtime that uses your OS's native webview capabilities combined with a compiled Rust backend for lightning fast native interactions. I've built a few Tauri apps, including recently an improved system metrics analyzer for macOS I call computer-state. My favorite speech to text app, Handy, is also built with Tauri. And with the release of Tauri 2 back in 2024, it officially supports iOS and Android as deployment targets. However, there is a problem, stack maturity. Even though it's been two years, there's not a lot of plugins, documentation, or information on how to develop with Tauri on Mobile effectively. Most packages, articles, and information you find online still primarily target desktop apps, which great when that's what you need. But I want something mature, something that I can find tons of documentation and plugin support for. So I'm going with Capacitor.
Native Function, Web Stack
Capacitor is a rewrite of the old Apache Cordova system for mobile applications. While it's conceptually similar, Capacitor is better built for handling native Swift and Kotlin integrations for building your own plugins or using existing plugins to extend your web view app into native functionality. This is very important to me because one of the core ideas for building this app is that I want widgets to keep me on track and constantly remind me of what needs done. You can't build widgets with React Native or a pure web-based application. You can prototype them using Scriptable for iOS, but we can talk about that another day. Here's an example of the scriptable prototype I made.
And while I haven't started Capacitor integration yet, when it does come time to do this, most of the work can probably be handled by the agent itself with some strict guidance from my part, as a lot of the system integrations as well as widget creation is both well documented and will have plenty of example code to go off of. And because this can simply be a port of the OpenNext app, with some minor changes as certain pages are SSR, it will look identical to what it does on the web with all of the same functionality.
Outsource infra, own orchestration
I mentioned that I'm using Cloudflare Workers to deploy the OpenNext part of the app, however I'm not using Cloudflare's own build system. For this app, I decided to give myself some more control and agency in the future by going with GitHub Actions. This is so that we build and deploy everything in a single place: OpenNext, Convex, and (eventually) the mobile ports.


Top comments (0)