Is Next.js Better Than React? It's React Plus the Parts You'd Build
Next.js is React plus a router, build and server rendering. Measured on this repo: 884 prerendered pages, and a client FAQ whose text is still in the HTML.
Next.js is not better or worse than React, because it is React plus the parts React leaves out: a router, a build, server rendering and metadata. Pick it when the page must be found by search engines or needs a server; skip it when the app lives behind a login. This storefront runs React 19.2.4 on Next.js 16.2.9 and prerenders 884 pages from one npm run build.
The question has a hidden premise
"Better than React" treats the two as rivals. They are layers. React renders components. Next.js is a framework that installs React, then decides how those components become URLs, HTML and JavaScript. Every Next.js page you write is a React component, and removing Next.js does not remove React; it removes the decisions Next.js made for you.
So the real question is: do you want to make those decisions yourself?
| Decision | Plain React (with a bundler such as Vite) | Next.js |
|---|---|---|
| Routing | You add and configure a router library | File system: src/app/pricing/page.tsx is /pricing |
| First HTML sent | An empty shell, filled in by JavaScript | Full HTML, prerendered at build or on request |
| Page titles, OG images | You add a head-management library | metadata exports and opengraph-image.tsx files |
| Data loading | useEffect plus a fetch library | async Server Components, Server Actions |
| Backend endpoints | A separate server | Route handlers in the same project |
| Sitemap and robots | A script you write | sitemap.ts and robots.ts |
| Upgrade path | You own every library choice | One framework version to move |
Plain React wins on flexibility and on having nothing you did not choose. Next.js wins on how much you do not have to build.
What Next.js gave this codebase, file by file
These are the parts of the storefront that exist only because the framework provides a slot for them.
| File | What it does | React alone would need |
|---|---|---|
src/app/sitemap.ts | Emits every product, hub and blog URL with a declared lastModified | A custom build script |
src/app/robots.ts | Generates robots.txt | A static file kept in sync by hand |
src/app/blog/[slug]/opengraph-image.tsx | Renders a social card per post | An image service or a pre-build step |
src/app/api/webhooks/lemonsqueezy/route.ts | Receives signed payment webhooks | A separate Node server |
src/proxy.ts | Refreshes the session on every request | Server middleware elsewhere |
Counting what a build produces is the cleanest way to see the difference. Running npm run build here ends with:
✓ Generating static pages using 3 workers (884/884) in 8.0s
That is 884 real HTML files. A plain React single-page app would ship one index.html and let the browser assemble the rest.
Client-side interactivity still works the same
Choosing Next.js does not make the page less interactive. The FAQ accordion on /pricing is src/components/molecules/FaqItem.tsx, a normal React component with useState:
"use client";
import { useId, useState } from "react";
// ...
export default function FaqItem({ question, answer }: FaqEntry) {
const [open, setOpen] = useState(false);
It is a Client Component, yet its question text is already in the prerendered file. After the build, grep -c "Is this really a one-time payment" .next/server/app/pricing.html returns 1. Crawlers read the question without running JavaScript, and the browser then hydrates the same component so the click handler works. That combination, server HTML plus client behaviour from one component, is the main thing a plain React shell cannot give you.
Only 26 of the 126 .tsx files under src/components and src/app carry "use client"; the rest never ship their code to the browser as client components.
When plain React is the better choice
| Situation | Better fit | Why |
|---|---|---|
| Admin tool behind a login, no SEO need | React + Vite | There is nothing for a crawler to read, so prerendering buys little |
| Widget embedded in someone else's page | React | You ship a bundle, not a site |
| Team already has a router, data layer and deploy pipeline | React | A migration would cost more than it returns |
| Marketing site, store, blog or docs | Next.js | Search visibility and fast first paint decide revenue |
| App needing both public pages and a dashboard | Next.js | One project, static public routes, dynamic private ones |
For an admin dashboard in particular, see Next.js vs React + Vite for admin dashboards. For the migration direction, Next.js vs Create React App covers what moving costs.
What you pay for the framework
Being honest about trade-offs matters, because "Next.js is better" is only true if you accept these.
- A mental model to learn. The Server/Client Component boundary is the main one. React
use clientlists the 26 files here that needed the directive and why. - Constraints on what runs where. Browser APIs such as
windowcannot run during prerender. A component that touches them has to be a Client Component and guard its access; forcing client-side rendering shows what each option emits. - A framework upgrade is yours to schedule. The repo's
CLAUDE.mdwarns that this Next.js version is newer than most training data, so the bundled docs innode_modules/next/dist/docs/are the reference, not memory.
Mistakes and troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
"You're importing a component that needs useState" at build | A Server Component imports hook-using code | Add "use client" to the file that owns the hook |
window is not defined during build | Browser API read while prerendering | Read it inside useEffect, or guard with typeof window |
| Page content missing from view-source | Data fetched in useEffect after load | Fetch in a Server Component so it is in the HTML |
| Everything is a Client Component and the bundle grew | "use client" placed on a parent instead of the leaf | Push the directive down to the smallest interactive file |
| Metadata missing on a client page | metadata export is not allowed in a Client Component | Export it from the server page.tsx that renders the client part |
Frequently asked questions
Is Next.js better than React for SEO? For pages that must rank, yes in practice: Next.js sends finished HTML, so a crawler sees content without executing JavaScript. React alone can do this only if you add your own server rendering.
Do I need to learn React before Next.js? Yes. Every Next.js page is a React component, so state, props and Hooks carry over directly. What you add is routing, rendering modes and the Server/Client split.
Can I use React libraries in Next.js? Mostly. Libraries that use state, effects or browser APIs need to be imported from a Client Component. Pure-render libraries work anywhere.
Is Next.js slower than React?
Not inherently. First paint is usually faster because HTML arrives already rendered. Hydration still has a cost, which is why keeping "use client" to the leaves matters.
Templates in this post
ASoc Folio is a personal portfolio site for designers and developers with services, resume and filtered work. ASoc Forge is an AI resume-builder landing page with a live editor preview. ASoc Frame is an AI image-generator landing page with a prompt hero and a how-it-works flow.
