Next.js or Vite? How I Decide
Every time I start a new project, I ask myself the same question: Next.js or Vite?
Both run React. Both have great DX. Both ship fast. But they're built for different things, and picking the wrong one early means fighting the framework later.
I've shipped products with both. Here's how I actually decide.
The One Question That Matters
Does this project need a server?
That's it. That's the decision.
If the answer is yes, or even "probably eventually," go with Next.js. If the answer is no, go with Vite.
Everything else, the file-based routing, the plugin ecosystem, the build speed, none of it matters as much as this one question.
When I Reach for Next.js
Next.js is my pick when the project has a public face. Anything that needs to rank on Google, share well on social media, or load fast on a cold visit.
That means:
- Marketing sites and landing pages
- Blogs and content-heavy sites
- Product pages where SEO drives growth
- Anything with dynamic
og:imagegeneration
This site is built with Next.js. The blog you're reading right now is MDX rendered server-side. The Open Graph images are generated at build time. The sitemap is auto-generated. I didn't have to stitch any of that together manually. Next.js just does it.
Server components are the real unlock here. You can fetch data, read from the filesystem, and render HTML without shipping a single byte of JavaScript to the client. For content sites, that's a huge win.
// This component runs on the server. Zero client JS.
export default function BlogPost({ params }) {
const post = getPost(params.slug);
return (
<article>
<h1>{post.title}</h1>
<MDXRemote source={post.content} />
</article>
);
}
The trade-off? Next.js is opinionated. You play by its rules. The app router, the file conventions, the rendering strategies. There's a learning curve, and once you're in, you're in.
Worth it for the right project. Overkill for others.
When I Reach for Vite
Vite is my pick when I'm building an app. Not a website, an app. Something behind a login screen, where SEO doesn't matter and the user is going to spend time interacting with it.
That means:
- Dashboards
- Internal tools
- SaaS products behind auth
- Anything where the first thing users see is a login page
Here's why: Vite gets out of your way. No server layer, no rendering strategies, no edge runtime decisions. Just React, a dev server that starts in milliseconds, and a build step that outputs static files.
Pair it with Firebase and you've got auth, database, storage, and hosting without writing a single line of backend code. Deploy the static build to Firebase Hosting, connect Firestore for data, and you're live.
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install firebase
npm run dev
That's a full-stack app in three commands. No server to manage. No cold starts. No infra costs until you actually have users.
There's another big one: Vite plays nicely with React Native in a monorepo. If you're sharing code between a web app and a mobile app, Vite just works. Same bundler config, shared packages, no friction. Next.js in a monorepo with React Native is a different story. The server layer, the webpack/turbopack setup, the Node.js dependencies, it all fights with React Native's Metro bundler. I've tried it. It's not fun.
If you're building a product that lives on both web and mobile, Vite + React Native is the path of least resistance.
The trade-off? No SSR, no built-in SEO tooling, no server components. If you need those later, you'll wish you started with Next.js.
The Gray Area
Some projects sit right in the middle. A SaaS with a marketing site and a dashboard. A product with public pages and private features.
I used to overcomplicate this. Build the whole thing in Next.js, use middleware for auth, mix server and client components everywhere.
Now I keep it simple: if the project has both a public and a private side, I still use Next.js. One codebase, one deploy. The marketing pages get server rendering. The dashboard pages get "use client" at the top. It works fine.
The only time I'd split them is if the dashboard is a completely separate product with its own domain, its own deploy, its own team. Then Vite for the app, Next.js for the site.
My Defaults
If I had to write it as a decision tree:
- Does it need SEO or server rendering? Next.js.
- Is it an app behind auth? Vite + Firebase.
- Is it both? Next.js.
- Are you prototyping something fast? Vite. Always.
These aren't rules. They're defaults. Defaults save you from decision fatigue at the start of a project, which is exactly when you should be thinking about the product, not the tooling.
Final Thoughts
The best framework is the one that disappears. You stop thinking about it and start thinking about what you're building.
For me, Next.js disappears when I'm building for the web. Vite disappears when I'm building an app. Both are great at their job.
Pick the right one, commit, and ship.