Next.js for React Developers: What It Adds and When You Need It
Next.js gives React file-based routing, server-side rendering, static generation, and API routes. Here's what changes when you move from plain React to Next.js.
If you've been building React apps with Create React App or Vite, you've probably hit a wall at some point. Maybe it was SEO — your single-page app renders an empty Next.js solves all of these problems. It's a framework built on top of React that adds the infrastructure pieces React deliberately doesn't include. It's opinionated where React is flexible, and those opinions are mostly good ones. export default async function ProductPage({ params }: { params: { id: string } }) { return ( export async function GET() { export async function POST(request: Request) { Next.js has two routing systems, which is confusing. The Pages Router ( The App Router uses React Server Components by default, supports nested layouts, has a different data fetching model (you If you're starting a new project, use the App Router. The Pages Router still works and isn't going away, but new features land in the App Router first. This is the biggest conceptual shift. In the App Router, components are Server Components by default. They run on the server, have zero JavaScript sent to the client, and can directly access databases, file systems, and environment variables. return ( When you need interactivity — event handlers, state, effects — you mark a component as a Client Component with import { useState } from 'react'; export default function LikeButton() { return ( The mental model: Server Components for data fetching and static content, Client Components for interactivity. Most of your app should be Server Components, with Client Components at the leaf nodes where users actually interact. Next.js is built by Vercel, and Vercel's hosting platform is optimized for Next.js. That means features like ISR, edge functions, and image optimization work best on Vercel's infrastructure. You can absolutely deploy Next.js elsewhere — Cloudflare Pages, AWS, Docker, static export — but some features require more configuration outside Vercel. This vendor coupling is worth knowing about. Next.js is open source and works anywhere, but the path of least resistance leads to Vercel's platform. Whether that's a problem depends on your deployment requirements. The CLI asks you about TypeScript, Tailwind CSS, ESLint, and the App Router. Say yes to all of them — those are the current best practices. From there, start building. Create pages, fetch data, add layouts. The Next.js docs are genuinely excellent and full of examples. If you want to strengthen your React fundamentals before jumping into Next.js — or practice the JavaScript/TypeScript concepts that Next.js builds on — CodeUp has interactive exercises covering React, JavaScript, and TypeScript that you can work through in your browser. A solid React foundation makes Next.js click much faster.What Next.js Adds to React
File-based routing. Create a file at app/about/page.tsx and you have a /about route. Create app/blog/[slug]/page.tsx and you have dynamic routes. No React Router configuration, no route definitions. The file system is the router.
Server-Side Rendering (SSR). The server renders your React components to HTML before sending them to the browser. The user sees content immediately, and search engines can crawl it. The page then "hydrates" — React takes over on the client side and makes it interactive.
Static Site Generation (SSG). For pages where the content doesn't change per-request (blog posts, documentation, marketing pages), Next.js generates static HTML at build time. The result is incredibly fast — it's just HTML files served from a CDN.
Incremental Static Regeneration (ISR). The middle ground between SSR and SSG. Pages are statically generated but can be revalidated after a set time period:
app/
page.tsx → /
about/
page.tsx → /about
blog/
page.tsx → /blog
[slug]/
page.tsx → /blog/my-first-post
api/
users/
route.ts → /api/users
API Routes. You can build backend endpoints right inside your Next.js app. No separate Express server needed for simple use cases:
// This page regenerates at most every 60 seconds
export const revalidate = 60;
const product = await fetch(https://api.example.com/products/${params.id});
const data = await product.json();
<div>
<h1>{data.name}</h1>
<p>{data.description}</p>
<span>${data.price}</span>
</div>
);
}
Image optimization. The // app/api/users/route.ts
import { NextResponse } from 'next/server';
const users = await db.query('SELECT * FROM users');
return NextResponse.json(users);
}
const body = await request.json();
const user = await db.insert('users', body);
return NextResponse.json(user, { status: 201 });
} component automatically resizes, converts to modern formats (WebP, AVIF), and lazy-loads images. This alone can cut page weight by 50% or more on image-heavy sites.
App Router vs Pages Router
pages/ directory) is the original. The App Router (app/ directory) is the new one, introduced in Next.js 13.await data directly in components instead of using getServerSideProps), and handles loading/error states with special files.app/
layout.tsx ← Root layout (wraps everything)
page.tsx ← Home page
loading.tsx ← Loading UI while page data loads
error.tsx ← Error boundary
blog/
layout.tsx ← Blog-specific layout (nested)
page.tsx ← Blog index
[slug]/
page.tsx ← Individual blog postServer Components
// This component runs only on the server
// No JavaScript shipped to the browser for this
export default async function UserProfile({ params }: { params: { id: string } }) {
const user = await db.users.findOne(params.id); // Direct DB access
<div>
<h1>{user.name}</h1>
<p>{user.bio}</p>
</div>
);
}"use client":"use client";
const [likes, setLikes] = useState(0);
<button onClick={() => setLikes(likes + 1)}>
Likes: {likes}
</button>
);
}When You Need Next.js vs Plain React
Use Next.js when:
Plain React (with Vite) is fine when:
The Vercel Connection
Getting Started
npx create-next-app@latest my-app
cd my-app
npm run dev