Skip to main content
ASoc
Tutorial

Next.js Route Groups: Why This 24-Route App Uses Zero

Route groups hide a folder from the URL. Every one of this app's 24 top-level folders needs to be in the URL — which is the exact case they're not for.

The ASoc Team9 min read

Route groups — folders wrapped in parentheses, like (marketing) — let multiple URL trees share a layout, or let you organize files without changing a URL. This storefront's src/app has 24 top-level route folders and uses zero route groups, and that's not a gap: only one of those folders needs a layout different from the root, and it already has a literal name because the URL requires one anyway.

When a route group actually earns its keep

Next.js's own docs describe two jobs for the (folderName) convention: organizing routes into groups without affecting the URL path, and opting subsets of routes into different root layouts. Both jobs solve the same underlying problem — you want a folder boundary that the URL doesn't need to know about.

That problem shows up when an app has routes that logically belong together (say, everything under a (marketing) umbrella and everything under an (app) umbrella) but neither umbrella corresponds to a real URL segment a visitor should ever see or type. Wrapping them in parentheses gives you app/(marketing)/pricing/page.tsx rendering at /pricing, not /marketing/pricing, while still letting (marketing) carry its own layout.tsx.

What this repo has instead: a flat root, one exception

src/app has exactly one nested layout file besides the root:

src/app/layout.tsx          — the site-wide shell (fonts, header, footer)
src/app/dashboard/layout.tsx — the only route with a second layout

Every other top-level folder — templates, blog, docs, pricing, contact, login, signup, the seven pSEO spokes (nextjs-admin-template, tailwind-shop-template, and so on) — renders under the root layout directly, with no layout override of its own. Two layout files across 24 top-level route folders is a genuinely flat tree, and it's flat by a documented design decision, not by accident: this repo's own conventions state that "product URLs stay flat" for the catalog and that the pSEO spokes are indexable, named routes in their own right — /nextjs-admin-template, not /spokes/nextjs-admin-template or /marketing/nextjs-admin-template. Every one of those top-level names is content a visitor is meant to see in the address bar and a search result, which is the exact case route groups are not for — a route group's whole purpose is hiding a folder from the URL, and every folder in src/app needs to be in the URL.

The one folder that does diverge — dashboard, with its own layout.tsx gating on a signed-in session — doesn't need a route group either, for a simpler reason: it's already a single, already-named segment. A route group buys you a shared layout across multiple URL branches that don't otherwise nest under a common real segment. dashboard is one segment nesting one layout under it in the ordinary way Next.js has supported since routes had layouts at all — app/dashboard/layout.tsx applies to app/dashboard/** with no parentheses required. Route groups solve a problem this repo doesn't have: multiple, separately-named top-level routes that need to share a layout without merging into one URL parent.

A worked example, for the shape this repo doesn't use

Since there's no route group in this codebase to show directly, here's the pattern applied to a hypothetical version of this same app that did need one — say, a variant that wanted (marketing) and (app) to each carry their own root-level layout without introducing a /marketing or /app URL segment:

app/
  (marketing)/
    layout.tsx        → wraps every marketing page in the public header/footer
    page.tsx          → renders at  /
    pricing/
      page.tsx        → renders at  /pricing
  (app)/
    layout.tsx        → wraps every app page in the dashboard shell instead
    dashboard/
      page.tsx        → renders at  /dashboard

(marketing) and (app) never appear in the URL — /pricing and /dashboard are exactly what they'd be without the parentheses — but each subtree now renders under a different layout.tsx. That's the one thing a route group buys you that a plain nested folder can't: two root-level layouts, applied by folder rather than by writing conditional logic inside a single shared layout. This repo doesn't need that trade because it only has one layout that isn't the root layout, and that one already lives at a named URL.

The other use case: organizing without a layout change

Route groups' second job — bundling files by team or feature with zero effect on URL or layout — is a real pattern this codebase already applies, just not to routes. src/components/ is organized by Atomic Design: atoms, molecules, organisms, templates, each folder a purely organizational boundary that never appears in an import path's meaning to the app, only in where a file happens to live on disk. A route group is the same idea aimed at app/ instead of components/ — a folder that exists for the person reading the codebase, not for the URL or the render tree.

