Why / When to use Next.js
Next.js is one way to build a React app, not the only way. Whether it's the right choice depends on what the app actually needs.
Use Next.js when…
- Content needs to be crawlable / SEO matters. A plain Vite SPA ships an empty HTML shell — search engine crawlers and social-media link previews may see nothing until JS runs. Next.js renders real HTML on the server (SSR) or at build time (SSG), so content is there immediately.
- First-load performance matters. Server-rendered HTML paints before any JavaScript downloads or runs. A pure client-rendered SPA has to fetch, parse, and execute its JS bundle first.
- You want frontend and backend in one project.API routes mean you don't need a separate Express/Fastify/etc. server for straightforward endpoints, webhooks, or BFF (backend-for-frontend) logic.
- Pages have very different rendering needs. A marketing site (static), a blog (static + periodic revalidation), and a live dashboard (SSR) can all coexist in one Next.js app, each choosing its own strategy per route.
- You want batteries-included conventions. Routing, code-splitting per route, image optimization, font optimization, and caching all come configured out of the box, rather than being assembled from separate libraries.
Don't reach for Next.js when…
- You're building a pure client-side app— an internal admin tool, a dashboard behind a login wall, a Chrome extension UI, an Electron app — where there's no public content to crawl and no server-render benefit. A Vite + React SPA (like ReactNotes) is simpler: fewer concepts (no Server/Client Component split, no server-only APIs to remember), and it deploys as static files to literally anywhere.
- The team doesn't want to manage a Node.js server runtime. SSR needs a server process (or a serverless/edge runtime, e.g. via Vercel/other hosts) — a static SPA can be hosted on any static file host or CDN with zero server infrastructure.
- The app is tiny or short-lived(a prototype, a coding exercise, a one-off tool) — Next.js's extra conventions (file-based routing rules, Server/Client boundaries, the App Router's async APIs shown throughout this cheat sheet) are overhead you don't need yet.
- You need a different framework's specific strength. Examples: a content site authored mostly in Markdown might fit Astro better (ships even less JS by default); a highly interactive, state-heavy client app with no SEO need might be simplest as plain React/Vite; a large enterprise Node backend might already have its own server framework that an API-routes approach would duplicate.
Quick comparison
| Concern | React + Vite (SPA) | Next.js |
|---|---|---|
| Routing | Manual, via react-router-dom | File-based, automatic |
| Rendering | Client-only | Server, static, or client — per route |
| SEO / crawlability | Weak by default (empty shell HTML) | Strong (real HTML from the server) |
| Backend endpoints | Needs a separate server | Built in (Route Handlers) |
| Deployment | Any static host / CDN | Needs a Node/edge runtime (or a host that provides one) |
| Conceptual overhead | Lower — one rendering model | Higher — Server/Client Components, async params/cookies, etc. |