Why You Might Not Need Next.js
Next.js is the default answer to "what should I build my web app with?" It shows up in tutorials, job postings, and starter templates so consistently that reaching for it has stopped feeling like a decision. It's just what you use.
But "the default" and "the right tool" aren't the same thing. Next.js
solves real problems — and if you don't have those problems, it hands
you a pile of complexity in exchange for nothing. This is a case for
stopping to ask whether you actually need it before you
npx create-next-app.
To be clear up front: this isn't a hit piece. Next.js is genuinely excellent at what it's built for. The argument is narrower — that it's over-applied, and that a lot of projects would be faster to build, easier to maintain, and cheaper to run with something simpler.
What Next.js is actually for
Next.js earns its keep when you need a specific set of things at the same time:
- Server-side rendering or static generation for SEO and fast first paints on content-heavy or public-facing pages.
- A blended frontend/backend where colocating API routes with your UI genuinely simplifies things.
- Fine-grained rendering control — mixing static, server-rendered, and streamed content within one app.
- Scale and a team that benefits from strong conventions and a well-trodden path.
If you're building something like an e-commerce storefront, a marketing site with a CMS, or a large product with a dozen contributors, these are real benefits and Next.js is a defensible, often great choice.
The problem is that most projects aren't that.
The tell-tale signs you don't need it
Ask yourself honestly:
Is your app behind a login? If every meaningful page sits behind authentication, SEO is irrelevant and server rendering buys you very little. A dashboard, an internal tool, an admin panel — these are client-side apps wearing a server-side framework as a costume.
Do you actually need a backend bundled in? Next.js API routes are convenient until your backend grows up. If you already have a separate API (or plan to), you're running a server framework mainly to serve a single-page app, which a static host does for free.
Are you fighting the framework more than using it? The App Router, server components, the client/server boundary, caching behavior that changes between versions — these are powerful, but they're also a constant tax on your attention. If you spend more time reasoning about where code runs than what it does, that's a signal.
Is it a small project or a prototype? The setup overhead, build complexity, and mental model are pure cost when you're trying to validate an idea this weekend.
What you might use instead
The honest alternative to "Next.js by default" isn't "suffer without tools." It's picking the smallest thing that fits.
A plain SPA with Vite. For an app that lives behind a login and talks to an API, a React (or Vue, or Svelte) single-page app built with Vite is fast to develop, trivial to deploy as static files, and has a dramatically smaller conceptual surface. No server to run, no client/server boundary to reason about. You'll be surprised how far this goes.
Astro for content-heavy sites. If your real need is "fast static pages with a sprinkle of interactivity" — blogs, docs, marketing sites — Astro ships almost no JavaScript by default and lets you use any component framework for the interactive bits. It's purpose-built for the content use case that people often reach for Next.js to handle.
SvelteKit or Remix if you do need full-stack SSR but want a different set of tradeoffs. These aren't "simpler" exactly, but they're worth evaluating rather than assuming Next.js wins by default.
Just a static site. Sometimes the answer is HTML, a bit of CSS, and a sprinkle of JavaScript. Not every project needs a framework at all, and a static site you can read in one sitting will outlive a clever one nobody understands.
The hidden costs of the default
Choosing Next.js when you don't need it isn't free, even though it feels like it:
- Hosting lock-in pull. Next.js runs best on infrastructure that understands its server features. A plain SPA deploys to any static host — a CDN, a bucket, GitHub Pages — for pennies or nothing.
- Build and cognitive complexity. More moving parts means more to debug, more to onboard new developers into, and more that can break on an upgrade.
- Version churn. Next.js evolves aggressively. Major shifts in routing and rendering have meant real migration work for teams who just wanted to ship a product.
- Performance you pay for but don't use. Server components and streaming are impressive — but if your app is interactive and authenticated, you may be carrying the weight of features that never help your users.
The actual rule of thumb
Use Next.js when your app is public-facing, content-rich, SEO-sensitive, or large enough that strong conventions pay for themselves. That's a real and common category — it's just not every category.
For everything else — internal tools, dashboards, prototypes, anything behind a login, anything small — start with the simplest option and add complexity only when a concrete need forces your hand.
The cost of starting simple and outgrowing it is usually a migration. The cost of starting complex is paid every single day you work on the project.
That's roughly where I've landed in practice. I still reach for Next.js when a project actually calls for it — or when a client or team has asked for it — but the truth is that most of the work I do just needs Vite. Once I stopped treating the heavier option as the default, I noticed how rarely my projects were the kind that justified it.
The best framework is the one whose problems are your problems. Before you reach for the default, spend five minutes confirming the default is reaching back.