Route Groups and Project Organization

Beginner
10 min

Route Groups and Project Organization

As an application grows, the app/ folder starts to fight you: marketing pages want a different shell from the logged-in area, helper components end up next to routes, and URLs mirror folder names whether you like it or not. Route groups, private folders and the src/ directory solve these problems. After this lesson you will be able to organise a large App Router project so that folder structure serves the team without leaking into URLs.

Route Groups: Folders That Do Not Affect the URL

Wrap a folder name in parentheses and Next.js omits it from the path:

text
app/ ├── (marketing)/ │ ├── layout.tsx # marketing layout │ ├── page.tsx # / │ └── pricing/page.tsx # /pricing └── (app)/ ├── layout.tsx # application layout └── dashboard/page.tsx # /dashboard

/pricing and /dashboard are served as if the groups did not exist, yet each group has its own layout.tsx. This is the standard way to give sections of a site different navigation, sidebars or metadata without adding a URL prefix. Groups can also be used purely for tidiness, for example (shop) and (account), with no layout at all.

Two rules to remember:

  • Two groups must not resolve to the same URL. (marketing)/about/page.tsx and (app)/about/page.tsx both map to /about and the build fails.
  • Navigating between pages in different root layouts triggers a full page load rather than a client-side transition.

Multiple Root Layouts

If you delete the top-level app/layout.tsx and give every route group its own layout containing <html> and <body>, each group becomes an independent application shell. This is useful when a documentation site and a web app share one deployment but nothing else:

tsx
// app/(docs)/layout.tsx export default function DocsLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en"> <body className="docs-theme">{children}</body> </html> ); }

The page for / must then live inside one of the groups, for example app/(marketing)/page.tsx.

Private Folders and Colocation

Only page.tsx and route.ts make a folder publicly reachable, so you can safely keep components, tests and utilities next to the routes that use them. To make the intent explicit, prefix a folder with an underscore:

text
app/ ├── dashboard/ │ ├── _components/Chart.tsx # not a route │ ├── _lib/queries.ts # not a route │ └── page.tsx # /dashboard

A private folder and everything inside it is excluded from routing entirely. It also keeps generated route types clean. If you ever need a real URL segment that starts with an underscore, use the encoded form %5Ffolder.

The src Directory and Shared Code

Many teams move app/ into src/ so configuration files stay at the project root while application code (src/app, src/components, src/lib, src/hooks) sits together. create-next-app offers this layout as a prompt and configures an import alias:

json
{ "compilerOptions": { "paths": { "@/*": ["./src/*"] } } }

With the alias, any file imports shared code as import { db } from "@/lib/db" regardless of how deep it lives. public/, next.config.ts and package.json always stay at the root.

| Convention | Effect on URL | Typical use | |---|---|---| | (group) | Removed from the path | Separate layouts, logical sections | | _folder | Never routable | Colocated components and helpers | | [param] | Dynamic segment | Details pages | | src/app | None | Keeps root directory tidy |

Tips

  • Name groups after intent, not layout details: (auth), (marketing), (dashboard).
  • Keep the root layout.tsx for truly global concerns (fonts, providers, analytics) and push everything else into group layouts.
  • Do not nest groups more than one level deep; it becomes hard to see which layout applies.
Quick Quiz
Question 1 of 3

What URL does `app/(shop)/cart/page.tsx` serve?

Key Takeaways

  • Route groups (name) organise routes and attach layouts without changing URLs.
  • Removing app/layout.tsx and giving each group its own <html> layout creates multiple root layouts.
  • Private folders _name are never routable, making colocation of components safe and explicit.
  • The src/ directory separates application code from root configuration files.
  • Conflicting paths across groups fail the build; keep group names descriptive and shallow.

Next lesson: Linking and Navigation — use the Link component for fast client-side transitions and prefetching.

Route Groups and Project Organization - Next.js | CodeYourCraft | CodeYourCraft