Private Folders and the Underscore Convention in Next.js

Prefixing a folder with an underscore opts it and everything inside it out of routing. Learn when this convention helps beyond normal colocation.

5 min read

Next.js private folders are folders whose name starts with an underscore. Naming a folder this way tells the router to skip it, and everything nested inside it, when building routes for the app directory.

texttext
app/
  blog/
    _components/
      PostCard.tsx
    page.tsx

The _components folder and the file inside it are never reachable as a URL, no matter what they are named. Even a file literally named page.tsx inside _components would stay private, because the underscore opts the whole subtree out of routing.

Colocation already works without this

Any file inside the app directory that is not named page, route, layout, or one of the other routing conventions is already safe to colocate. A component or helper function placed next to a page never becomes a URL on its own. Private folders add an explicit signal on top of that default, rather than being required to make colocation work.

Why reach for one anyway

A private folder is useful when a naming collision is a real risk, or when a clearer visual split between UI code and routing code helps a team scan a project faster. It is also useful for consistency, since many Next.js example projects and libraries use the same underscore convention for their own internal folders.

SituationPrivate folder helps
Avoiding a future clash with a new file conventionYes
Sorting internal files to the top or bottom in an editorYes
Making a route publicly reachableNo, the opposite

Creating a URL segment that starts with an underscore

Occasionally a project genuinely needs a URL segment beginning with an underscore, such as a username-based route where a username can start with one. Prefix the folder with %5F, the URL-encoded form of an underscore, instead of a literal underscore.

texttext
app/
  %5Fspecial-user/
    page.tsx

This folder routes normally to /_special-user, because %5F avoids triggering the private folder convention while still producing a leading underscore in the resulting path.

Common mistake

Assuming a private folder is required for safety is a common misunderstanding. Skipping the underscore does not make a component or utility file routable by accident, since only the specific reserved file names trigger routing behavior.

The other common mistake is confusing this convention with route groups. A private folder hides everything inside it from routing entirely, while a route group still routes its contents normally and only hides the folder name from the URL.

For the parenthesis-based convention that organizes routes without hiding them from routing, see route groups in Next.js. Both conventions are covered together in how file-based routing works in the Next.js App Router.

Rune AI

Rune AI

Key Insights

  • Prefix a folder name with an underscore to opt it out of routing entirely.
  • The opt-out applies to the folder and every subfolder inside it.
  • Regular colocation already keeps non-routing files safe without this prefix.
  • Use %5F instead of a literal underscore for a URL segment that needs one.
  • Private folders help most when avoiding naming conflicts with future file conventions.
RunePowered by Rune AI

Frequently Asked Questions

Do I need private folders for colocation to work?

No. Files inside app are already safe to colocate by default, since only a page or route file makes a segment public. Private folders add an explicit signal on top of that, not a requirement for it.

Can I create a URL segment that literally starts with an underscore?

Yes, by using %5F instead of a literal underscore in the folder name. That URL-encoded form does not trigger the private folder convention.

Does an underscore prefix work at any depth?

Yes. Prefixing a folder opts that folder and every subfolder inside it out of routing, no matter how deeply nested the structure underneath it is.

Conclusion

A private folder, created by prefixing its name with an underscore, tells Next.js to skip that folder and everything inside it when building routes. Reach for one when a naming collision or a clearer split between UI and routing code is worth the extra signal.