A tech stack is the collection of tools, platforms, and services your app is built on — where your code runs, what database you use, how you handle auth, where files live, how email gets sent. Early choices create inertia. Migrating databases or switching hosting platforms later is painful, so getting the foundational choices reasonably right matters. If Cartara flagged this in your diff, you likely introduced a tool or dependency that conflicts with your existing stack or adds unnecessary complexity.
The meta-principle: choose boring, well-supported tools
The best stack for a builder is not the most technically impressive one. It's the one with the most tutorials, community answers, and documentation; the best AI assistant support; and the lowest operational overhead.
When in doubt, choose the option with more Google results. Obscure tools have thin communities and poor AI assistant knowledge, which slows you down exactly when you're trying to move fast.
The modern founder stack
A sensible starting point for most web apps:
| Layer | Recommended | Why |
|---|---|---|
| Frontend framework | Next.js | Most popular React framework, huge ecosystem, excellent Vercel integration |
| Hosting | Vercel | Zero-config deploys, preview URLs, edge functions |
| Database | Supabase (Postgres) | Postgres + auth + storage + realtime in one place |
| Auth | Supabase Auth or Clerk | Supabase: free and integrated; Clerk: better UX, worth paying for |
| File storage | Supabase Storage or Cloudflare R2 | Supabase: simplest if already using it; R2: cheapest egress |
| Resend | Developer-friendly, generous free tier | |
| Payments | Stripe | Industry standard, best documentation |
| Background jobs | Inngest or Trigger.dev | Serverless-native, handles retries and scheduling |
| AI/LLM | Vercel AI SDK + Anthropic/OpenAI | Handles streaming, tool use, multi-provider |
This stack gets you production-ready infrastructure in days. It handles auth, database, storage, email, and payments without running a single server yourself.
Frontend framework decisions
Next.js is the default for most web apps. Server-side rendering, API routes, excellent performance, and first-class Vercel integration. Works for everything from landing pages to complex apps.
Alternatives worth knowing:
- SvelteKit — smaller, faster, simpler, but smaller ecosystem
- Remix — excellent for full-stack, strong opinions about data loading
- Plain React (Vite) — for single-page apps that don't need server-side rendering
Avoid: older tooling (Create React App), custom Webpack configs, or anything where "how do I do X" doesn't have a clear current answer.
Hosting decisions
Vercel for frontend and full-stack Next.js. Zero configuration, CI/CD built in, preview deployments on every pull request.
Alternatives:
- Netlify — similar to Vercel, more flexible for non-Next.js
- Railway — excellent for backend services and Docker containers
- Render — good all-rounder with a free tier
- Fly.io — for more control over containerized apps
Avoid managing your own servers (VMs on AWS/GCP/Azure) until you have a specific reason. See Cloud Provider Overview.
Database decisions
Supabase (Postgres) for most apps. You get a managed Postgres database, auto-generated REST and GraphQL APIs, realtime subscriptions, row-level security, and a built-in dashboard — all in one.
Alternatives:
- PlanetScale (MySQL) — excellent DX, schema branching, strong at high scale
- Neon — serverless Postgres that scales to zero, good for low-traffic apps
- Firebase/Firestore — document database, good for realtime and mobile-first apps; less flexible for complex queries
Avoid MongoDB as a default choice. Postgres handles JSON natively and is more flexible for the kinds of queries apps actually need.
Authentication decisions
Supabase Auth if you're already using Supabase — free, integrated, handles email/password, OAuth (Google, GitHub), magic links.
Clerk if you want a better out-of-the-box experience — beautiful pre-built components, excellent developer experience, more flexible. Worth paying for in most products.
Never build your own auth. Password hashing, session management, and security edge cases are too complex to get right from scratch.
Payments, email, and other services
Stripe for payments — best documentation, best integrations, handles subscriptions, one-time payments, and invoicing. Lemon Squeezy is a simpler alternative that acts as merchant of record (handles VAT/tax complexity automatically).
Resend for transactional email — clean API, React Email for templates, excellent deliverability. For marketing email, add Mailchimp, Kit, or Loops separately.
What You'll See in Your Code
Cartara often flags library choices that duplicate functionality already in your stack:
// If you're already on Supabase, this is redundant:
import { PrismaClient } from '@prisma/client'
import { createClient } from '@supabase/supabase-js'
// Running two separate database clients adds complexity for no benefit
// Better: use one consistently
import { createClient } from '@supabase/supabase-js'
// Or use Prisma with your Supabase Postgres connection string — not both simultaneouslyA common pattern with good stack discipline:
// supabase.ts — one client, used throughout the app
import { createClient } from '@supabase/supabase-js'
export const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
// auth handled by Supabase, not a custom implementation
export async function signIn(email: string, password: string) {
return supabase.auth.signInWithPassword({ email, password })
}Decisions to avoid early
TypeScript vs JavaScript: Use TypeScript from day one. The type safety pays off quickly and virtually all modern tooling assumes it.
Monorepo vs multiple repos: Start with a single repo. Monorepos add tooling complexity that isn't worth it until you have multiple distinct products or large teams.
Microservices vs monolith: Start with a monolith. Microservices are a solution to organizational and scaling problems you almost certainly don't have yet.
Custom infrastructure: Unless you have a pressing specific reason, don't run your own servers, Kubernetes clusters, or databases. The operational overhead is significant and the managed alternatives are excellent.
The "boring" vs "shiny" tension
New tools and frameworks emerge constantly. Newer tools have thinner communities, worse AI assistant support, and more sharp edges. A useful heuristic: if a tool is less than two years old and doesn't have tens of thousands of GitHub stars, it's probably not production-ready for a small team. Let others find the sharp edges first.
The exception: purpose-built AI tooling (agents, vector databases) where newer tools are sometimes genuinely best-in-class because the space didn't exist two years ago.