People ask about my stack a lot. Usually they're trying to figure out if I'm "modern" enough or if I use their preferred framework. Here's the honest answer: I pick boring tools that work and exciting tools only when they're actually better.
Frontend
Next.js with TypeScript. I've been on Next.js since version 12 and it keeps getting better. The App Router is mature now. Server components are genuinely useful for performance. TypeScript is non-negotiable — every project, every time. The type safety alone has caught hundreds of bugs before they ship.
Tailwind CSS. I resisted this for a long time. Thought it was ugly and cluttered. I was wrong. Once you're used to it, you move incredibly fast. No more naming CSS classes. No more "where did I put that style" debugging. Version 4 with the new engine is even better.
Backend
Supabase or plain Postgres depending on the project. If I need auth, storage, and a database quickly, Supabase is hard to beat. For projects that need more control, I go with a Postgres database and build the API layer ourselves.
Vercel for hosting. Deploying is a git push. Preview deployments for every PR. Edge functions when you need them. The developer experience is the best in the industry and it's not close.
AI and tools
Claude and GPT APIs depending on the use case. Claude is better for long-form reasoning and code generation. GPT is better for certain structured output tasks. I use both and pick per feature.
Resend for email. Simple API, good deliverability, nice developer experience. I switched from SendGrid and never looked back.
What I don't use
I don't use Kubernetes. Kubernetes solves real orchestration problems — multiple services, high availability across nodes, auto-scaling under variable load. But those problems almost never appear when you're building client products at our scale. The operational cost is high: cluster management, networking, RBAC, monitoring, secret management. That overhead is justified at scale. It's not justified when Vercel handles deployment, scaling, and edge distribution with a git push. Most applications we build will live and die without ever needing container orchestration.
I don't use microservices unless the project genuinely needs them. Microservices make sense when you have multiple teams that need to deploy independently, or services with very different scaling requirements. For most client projects — a single product with a small team — a well-structured monolith is faster to build, easier to debug, and simpler to deploy. The coordination overhead of microservices isn't worth it until you've outgrown the monolith.
I don't use GraphQL unless the client specifically requires it. GraphQL is great when you have many different clients consuming the same API in different ways — mobile apps, web apps, third-party integrations all needing different data shapes. For most of our projects, REST with well-designed endpoints is simpler, easier to cache, and doesn't require the extra tooling layer. We don't chase new frameworks.
The goal isn't to have the most impressive stack. It's to ship reliable software fast. Every tool I use earns its spot by making us faster or our products more reliable. Nothing gets in because it's trendy.
