Lesson 3 of 81
Every folder in app/ becomes a URL segment by default — until you tell the router otherwise. Route groups and private folders are the two ways to opt a folder out of that default without moving files anywhere.
9 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 3
`app/dashboard/_internal/page.tsx` exists — a `page.tsx` file inside an underscore-prefixed folder. Is `/dashboard/internal` (or any variant) reachable?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
In the App Router, folder nesting normally maps directly onto URL structure: app/blog/posts/page.tsx is /blog/posts. Two conventions let you organize files into folders without that folder name showing up in the URL:
(folderName). Wrapping a folder name in parentheses tells the router "this folder is for organization only, don't add it to the path." app/(marketing)/about/page.tsx still resolves to /about, not /marketing/about. The main reason to reach for this: it lets you attach a different layout.tsx to different sections of your app that otherwise sit at the same URL depth — including giving each section its own root layout (its own <html>/<body>)._folderName. Prefixing a folder with an underscore opts that folder and everything inside it out of routing entirely, even if it contains a page.tsx. This is where you colocate components, hooks, or utilities that belong to a specific route but shouldn't be reachable as one — app/dashboard/_components/StatsCard.tsx is never a URL, no matter what's inside it.app/
├── (marketing)/
│ ├── layout.tsx → root layout #1: public nav, footer, <html>/<body>
│ ├── page.tsx → "/"
│ └── pricing/page.tsx → "/pricing"
├── (app)/
│ ├── layout.tsx → root layout #2: sidebar shell, its own <html>/<body>
│ ├── dashboard/
│ │ ├── _components/
│ │ │ └── RevenueChart.tsx → not a route, just colocated UI
│ │ └── page.tsx → "/dashboard"
Neither (marketing) nor (app) appears in any URL — /, /pricing, and /dashboard are the actual paths. But each group gets its own layout.tsx, and because there's no shared app/layout.tsx above them, both are root layouts: each must independently define its own <html> and <body> tags. _components/RevenueChart.tsx sits right next to the dashboard page that uses it, but the router never considers it a route candidate, underscore-prefixed or not.
(marketing)/about/page.tsx and (shop)/about/page.tsx both resolve to /about — since the group names are invisible to the URL, the router sees two files both claiming the same path and errors.page.tsx several levels deep inside a _folder is still unreachable, it doesn't "escape" back into routing just by having the right filename./) needs to live inside one of them — there's no implicit top-level layout left to fall back on once you've removed app/layout.tsx.%5F-encoding, since a bare underscore prefix always means "private" to the router."How would you give your marketing pages and your logged-in app completely different shells, sharing one codebase?" is a real architecture question, and route groups with multiple root layouts is the actual, current Next.js answer — confusing it with private folders (which do the opposite: hide files from routing rather than reorganize URL-visible sections) is a common tell that the candidate hasn't used the App Router in a real project.