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 along the way.
The Short Version
CRA was the right tool for a long time. It isn't anymore, and that's not just my opinion. The React team officially deprecated Create React App on February 14, 2025 and now points people toward frameworks like Next.js.
Here's what you gain by switching:
- File-based routing instead of a hand-maintained route table.
- Server Components, so you can fetch data without
useEffectand loading states everywhere. - Built-in image optimization, SSR, and API routes that you'd otherwise bolt on with three separate tools.
The cost is a slightly heavier mental model. For anything beyond a toy app, it's worth paying.
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 like overkill 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.
That was the tipping point. I wasn't fighting one missing feature. I was assembling a framework by hand, badly, around a tool that was never meant to be one.
CRA isn't just out of fashion, it's deprecated
This part matters more than personal taste. In February 2025, the React team retired Create React App for new projects. Install it today and you get a deprecation warning. It still runs, but it won't get new features, and the official guidance is to move to a real framework or a modern build tool like Vite.
So "should I still start projects on CRA?" isn't really a question anymore. The maintainers answered it. The real question is what you move to, and for production React apps that need routing, data fetching, and SEO, Next.js is the path of least resistance.
What Next.js does better
File-based routing was the first thing that clicked for me. No more babysitting a central routes.ts file. The folder structure is the routing, and once you internalize that, going back feels clumsy.
Server Components changed how I think about data fetching. Instead of useEffect plus 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.
// Server Component (the default in the App Router).
// 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, all for free.
API routes and server logic live in the same project. The marketing site, the dashboard, and the API that pushed me off CRA now sit in one repo with one mental model, instead of three tools stitched together.
The one concept that trips everyone up
The honest downside of Next.js is that the mental model is heavier. "Is this a Server Component or a Client Component?" is a question you now have to answer on purpose, and it's where newcomers get stuck.
The rule is simpler than it looks. Components are Server Components by default. The moment you need state, effects, or browser-only APIs, you opt into a Client Component with a directive at the top of the file:
'use client';
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}Default to the server. Reach for 'use client' only when a component actually needs interactivity. Once that becomes a habit, the rest of the model falls into place.
If you're making the switch
A move off CRA is rarely a full rewrite. The rough path looks like this:
- Scaffold a fresh Next.js app and bring your components over more or less as-is.
- Translate your routes into the folder structure, replacing your router config.
- Move data fetching out of
useEffectand into Server Components where it makes sense. - Add
'use client'to the components that genuinely need it, not preemptively to all of them. - Swap
<img>tags fornext/imageas you go.
You don't have to do all of it on day one. The pieces convert incrementally, which is what made the switch feel manageable rather than terrifying.
What I missed from CRA
Honestly? Not much. The only real loss is simplicity. CRA asked nothing of you. Next.js asks you to understand where your code runs. That's a fair trade for what you get back, but it is a trade, and it's worth naming.
The verdict
If you're starting a new React project today, use Next.js. The ecosystem, the developer experience, and the performance wins are too significant to ignore, and CRA is no longer a real option anyway.
The learning curve is real, but it's worth it.
Frequently Asked Questions
Is Create React App actually dead?
For new projects, effectively yes. The React team deprecated it on February 14, 2025. Existing apps still run and CRA was updated to support React 19, but it receives no new features and the official recommendation is to migrate.
Should I migrate an existing CRA app right now?
If it's working and stable, there's no emergency. But since CRA won't get improvements or bug fixes, plan the move rather than ignoring it. Start with new features built the Next.js way, then migrate the rest incrementally.
Next.js or Vite?
Both are valid post-CRA choices. Reach for Vite when you want a fast, lightweight single-page app and you're happy wiring up routing and data fetching yourself. Reach for Next.js when you need SSR, SEO, API routes, or a full-stack setup in one place. My projects needed the second list, so Next.js won.
Do I need a server to run Next.js?
Not necessarily. Next.js can statically export for simple sites, and platforms like Vercel handle the server-side parts for you with zero infrastructure work. You only manage a server if you choose to self-host.
Is the App Router worth it over the Pages Router?
For new projects, yes. The App Router is where Server Components, streaming, and the modern data-fetching model live, and it's where Next.js is heading. The Pages Router still works, but you'd be opting into the older model on purpose.
Is Next.js overkill for a small project?
Sometimes. For a tiny static page with no data needs, a plain Vite + React setup is lighter. The moment you need routing, SEO, or any server logic, Next.js stops being overkill and starts saving you time.
Further Reading
- Sunsetting Create React App — the official React team announcement.
- Next.js documentation — the App Router, Server Components, and everything else.
- Creating a React App — React's current recommendations for starting a project.
Related posts on this blog
- The Underrated Power of Reading Time on Your Blog — a small frontend UX detail that earns trust before a reader starts.
- Stop Prompting Claude Like It's Google — a different kind of tooling switch, this time in how you work rather than what you build with.
Made the jump off CRA yourself, or stuck mid-migration? I'd be glad to compare notes. Find me on LinkedIn or check out more of my work on GitHub.