MADEBYARIS

Next.js App Router vs Pages: when I still touch Pages

4 min read
By Aris Setiawan
Next.js App Router vs Pages: when I still touch Pages

I start new Next.js work in App Router. I still touch Pages on old repos, on mixed trees, and anywhere getServerSideProps still owns the request.

That is the comparison. Not a feature matrix.

I’m Aris Setiawan. I ship Next.js for client work. Yesterday I wrote the App Router I actually keep in `app/`. This post is the other question: when pages/ is still on the disk, and what I do not rewrite in a weekend.

The offer page is Hire a Next.js developer. This is the practice, not a migration sales deck.

New product: I do not open pages/

A 2026 product starts in app/. Layout, page, a small client boundary, a cache I can walk after a write. I wrote that set yesterday. I do not add a pages/ folder so the repo looks familiar.

New product starts in app, not pages

Pages still exists in Next.js. That is not a reason to start there. _app, getServerSideProps, and pages/api are the old request path. On a new app they become a second tree I have to explain on day two.

If the ticket is a new product, the router is App Router. If someone wants Pages because the last contractor used it, I say no and I keep the reason short.

Old repo: pages/ is still the tree

I inherit apps that live in pages/. _app.js, index.js, pages/api, a pile of getServerSideProps. The product works. Users are on it.

Old repo, pages is still here

I do not rewrite that tree because a post said App Router is the only router. I open the data function first. I write down where the session is read, what the page fetches, and what happens after a write. If I cannot say those three things, I am not ready to move the route.

I still touch Pages to ship a fix: a broken query, a header, a form that posts to the wrong API. The fix stays in Pages if the route is Pages. Mixing one App Router file into a Pages-only tree without a plan is how you get two auth stories.

Mixed repo: both folders, one URL at a time

A lot of client repos already have app/ and pages/ next to each other. New marketing pages landed in App Router. The dashboard is still getServerSideProps.

Mixed repo, app and pages both present

That is fine if each URL has one owner. It is not fine if /account is Pages and /account/settings is App Router and they do not share the session the same way.

When I migrate, I take one URL. I copy the data rules, not the file names. getServerSideProps does not become a Server Component by renaming the file. Cookies, cache, and the client boundary have to be decided again. I ship that URL. I leave the next one until this one is boring.

I do not pick a weekend and “finish the migration.” That is how you get a half-moved checkout and a rollback you cannot explain.

What I still meet in Pages

getServerSideProps: the request is the cache. I do not pretend fetch with a tag is the same thing. If the page must see the cookie on every hit, I keep it that way until the App Router version says so in the fetch.

getStaticProps plus revalidate: this one maps. A Server Component with a revalidate window or a tag is the replacement. I still have to name what busts it after a write.

_app and _document: layout and the document shell. In App Router that is app/layout.tsx and a small metadata file. I do not paste _app into a client layout.

pages/api: route handlers in App Router, or a Server Action when the work is ours. I do not open a new pages/api file on an app that already has app/.

What I skip

Starting a 2026 product in Pages.

Flipping a root layout to 'use client' so the Pages habits fit.

A rewrite with no rollback URL. If I cannot keep the old route live while the new one is proven, I am not migrating yet.

Treating “App Router” on a job post as the architecture. The folder on disk is the architecture.

What I will take

I take the messy case: old pages/, a mixed tree, a route that still needs getServerSideProps until we can walk the cache. I will also take a new app/ tree. I will not take a rewrite of the whole site with no owner for each URL.

If you want this owned on your product, that is the work on Hire a Next.js developer. Send the repo or the ticket.

Tags:

Aris Setiawan

Aris Setiawan

Senior Full Stack Developer specializing in Next.js, React, and WordPress. I write about web development, performance optimization, and best practices.

Related Articles