Eighteen months of building under one roof with two people has turned our stack into a set of defaults we'd have to be convinced out of. Here is what we reach for by default in 2026, and, more usefully, what we used to use and stopped.
The current default stack
- Next.js with the App Router. Turbopack in dev, Vercel or Cloudflare in prod depending on edge needs. We have not shipped a marketing or product site on anything else in nine months.
- Tailwind v4 plus shadcn/ui. The design system is our own, built on shadcn primitives. Writing CSS from scratch is a sign we scoped something wrong.
- TypeScript everywhere, strict mode, no exceptions. A repo without strict TypeScript starts rotting in week two.
- Postgres. Usually Supabase, sometimes Neon. We lean Supabase when auth and storage should land in the same product, Neon when branching and autoscaling matter more.
- Drizzle for the ORM. We miss Prisma's developer ergonomics on some days. We do not miss its runtime behaviour on any day.
- TanStack Query plus URL-derived state. Zustand or Jotai only when a real client-state problem earns its weight.
- Clerk or Supabase Auth. Depends on the shape of the product. Anything custom for auth is a red flag we push back on.
- Resend for transactional email. PostHog for analytics and feature flags. Both passed the one-year smell test.
- MDX for marketing content. Sanity for any editorial team bigger than the founder.
What we used to use and stopped
Prisma. We shipped four projects on it before switching to Drizzle. The developer experience is warmer, but the runtime behaviour, schema drift handling, and migration story had one too many bad nights. Switching wasn't cheap and we would do it again.
Zustand-everywhere. In the first year we reached for Zustand almost reflexively. Most of what we stored in it was server state, which belongs in TanStack Query, or URL state, which belongs in the URL. We now refuse client stores until we've proven we need one.
Chakra, then MUI, then Chakra again, then shadcn. The component library tourism ended when we realised the components we wanted were a handful of primitives plus our own design tokens, and shadcn plus a small internal library covers it.
Our own auth. We built auth ourselves on one project in 2024. It worked. It was not worth the six weeks of attention and the ongoing security surface. We will not do it again.
Vercel-everywhere. Excellent default; not always the right one. For sites with heavy regional traffic or heavy websocket workloads we now default to Cloudflare or, for India-heavy products, a region-matched provider.
Notion-as-CMS. Fast to prototype with, expensive to keep running in production. Every engagement that started on Notion migrated off inside four months. We now skip the migration.
The rule underneath the list
The rule: every piece of the stack earns its place by surviving a bad week. If it broke something we couldn't fix quickly the first time, we looked for a replacement. If the replacement also broke something, we went back. Two negative experiences, not one, are the signal.
This is not a stack to copy. It is a stack with reasons. The reasons are worth more than the list.
Heuristics
- Default stack, deviation with evidence. A studio without a default has no experience; a studio that never deviates has no honesty.
- Every piece of the stack gets one bad week to justify itself. Two and we replace it.
- The most expensive thing in the stack is the thing you built yourself for a problem already solved. Auth is the canonical example.
If the stack decision for a given project is ambiguous, we default to the Framer / Webflow / WordPress split for marketing sites and the Next.js plus Postgres default for anything with users.
Written 2025-11-22 by Naman Barkiya.