React is a library for building user interfaces from components. Next.js is a framework that uses React and adds file-based routing, server rendering, server components, API endpoints and build tooling. You write React either way. Choose Next.js when pages need server-rendered HTML, secrets or backend routes; plain React with Vite suits apps that live behind a login.
| Need | React with Vite | Next.js (App Router) |
|---|---|---|
| Components, state, hooks | Yes | Yes, same React |
| Routing | Add a router library | Folders in app/ become routes |
| HTML rendered before JavaScript loads | No, unless you add SSR or prerendering | Yes, server or build time |
| Server components and secrets on the server | No | Yes, layouts and pages are server components by default |
| API endpoints in the same project | No, separate backend | route.ts files |
| Output | Static files from vite build | Node server, or static files with output: 'export' |
Updated
Tick the features your project needs. Each one is marked as built into Next.js or easy in a Vite React app, and the tally gives you a starting recommendation. The code below shows the same small page written both ways.
The file path is the URL. The page awaits data before HTML is sent; only the button ships as client JavaScript.
// app/products/page.tsx -> /products
import { AddButton } from "./add-button";
export default async function ProductsPage() {
const products: { id: string; name: string }[] =
await fetch("https://api.example.com/products").then((r) => r.json());
return (
<ul>
{products.map((p) => <li key={p.id}>{p.name} <AddButton id={p.id} /></li>)}
</ul>
);
}
// app/products/add-button.tsx
"use client";
export function AddButton({ id }: { id: string }) {
return <button onClick={() => console.log("add", id)}>Add</button>;
}Routing comes from React Router, and the list appears after the browser fetches it.
// src/main.tsx
import { createRoot } from "react-dom/client";
import { BrowserRouter, Routes, Route } from "react-router";
import { Products } from "./Products";
createRoot(document.getElementById("root")!).render(
<BrowserRouter>
<Routes>
<Route path="/products" element={<Products />} />
</Routes>
</BrowserRouter>
);
// src/Products.tsx
import { useEffect, useState } from "react";
export function Products() {
const [products, setProducts] = useState<{ id: string; name: string }[]>([]);
useEffect(() => {
fetch("/api/products").then((r) => r.json()).then(setProducts);
}, []);
return <ul>{products.map((p) => <li key={p.id}>{p.name}</li>)}</ul>;
}Both commands ask a few questions, including whether to use TypeScript.
# Next.js
npx create-next-app@latest
# React with Vite (choose the react-ts template for TypeScript)
npm create vite@latest
React decides how a component turns state into UI and updates the page. It does not decide how URLs map to screens, where data loads or how the project is built. Those choices are yours in a Vite app and Next.js's in a Next app.
That is the trade: Next.js removes decisions and adds server features, and in return you follow its folder conventions and run its build.
In Next.js, app/blog/page.tsx is the /blog route and layout.tsx wraps its children. Pages are server components unless marked otherwise, so they can await data directly, and interactive pieces live in files that start with 'use client'.
In a Vite app, main.tsx renders one root component into index.html, routes come from a library such as React Router, and data loads in the browser through fetch or a client cache.
Internal tools, dashboards, editors and anything behind a sign-in rarely need server-rendered HTML. A Vite app starts quickly, deploys as static files and keeps the mental model small.
If such an app later needs public pages, it is common to put marketing pages on a separate site and keep the app itself as it is.
They are not alternatives in the usual sense, because Next.js runs React. The real question is whether you want a framework's routing, server rendering and conventions, or a lighter setup where you choose each piece yourself.
The current react.dev guide recommends starting with a framework such as Next.js or React Router, and lists Vite, Parcel and Rsbuild for building your own setup from scratch. It does not list Create React App.
Yes. Set output: 'export' in next.config.js and next build writes HTML, CSS and JavaScript to an out folder. Features that need a running server, such as cookies, rewrites, redirects and server actions, are not available in that mode.
Learn the React basics first: components, props, state and effects. Next.js then adds routing and server concepts on top, and debugging is much easier when you can tell which problem belongs to which layer.
Not automatically, but by default the HTML has no page content until JavaScript runs. Marketing pages that need to rank are easier with server rendering or prerendering; dashboards behind a login do not need it.
Related: Frontend framework comparison, Next.js App Router, React Server Components, React Router examples, Data fetching in React, Next.js SEO.
Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.
We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.