Most studio-side technology choices are not battles between competing frameworks; they are decisions about which trade-offs you are paying for. We default to Next.js for the majority of new business applications, and this post is the technical reasoning behind that choice — including where we deliberately do not use it.
This is a technical post for engineering audiences. If you are an operator looking to evaluate a partner, the relevant question is "is your default stack defensible?" — this post is the long-form answer.
What we mean by "business apps"
Throughout this post, "business apps" means:
- Multi-page web applications with significant content (marketing pages plus interactive functionality)
- Applications with a meaningful authentication / authorization layer
- Applications that integrate with multiple external services (CRM, payments, email, AI APIs)
- Applications expected to live and evolve for 3-5+ years
This is most of what an SMB-to-mid-market client builds. It is not most of what a hyperscale consumer app builds (those have different constraints), and it is not most of what a single-page tool builds (those have different constraints too).
The default-stack we ship in 2026
For a typical new business app, our default starts looking like this:
- Framework: Next.js (App Router, server components by default)
- Language: TypeScript with strict mode
- Database: Postgres (via Supabase for most engagements; managed Postgres elsewhere for clients with existing AWS / GCP commitments)
- Auth: Supabase Auth or Clerk depending on the auth model needed
- Hosting: Vercel for most projects; Netlify for clients with an existing Netlify setup; Cloudflare Pages for very high-traffic edge-distributed cases
- Styling: Tailwind CSS with a project-specific design token layer
- Email: Resend (transactional) + a marketing platform per client preference
- Background work: Inngest, Trigger.dev, or Cloudflare Queues depending on the workload
- AI: OpenAI / Anthropic / open-source models behind a thin abstraction layer
This stack is the default. We deviate when the project warrants — section at the end of the post covers when.
Why Next.js specifically
Six reasons, in roughly the order they matter for business apps:
1. Single framework for SSR, SSG, ISR, and full client interactivity
Business apps need all four:
- SSR for authenticated dashboards where data is per-user and freshness matters
- SSG for marketing pages where speed and SEO matter and content rarely changes
- ISR for content pages that change occasionally (portfolio items, blog posts, team profiles) and benefit from CDN caching with revalidation
- Client interactivity for the components users actually interact with
Most other frameworks force you to pick a model. Next.js lets you pick per-route, per-component. We use all four in most of our applications, and the unified mental model means engineers do not switch frameworks based on what a particular surface needs.
2. Server components solve the "what runs where" problem
Before server components, every component started as a client component, and you had to consciously work backward to push logic to the server. With server components as the default, every component starts on the server, and you opt into client-side behavior only where it is needed. This inverts the right default.
The practical impact: bundle sizes drop substantially. A typical business app shipping under the App Router has 30-50% less client JavaScript than the equivalent under the Pages Router. For business app users — who are often on mid-tier hardware in office environments — that translates directly into perceived performance.
3. The metadata API ships SEO without an extra layer
The metadata and generateMetadata exports replace the entire category of react-helmet-style libraries we used to ship. Per-route SEO, per-route canonical URLs, per-route Open Graph and Twitter cards, per-route JSON-LD — all colocated with the page, all type-safe, all consistent.
For business apps where SEO matters at all (most of them), this is a meaningful productivity win and a meaningful quality win.
4. The deployment story is mature
Vercel runs Next.js as well as anyone runs anything. Netlify ships its own first-class Next.js plugin. Cloudflare Pages and AWS Amplify both have working Next.js adapters. Self-hosting on a Node server is straightforward. Self-hosting on Docker is straightforward.
The point is not that one of these is best — the point is that you have multiple defensible options, and switching between them mid-life is not a rewrite. We have moved client apps between Vercel and Netlify based on pricing and integrations without any framework-level rework.
5. The ecosystem is dense
Authentication libraries (NextAuth, Clerk, Supabase Auth, Auth0), data libraries (TanStack Query, SWR), form libraries (React Hook Form, react-form), CMS integrations (Sanity, Contentful, Payload, Strapi, Notion), payment integrations (Stripe, Paddle), email senders, observability tools — every category has a well-maintained Next.js integration.
This matters for business apps because the cumulative integration time across half a dozen of these is the difference between a 4-week build and an 8-week build.
6. Long-term sustainability
Next.js has Vercel as a commercial backer with an aligned business interest in keeping it healthy. It has a substantial open-source contributor base. It has a clear release cadence and reasonable backward-compatibility commitments. Major releases come with codemods that handle most of the migration mechanically.
For business apps expected to live 3-5+ years, this is not a small consideration. We have inherited applications from other studios where the original framework choice was abandoned by its maintainers two years in. That is a multi-month migration cost the original team avoided by picking a more boring choice.
What Next.js does not solve
To be honest about the trade-offs:
Build times can get long
Production builds for medium-sized Next.js apps can take 3-8 minutes on Vercel's standard build infrastructure. For very large apps, longer. There are mitigations (Turbopack is shipping, incremental builds help), but it is a real friction point in fast-iteration workflows.
Server component mental model has a learning curve
The "this is a server component, that is a client component" boundary is not always obvious to engineers new to the App Router. Misplaced 'use client' directives lead to hydration errors that are confusing to debug. Onboarding time for engineers new to the App Router is a real cost.
Vercel-specific features can create soft lock-in
Vercel-specific features (Edge Functions, Image Optimization, Analytics) work best on Vercel and degrade in functionality on other hosts. We deliberately use only the features that work cross-host so client lock-in is minimized — but the temptation to reach for the convenient Vercel-specific feature is real.
Edge runtime constraints can surprise
The Edge runtime (used for middleware, edge functions, and some other features) does not support all Node.js APIs. Code that works in the Node.js runtime may not work at the edge. For most business apps this is irrelevant; for apps that lean heavily on edge features, it is a recurring source of debugging time.
Server actions have rough edges
Server actions (the form-action-style server-side mutation pattern in the App Router) are useful but have rough edges around error handling, type safety, and progressive enhancement. We use them sparingly and lean on traditional API routes for most mutations.
When we reach for something else
Six scenarios where we deliberately do not start with Next.js:
1. Single-purpose tools and dashboards
For an internal-only dashboard or a single-purpose tool with no SEO or marketing surface, we usually reach for Vite + React (or Vite + Svelte for projects where the team prefers it). The build is faster, the deploy is simpler, and we are not paying for SSR machinery we do not use.
2. Real-time-heavy applications
For applications dominated by real-time WebSocket traffic (collaborative editors, live trading dashboards, multiplayer experiences), we usually reach for a stack with first-class WebSocket support — typically Cloudflare Workers + Durable Objects, or a Phoenix LiveView stack for Elixir-friendly teams.
3. Heavy-data interactive UIs
For applications that are dominated by complex client-side state (very interactive data tools, design tools, IDE-style applications), the React Server Components model fights you. We usually reach for plain React + Vite + a robust state management story (Zustand, Jotai) and accept the loss of SSR.
4. Static content sites with no interactivity
For pure marketing sites or documentation sites with no real interactivity, we sometimes reach for Astro. The output is more cleanly static, the JavaScript footprint is smaller, and the developer experience is excellent for content-heavy sites.
5. Existing engineering teams with strong framework preferences
When we extend an existing engineering team that has invested in a different framework (Remix, SvelteKit, Nuxt, Rails, Phoenix, Django), we work in their stack. Adding a second framework to a team's mental load is usually a worse trade than picking a less-preferred-by-us stack.
6. Mobile-first native applications
For applications where the primary surface is iOS and Android native apps, we usually reach for React Native (or sometimes Expo specifically). Next.js is not the right tool for the surface and trying to share code between Next.js and React Native creates more friction than it removes.
Why "boring" is the right framing
Defaulting to Next.js is, in a real sense, a "boring" choice in 2026. It is not the newest framework. It is not the framework with the most exciting demos. It is not the framework that wins on any single technical dimension.
It is the framework that scores reasonably well on every dimension that matters for business apps, has the deepest ecosystem, is most likely to still be around (and well-maintained) in 5 years, and that the largest pool of available engineers can hire into without retraining.
For business apps that need to ship and then live for years, "boring" is the correct optimization function. We deliberately avoid the temptation to chase the newest framework, because most clients are buying durability, not novelty.
Practical guidance for engineering teams considering Next.js
If you are evaluating Next.js for your business app:
1. Use the App Router. Server components are the right default for new code in 2026. The Pages Router is well-supported but represents the prior generation of the framework.
2. Use TypeScript with strict mode from the start. Adding strict mode later is much harder than starting strict.
3. Pick a deployment target before architecting features. Vercel-specific features lock you in lightly; planning for cross-host compatibility costs little upfront and saves real money mid-life.
4. Plan for the rough edges. Server actions, edge runtime constraints, and server/client boundary debugging are recurring time sinks. Budget for them.
5. Set up observability early. A production Next.js app benefits hugely from structured logging, error tracking (Sentry, Datadog, similar), and request tracing. Add these in week 1, not month 6.
For a 30-minute walkthrough of whether Next.js is right for your specific application, book a consultation — we will run the trade-off matrix on your project and give you a defensible recommendation, including "no, do not use Next.js for this" when that is the right answer.
See also: custom software services, web development services, and our earlier post Custom AI Automation vs Off-the-Shelf Tools.