Folder-Based Routing
Folders inside src/app define URL segments. Each folder becomes a part of the URL path.
Overview
Bini.js uses folder-based routing - every folder inside src/app/ becomes a URL segment. Add page.tsx inside that folder to make the route accessible.
Folder names must be valid URL segments and the structure directly maps to the URL path.
| Folder Pattern | URL | Type |
|---|---|---|
| app/about/page.tsx | /about | Static folder - creates URL |
| app/blog/page.tsx | /blog | Static folder - creates URL |
| app/dashboard/settings/page.tsx | /dashboard/settings | Nested folder - creates URL |
| app/(marketing)/about/page.tsx | /about | Route group - folder ignored, no extra segment |
| app/_components/Header.tsx | - | Private folder _ - no URL |
| app/.internal/page.tsx | - | Private folder . - no URL |
Basic Folder Routing
Every folder becomes a segment. Add page.tsx to expose it. index.tsx also maps to its parent.
export default function AboutPage() {
return <h1>About</h1>
}page.tsx creates a URL. This keeps layouts, loading, and error boundaries co-located per folder.Nested Routes
Nest folders to create nested URL segments. Each nested folder adds a segment and creates a URL.
export default function AuthorsPage() {
return (
<ul>
<li>Alice</li>
<li>Bob</li>
</ul>
)
}Route Groups
(group) organizes folders without affecting URL. The group folder does not create a URL segment.
export default function MarketingLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<div>
<nav>Marketing Nav</nav>
<main>{children}</main>
</div>
)
}URLs are /, /about, /pricing, /dashboard - the (marketing) and (app) folders don't create URL segments.
Private Folders (Private Routes)
Private folders are folder-based private routes - prefix a folder with _ or . to exclude it from routing. They do not create URLs.
| Folder Pattern | Creates URL? | Description |
|---|---|---|
| _components | No | Private folder - _ prefix - no URL |
| _lib, _hooks | No | Private folders - no URL |
| .hidden, .internal | No | Dot prefix - private - no URL |
| blog/_components | No | Private inside route - no URL |
| (group) | No extra segment | Route group - folder ignored |
| blog, about | Yes | Public folder with page.tsx - creates URL |
_ or .) do not create URLs. Use them to keep components, utils, and hooks next to the route that uses them. Static and nested folders with page.tsx do create URLs.Nearest Wins with Folders
loading.tsx, not-found.tsx, error.tsx use nearest-wins resolution for folder hierarchy. A file in a subfolder only affects that subfolder.
Resolution: route's own folder → parent folders → built-in default.
export default function DashboardLoading() {
return <p>Loading dashboard…</p>
}Route Priority
In folder-based routing, static folders define exact routes and create URLs. Shorter paths are matched first.
- Static folders - exact matches like
about/page.tsx→/about- creates URL - Nested folders -
blog/authors/page.tsx→/blog/authors- creates URL - Route groups -
(marketing)/about/page.tsx→/about- no extra segment - Private folders -
_components,.internal- no URL
Complete Example
Complete folder-based routing example showing which folders create URLs and which don't.
| Folder Path | URL | Creates URL? |
|---|---|---|
| app/page.tsx | / | Yes - creates URL |
| app/about/page.tsx | /about | Yes - static folder creates URL |
| app/blog/page.tsx | /blog | Yes - static folder creates URL |
| app/blog/authors/page.tsx | /blog/authors | Yes - nested folder creates URL |
| app/dashboard/settings/profile/page.tsx | /dashboard/settings/profile | Yes - deeply nested creates URL |
| app/(marketing)/about/page.tsx | /about | Yes, but group folder ignored |
| app/_components/Header.tsx | - | No - private folder, no URL |
| app/.internal/config.ts | - | No - private folder, no URL |
| app/blog/_components/PostCard.tsx | - | No - private inside route, no URL |
page.tsx create URLs. Private folders (_ / .) and route groups (group) do not create extra URL segments. Private folders are for organizing code without creating URLs.