Why I Switched to Next.js (And Never Looked Back)
After years of building with various React frameworks, I made the switch to Next.js. Here's my honest breakdown of what makes it the best choice for modern web development and the tradeoffs you should know about.
The Breaking Point
I've been building web applications for years. I started with vanilla HTML/CSS/JS, moved to React with Create React App, tried Gatsby for static sites, and even experimented with Remix. Each framework solved some problems but introduced others.
The breaking point came when I was building a client project that needed:
- Server-side rendering for SEO
- Static generation for landing pages
- API routes for backend logic
- Image optimization out of the box
- TypeScript without painful configuration
No single tool checked all these boxes — until Next.js.
What Makes Next.js Different
1. The Rendering Flexibility
Next.js doesn't force you into one rendering strategy. You can mix and match on a per-page basis:
// Static Generation (SSG) — built at compile time
export async function getStaticProps() {
const posts = await fetchBlogPosts();
return { props: { posts } };
}
// Server-Side Rendering (SSR) — built on each request
export async function getServerSideProps(context) {
const user = await getUser(context.req);
return { props: { user } };
}
// Incremental Static Regeneration (ISR) — best of both
export async function getStaticProps() {
const data = await fetchData();
return {
props: { data },
revalidate: 60, // Rebuild every 60 seconds
};
}This flexibility is game-changing. Your marketing pages can be statically generated for maximum speed, while your dashboard can be server-rendered for real-time data.
2. File-Based Routing
No more wrestling with React Router configuration. Create a file, get a route:
pages/
index.tsx → /
about.tsx → /about
blog/
index.tsx → /blog
[slug].tsx → /blog/my-post
It's intuitive, reduces boilerplate, and makes your project structure self-documenting.
3. Built-in API Routes
Need a backend endpoint? Just create a file in pages/api/:
// pages/api/contact.ts
export default async function handler(req, res) {
if (req.method === "POST") {
const { email, message } = req.body;
await sendEmail({ email, message });
return res.status(200).json({ success: true });
}
return res.status(405).end();
}No separate Express server. No CORS configuration. It just works.
4. Image Optimization
The next/image component is worth the switch alone:
import Image from "next/image";
<Image src="/hero.png" alt="Hero image" width={1200} height={630} priority />;It automatically:
- Serves WebP/AVIF formats
- Lazy loads below-the-fold images
- Prevents Cumulative Layout Shift
- Resizes for different screen sizes
The Tradeoffs
I want to be honest — Next.js isn't perfect for every situation:
- Learning curve — if you're new to React, the SSR/SSG concepts add complexity
- Vercel lock-in perception — while you can self-host, the best experience is on Vercel
- Bundle size — for simple static sites, something like Astro might be lighter
- Build times — large sites with thousands of pages can have slow builds (ISR helps)
My Verdict
After 18 months of building production applications with Next.js, I can confidently say it's the most productive React framework available. The developer experience, performance defaults, and ecosystem make it my default choice for any new project.
If React is the engine, Next.js is the entire car — steering, brakes, GPS, and all.
Building something with Next.js? I'd love to hear about it. Connect with me on LinkedIn.