DEV Community

Sibasish Mohanty
Sibasish Mohanty

Posted on

From Simplicity to Complexity: My Love-Hate Journey with Next.js

I remember the day I started using Next.js like it was yesterday. It was version 8. And honestly? It was love at first sight. I bootstraped our new project in Nextjs despite my CTOs hesitation and made my teammates who never wrote a single line of code in React, learn Nextjs and ship with confidence.

File-based routing.
SSR. SSG. ISR.
Zero config.
You slapped a file in the pages/ folder, and boom—you had a route.
Simple, elegant, almost… magical.

// pages/about.js
export default function About() {
  return <div>About us</div>
}
Enter fullscreen mode Exit fullscreen mode

It did what React should have done out of the box but didn’t. I was sold.
Deploy it, forget about webpack configs, no client-side routing hacks. Just productivity.


The Shift: Enter Next.js 13 & The App Router Madness

Then Next.js 13 hit, and things changed.
Suddenly, pages/ was optional. Enter the app/ directory. Layouts. Templates. Nested routing. React Server Components. use client directives.

It felt… like betrayal.

// app/layout.js
export default function Layout({ children }) {
  return <div className="layout">{children}</div>
}
Enter fullscreen mode Exit fullscreen mode

Why?
Because the mental model shifted from “Page = Route” to “Segment = Route + Layout + Data Layer + Responsibility Split.”
Now I had to think in terms of route segments and where data should live: server component vs client component vs fetch cache vs what the hell.


The Mental Model Shift Nobody Talks About

Before, I thought:
“I add a file, it’s a route. Done.”

Now I have to ask:

  • Is this a server component or client component?
  • Should data fetching happen in generateStaticParams or inline in the component?
  • Where does this layout go?
  • Is this a template or a layout?

It’s not just about writing code anymore.
It’s about architecting for Next.js’s new ecosystem.

// app/products/[id]/page.js
export default function ProductPage({ params }) {
  const { id } = params
  // Do I fetch here? Should this be a server component?
}
Enter fullscreen mode Exit fullscreen mode

Fun, right?


Love, But With Conditions

Let me be clear: I love the power.
Server Components are a huge win.
Nested layouts? Clean.
Improved routing flexibility? Great.
Performance optimizations baked in? Finally.

But…

It feels overengineered.
Every simple use case now requires reading three different RFCs.
Constantly wondering if you’re doing it “the Next Way™” or just making a hack that’ll break in the next release.


Should You Care?

If you’re building large, scalable apps or deeply care about performance, yes.
Next.js App Router is awesome when you’ve got the bandwidth to understand it.

If you just want to ship stuff, fast and simple…
Stick to pages/. Forget Server Components. Forget complicated layouts.
Use Next.js like the framework it used to be.


My Takeaway

Next.js is amazing at scale.
Next.js is terrible when you want simplicity.

It’s like loving a Swiss Army knife, but sometimes you just need a plain old screwdriver.
And now, the screwdriver has a dozen attachments you don’t care about.

Still, I’m in.
Because I know the payoff exists…
If I survive the learning curve.

Top comments (2)

Collapse
 
giovannimazzuoccolo profile image
Giovanni Mazzuoccolo

I understand the frustration. Unfortunately—though I hope I’m wrong—this seems to be a common challenge when switching between frameworks.
For example, when I migrated an application from Nuxt 2 to Nuxt 3, it was easier to rewrite it from scratch than to do a direct migration. The same happened years ago when I moved a project from AngularJS to Angular.

Collapse
 
sibasishm profile image
Sibasish Mohanty

Absolutely! But some of these changes don't seem to add much value