If you search "Next.js vs React," you'll see a lot of articles that treat them like two competing frameworks. That's the wrong starting point.
Next.js is built on React. You're not choosing React or Next.js. You're choosing between:
- a plain React project (Vite, Create React App, or a custom SPA setup), and
- a React project with Next.js as the framework on top.
After 8+ years building web apps — from MVPs to production platforms — I default to Next.js for almost every serious web project. Not because React is bad. React is excellent. But for real products, Next.js gives you a full stack of decisions already made — and those decisions are usually the right ones.
Here's why.
1. SEO and First Load Are Built In, Not Bolted On
A plain React SPA typically ships a mostly empty HTML shell. The browser downloads JavaScript, React mounts, data is fetched, and then the user sees content.
That works for dashboards behind login. It is painful for:
- portfolios
- landing pages
- blogs
- marketing sites
- anything that needs Google, LinkedIn previews, or fast first paint
Next.js solves this at the framework level with:
- Server Components (App Router) — render on the server by default
- Static generation (SSG) — pre-build pages at deploy time
- Server-side rendering (SSR) — render per request when needed
- Streaming — send HTML in chunks while slower parts load
With a plain React app, you can add SSR — but you're assembling tools yourself (custom Node server, hydration setup, routing, caching). With Next.js, it's the default path.
Real impact: better Core Web Vitals, better crawlability, better social sharing previews — without a separate backend just to render HTML.
2. Routing Is a Feature, Not a Dependency You Wire Up
In a plain React project, routing usually means:
- install
react-router - define routes manually
- handle layouts yourself
- figure out code splitting per route
- add loading and error states yourself
In Next.js, the file system is the router:
app/
page.tsx → /
about/page.tsx → /about
blog/page.tsx → /blog
layout.tsx → shared layout
loading.tsx → loading UI
not-found.tsx → 404 page
Nested layouts, route groups, dynamic segments, and error boundaries are first-class. You spend less time on plumbing and more time on product.
I've shipped multi-page sites (portfolio, blog, project pages) where adding a new route is literally creating a folder and a page.tsx. That velocity matters on client work.
3. Full-Stack in One Repo (Without a Separate API Project)
Plain React is frontend-only. Need an API? You spin up Express, Nest.js, or Firebase Functions in another repo — then deal with CORS, auth, deployment coordination, and env var duplication.
Next.js gives you:
-
Route Handlers (
app/api/.../route.ts) — REST endpoints - Server Actions — mutations from the client without writing a separate API layer
- Server-side data fetching — call your DB or third-party APIs directly in Server Components
For many apps — contact forms, CMS fetches, auth callbacks, webhooks, internal tools — you don't need a standalone backend on day one.
Example use cases I've used Next.js API routes for:
- blog post fetching
- form submissions
- webhook receivers
- server-side token exchange (keeping secrets off the client)
One repo. One deploy. Less context switching.
4. Performance Optimizations You'd Otherwise Skip
Next.js ships with optimizations that teams often postpone in plain React projects because "we'll add it later" (and never do):
| Feature | Plain React | Next.js |
|---|---|---|
| Automatic code splitting | Manual setup | Built in per route |
| Image optimization | You pick a library |
<Image /> component |
| Font optimization | Manual | next/font |
| Script loading strategy | Manual |
<Script /> component |
| Bundle analysis | Extra tooling | @next/bundle-analyzer |
The <Image /> component alone is worth it on content-heavy sites. Lazy loading, responsive sizes, modern formats (WebP/AVIF), and layout shift prevention — handled.
On a portfolio or product site with screenshots and hero images, this is a measurable win without extra libraries.
5. Better Developer Experience for Production Apps
Things that feel small in a demo but matter in production:
-
Environment variables —
NEXT_PUBLIC_vs server-only vars are clearly separated - Middleware — auth checks, redirects, geo routing at the edge
-
Built-in metadata API — SEO tags per page without
react-helmet - Incremental Static Regeneration (ISR) — update static pages without full rebuilds
- Deployment story — Vercel is first-class, but Next.js also runs on Netlify, AWS, Docker, etc.
When I build client projects, I need predictable structure. Next.js gives every page the same conventions: where data lives, where loading states go, where errors go. New developers on the project ramp up faster.
6. The App Router Changed the Game (2024–2026)
If you looked at Next.js years ago and thought "it's just SSR for React," look again.
The App Router (now the default) gives you:
- React Server Components
- Streaming and Suspense boundaries
- Colocated loading/error UI
- Server Actions for forms and mutations
- Partial Prerendering (where supported)
This is not "React with extra steps." It's a different — and better — default for web apps that need both interactivity and performance.
I use "use client" only where I need hooks, browser APIs, or heavy interactivity. Everything else stays on the server. Less JavaScript to the browser. Faster pages. Simpler mental model once you learn it.
7. Plain React Still Has a Place (Being Honest)
Next.js is not magic. I still reach for plain React (usually Vite) when:
- the app is a logged-in dashboard with zero SEO needs
- it's an embedded widget inside another site
- the team already has a separate backend and wants a thin SPA frontend
- the scope is a small internal tool that will never be public-facing
But even then, I ask: will this ever need SEO, public pages, or server-side data? If yes, I start with Next.js anyway. Migrating from SPA to SSR later is expensive.
Side-by-Side: What You Get on Day One
Plain React (Vite/CRA):
✅ Fast dev server
✅ Full control
❌ No SSR/SSG out of the box
❌ No file-based routing
❌ No API layer
❌ No image/font optimization
❌ SEO requires extra work
Next.js:
✅ Everything React gives you
✅ SSR, SSG, ISR, streaming
✅ File-based routing + layouts
✅ API routes + Server Actions
✅ Image, font, script optimization
✅ Metadata and SEO built in
✅ Production conventions from day one
My Default Decision Framework
When a new web project comes in, I ask:
- Does this need to rank on Google or look good when shared? → Next.js
- Will we need server-side logic (forms, auth, webhooks)? → Next.js
- Is this a multi-page product site? → Next.js
- Is this a private admin panel with no public pages? → Plain React is fine
For me, that means Next.js wins roughly 80–90% of the time.
Final Take
React gives you the UI layer. Next.js gives you the product layer — routing, rendering strategy, API, optimization, and deployment patterns that every real web app eventually needs.
Starting with plain React and adding those pieces one by one works. I've done it. But it's slower, easier to get wrong, and you end up rebuilding toward what Next.js already provides.
If you're starting a new web project in 2026 and you're not sure which to pick: use Next.js with the App Router. You'll move faster, ship better-performing pages, and spend your time on features — not infrastructure.
Top comments (0)