After four years of building React apps with Create React App, I finally made the switch to Next.js. Here's an honest breakdown of what changed, what improved, and a few things that surprised me.
Why I stayed with CRA for so long
Create React App was genuinely great for its time. Zero config, instant start, everything just worked. For a long time, the complexity of setting up SSR, file-based routing, or API routes felt unnecessary for what I was building.
Then my projects got more complex.
The moment things changed
I was building a marketing site that needed SEO, a dashboard that needed protected routes, and an API that needed server-side logic — all in one repo. CRA made me reach for three separate tools to solve problems Next.js handles out of the box.
What Next.js does better
File-based routing is the first thing that clicked for me. No more maintaining a central routes.ts file. The folder structure is the routing — and once you internalize that, it feels obvious.
Server Components changed how I think about data fetching. Instead of useEffect + loading states for every component, I can fetch data directly in the component, on the server, with zero client-side JavaScript for the initial render.
// This runs on the server — no useEffect, no loading state
export default async function PostList() {
const posts = await db.posts.findMany();
return <ul>{posts.map(p => <li key={p.id}>{p.title}</li>)}</ul>;
}Built-in image optimization with next/image is something I didn't know I needed until I had it. Automatic WebP conversion, lazy loading, and layout shift prevention — for free.
What I missed from CRA
Honestly? Not much. The one thing I'd call out is that the mental model is more complex. "Is this a Server Component or a Client Component?" is a question you have to answer deliberately, and it trips up newcomers.
The verdict
If you're starting a new React project today, use Next.js. The ecosystem, the DX, and the performance wins are too significant to ignore.
The learning curve is real — but it's worth it.