The Minimal Full-Stack Setup I Use for Every New Project
After building a lot of projects, I have settled on a setup that lets me move fast without accumulating technical debt. Here is exactly what it looks like and why.
Every new project is a fresh opportunity to over-engineer things. I have been guilty of this. Now I default to the smallest setup that can actually ship, and add complexity only when I hit a real constraint.
The stack
Framework: Next.js App Router. Database: Postgres via Neon or Supabase. Auth: Clerk or NextAuth. Deployment: Vercel. That is it.
I reach for this combination because:
- Zero infrastructure to provision — everything is managed
- Instant preview deployments on every PR
- Postgres covers 95% of data modeling needs
- Type safety end-to-end with TypeScript + Zod
Project structure
I keep the structure flat and boring. Feature-based directories when the project grows, but never before:
src/
app/ # Routes only — thin pages
components/ # UI, shared across features
lib/ # Services, utilities, types
config/ # Static config (site, navigation)Data fetching rules
Server Components fetch data directly. Client Components get data as props. API routes only for webhooks and mutation endpoints. No useEffect for fetching.
What I skip
No Redux. No React Query (server components make it unnecessary for most cases). No Prisma for simple projects (direct SQL with postgres.js or Drizzle). No Docker locally (use the managed service's dev plan instead).
The rule
Before adding any dependency or abstraction, I ask: what specific problem am I solving right now, not eventually? Most of the time, the answer is nothing. The project ships without it.
Speed comes from simplicity, not from tooling. The best stack for a new project is the one you understand completely and can debug at 2am.