How to Organize Next js 15 App Router Folder Structure

Let me walk through, step-by-step, how I organize a scalable Next.js project folder structure using the latest App Router. I’ll keep it as practical and conversational as possible, sharing the logic I use daily for clean, maintainable code.
Why Getting Your Folder Structure Right Matters
Before jumping in, I want to explain why I care so much about folder structure. When starting a new Next.js project, especially with the App Router, how folders are laid out will either save me loads of time—or cause total chaos as the codebase grows.
With good structure, new routes, features, and even teammates can fit in seamlessly. Messy structure means time wasted hunting for files, risking bugs, and ugly merges. Whenever I need to scale the project or migrate to new Next.js features, having a scalable folder tree makes me grateful I took a little extra time in the beginning.
The Basic Folder Layout I Always Use
Here’s a simple root-level example, which works for most Next.js projects:
“App Router” means the app/
folder is the star of the show. In there, nested folders become route segments for your site, so /app/blog/page.js
maps nicely to /blog
, and so forth.
How I Organize Routes Inside app/
Here’s the thing—every folder inside app/
is basically a different part of your website. If I create an /blog
route, I add a blog
folder. If I need a /about
page, I make an about
folder.
Each route folder will usually have a page.js
(or page.tsx
if using TypeScript), which defines what people see. But Next.js lets me add even more files:
layout.js
for shared UI like headers or navbarsloading.js
for skeleton loading stateserror.js
to handle errors for just that routeroute.js
for API endpoints exposed at that path
For example, here’s how a few sections might look:
I like to keep each route’s concern together with it—making it easy to find, edit, and test logic tied to just that part of the project.
Co-locating Route-Specific Components, Hooks, and Logic
One of the coolest things about App Router is colocation. I can put route-specific components, hooks, and helper files right inside the route folder itself. So, if /dashboard
has charts and complex logic unique to dashboards, they belong inside app/dashboard/
, not floating somewhere else.
Example structure:
This way, logic unique to the dashboard is nearby, and I’ll never confuse these helpers or components with reusable ones used elsewhere in the app.
Anything shared between routes—like a nav bar, button, or date helper—stays outside app/
, in folders like components/
or utils/
at the root.
Route Groups and Private Folders
Sometimes, I need folders in app/
for structure, but I don’t want them showing up in the URL. Next.js provides route groups and private folders for this. Here’s how I use them:
- Route Groups: Wrap the folder name in parentheses:
(admin)
,(marketing)
. Next.js ignores these folders in the final URL; they’re just for organization. For example,app/(admin)/users/page.tsx
maps to/users
, not/admin/users
. - Private Folders: Prefix folder names with an underscore, like
_components
or_hooks
, to hide them from routing.
A practical example:
This setup keeps “admin” and “shop” files grouped, without messing up public URLs.
Keeping Global Stuff Out of app/
A big mistake is dumping everything in the app/
folder. If a piece of code—a Button, a utility function, or a model—is used in several routes, I put it in a top-level folder like components/
or utils/
. This makes it easy to import from anywhere and avoids duplication.
For example, a reusable Avatar
component goes in components/
, not inside app/dashboard/components/
if it’s also used in other places.
This rule keeps my project easy to maintain, update, and migrate. If everything lives inside route-specific folders, I’ll end up copying code everywhere. So, for shared stuff, global location wins.
Special Next.js Files
Next.js App Router recognizes certain filenames inside the route segment folders:
page.js
orpage.tsx
: Main UI for a routelayout.js
: Shared UI wrappers for child routesloading.js
: Custom loading stateerror.js
: Route-specific error handlingroute.js
: Server API endpoints
Every time I need a new feature, I think: Does this belong everywhere? (root-level), or is it just for one route (inside that route’s folder)? When in doubt, colocate with the route, and only globalize if it’s reused.
How Static Files Work
public/
is for things like images, icons, pdfs, etc. It sits outside app/
, and those files are instantly served as static assets—no processing, just direct access. So, stuff like logos or product images live here, referenced from everywhere in the app by /logo.png
or similar.
Example: Simple Real-world App Structure
Here’s how a medium-sized app of mine might look after a few features:
This setup keeps everything organized, scalable, and clean. Each big feature gets its own section, while shared stuff stays easy to access. Adding a new route or feature? Just drop a folder inside app/
with its logic, UI, and helpers.
My Final Tips
- Think feature-first. Organize by feature, not just file type. If dashboards or shops have lots of custom stuff, give each a folder with its own subfolders.
- Route groups and private folders are your friend—use them to keep things uncluttered.
- Keep shared code out of
app/
—store global helpers, components, and utilities at the root. - Document your structure for teammates to help onboard quickly and stay consistent.
For me, sticking to these patterns means my Next.js projects are always easy to navigate, scale, and maintain—no matter how big they get. If you ever need to refactor or migrate, a clear folder layout is the best insurance.
And that’s my personal approach to building a scalable Next.js project folder structure with the App Router! Hope this helps anyone looking to build clean, future-proof Next.js applications.