The reason app/ doesn't have an equivalent isn't that the idea doesn't apply — it's that every folder already needs a name for a reason unrelated to organization. templates/, blog/, pricing/, the seven pSEO spokes: each one is a real, indexable URL segment first, and incidentally also an organizational grouping of related files second. There's no folder in this tree that exists purely to group things, the way an (marketing) or (admin-tools) route group would, because every folder's name is already doing load-bearing work as a URL.

Troubleshooting

SymptomCauseFix
"Next.js route groups not working" — the grouped route 404sParentheses typo'd, or the folder is missing a page.tsx/layout.tsx inside itRoute groups are purely a naming convention — (name) must match exactly, and the folder still needs real route files inside
Two folders resolve to the same URL and the build failsTwo different route groups define the same path — e.g. (marketing)/about/page.tsx and (app)/about/page.tsx both resolve to /aboutNext.js treats this as a genuine collision; rename one of the conflicting segments, since route groups don't create separate namespaces for the same path
Navigating between two route-grouped sections causes a full page reload instead of a client transitionThe two groups render different root layouts, and React has to remount the tree when the layout itself changesExpected behavior, not a bug — a full reload is the cost of swapping root layouts; keep genuinely shared chrome in one common layout if the reload is unwanted
A route group was added purely "to organize files" and nothing changedThat's the other legitimate use — grouping by team or feature with zero URL or layout effect — so no visible change is correctConfirm the folders inside still contain real page.tsx files; an empty organizational group with nothing routable inside it does nothing at all
Unsure whether a new section needs a route groupThe section needs its own root layout that a nested layout can't express as cleanly, or the URL must not gain a segment for itIf a plain nested folder already gives you the right layout and the right URL — as dashboard/ does here — a route group adds parentheses with no additional benefit

FAQ

How do I add route groups in Next.js? Wrap the folder name in parentheses — (folderName) — anywhere under app/. The parentheses are stripped from the resulting URL; everything else about the folder (nested routes, its own layout.tsx) works exactly as it would unwrapped.

What are Next.js route groups best practices? Reach for one only when you need either (a) a shared layout across routes that don't already nest under one real URL segment, or (b) to organize files by team or feature with zero effect on routing. If a route group would wrap a single named segment — the way dashboard/ sits in this repo — a plain folder does the same job with one less piece of naming convention to explain.

Can two route groups define routes at the same URL? No — Next.js resolves both to the same path and errors at build time if they collide. Route groups don't create separate URL namespaces; they're a build-time folder convention, not a runtime routing layer.

Does a route group change how a route is fetched or rendered — SSG vs SSR? No. Route groups are purely organizational; they have no effect on a route's rendering mode. The static-rendering audit covers what actually pushes a route off static generation in this codebase, and none of the four triggers there involve folder structure.

Templates in this post

ASoc Pulse Admin ships five separate dashboards inside one product — a commerce-ops back office where multiple dashboard "modes" sharing one authenticated shell is exactly the kind of layout-sharing problem route groups are built to solve, if those modes ever needed visually distinct layouts of their own. ASoc Scholar Admin, at 13 dashboards and 210+ pages, is the largest admin product in the catalog and the one most likely to eventually want route groups purely for file organization, independent of any layout change. ASoc Vertex Admin is a sales-analytics dashboard with a full sidebar shell — a single-layout admin app, the same one-layout-one-folder shape this post's own dashboard/ route uses.

Browse the full sets: React admin templates, Next.js admin templates, Tailwind admin templates. For what actually determines a route's rendering mode in this codebase, see the static-rendering audit.

Keep reading

Tutorial12 min read

Next.js Routing: 27 Page Files, 412 URLs, Three Conventions Unused

A census of one production app/ tree: which of the nine reserved filenames actually earn a file, and the 40 links, 13 redirects and 2 routers that move between them.

Read more
Tutorial10 min read

An RSS Feed in the App Router, Without an RSS Library

One route file, force-static, and eight lines of helpers. RFC-822 dates, five escaped characters, and the absolute-URL bug that reached our production markup.

Read more
Tutorial12 min read

Building a SaaS Landing Page in Next.js 16 That Loads Fast

Static rendering, LCP on the hero, and a small client bundle — plus the accessibility bugs our own Lighthouse audit caught that code review missed.

Read more