# 5 Next.js Folder Structures That Scale

*Originally published at* [*techpotions.com*](https://techpotions.com/lab/best-next-js-folder-structure)*.*

Picking the **best next js folder structure** for a production Next.js app can feel like choosing a house frame before you've even poured the foundation. Too rigid and you fight the routing model. Too loose and your codebase becomes a haunted house where imports rot in the dark. At techpotions, we've just finished shipping a multi-tenant SaaS analytics dashboard, real users, real server actions, real pain. We tried five distinct folder strategies, broke things in staging, and kept the ones that survived. Here's what we learned, tradeoffs included.

## Why the best next js folder structure depends on your app's growth trajectory

Before you rearrange `app/`, remember that Next.js itself [doesn't mandate a single layout](https://nextjs.org/docs/app/getting-started/project-structure). It supports an optional `src` folder, and the router can sit inside `app/` or be nested deeper. Owais's [architecture guide](https://buildwithowais.com/blog/nextjs-architecture) wisely points out that architecture is four decisions, rendering, boundaries, data access, and colocation, not just a folder tree. So the best next js folder structure is the one that answers those decisions for your team.

Our own dashboard project cycled through these five, each solving a different phase of the product. The real test came when three engineers started shipping in parallel and server actions multiplied.

## 1\. Flat `app/` with colocated server actions, the starter trap

**Best for:** MVPs, solo devs, or internal tools that need speed over scale. **Tradeoff:** routes and logic fuse into a mess that's impossible to test or refactor.

When we bootstrapped the dashboard, we dumped everything inside `app/`: a `dashboard/layout.tsx` next to a `serverActions.ts` that handled every mutation. For the first two months it felt frictionless, one click, one file. The problem hit when we needed to reuse the same data-fetching function from a cron job. We couldn't import an `app/` server action from outside the router without hacks, so we duplicated logic. Then the layout grew into a 1,200-line God component, and even [the official Next.js docs](https://nextjs.org/docs/app/getting-started/project-structure) emphasize that `app/` is primarily for routing, not shared business logic.

**When it broke for us:** A teammate renamed a `layout.tsx` and accidentally untangled the React context tree. 15 pages went blank in production. That's when we knew we needed co-location that is decoupled from the route hierarchy.

> This approach aligns with small-to-medium projects, but if you're scaling, our [web development services](https://techpotions.com/services/web) team often recommends extracting logic early.

## 2\. `src/` with route-based colocation, the official safety net

**Best for:** teams that want a clean separation between config and code, without over-engineering. **Tradeoff:** still allows business logic to leak into the router if you aren't disciplined.

Next.js encourages putting application code inside an optional [`src` directory](https://nextjs.org/docs/app/getting-started/project-structure). We moved to `src/app/` and kept all config, tests, and utilities at root. The `app/` directory now contained only route segments and UI components, while `src/lib/` held our Prisma client and auth helpers. It felt like a step up, our [Next.js development company](https://techpotions.com/solutions/nextjs-development-company) uses this foundation for most client projects because it's easy to explain.

**What stuck:** Having `src/hooks/` and `src/utils/` outside the router meant we could `import { useAuth } from '@/hooks/auth'` from any route without path-traversal acrobatics. The **best next js folder structure** for maintainability often starts right here.

**What still hurt:** Server actions for a specific dashboard widget lived in `src/app/dashboard/actions.ts`. When the widget moved to a new URL, the actions didn't move with it, or worse, they stayed, coupling an old route to fresh business logic. This showed us we needed to group by *feature*, not by *URL*.

## 3\. Feature-first with `src/features/`, the team aligner

**Best for:** multi-team applications where features own their full lifecycle: UI, API, types, tests. **Tradeoff:** hard to enforce without linting, and newcomers over-decompose into micro-features prematurely.

After the server-action scattering incident, we adopted a structure [popularized in large-scale Next.js guides](https://www.groovyweb.co/blog/nextjs-project-structure-full-stack):

```text
src/
├── features/
│   ├── analytics/
│   │   ├── api/          # server actions, tRPC routers, services
│   │   ├── components/   # Dashboard widgets, charts
│   │   ├── hooks/        # client‑side state
│   │   └── __tests__/
│   └── billing/
│       ├── api/
│       ├── components/
│       └── ...
└── app/                  # thin wrapper, mapping URLs → features
```

The `app/dashboard/page.tsx` became a three-liner that imported `<AnalyticsDashboard />` from `@/features/analytics`. Server actions lived in `src/features/analytics/api/actions.ts` and were importable from cron jobs, webhooks, and even a separate NestJS worker we ran. This isolation allowed two teams to work on `analytics` and `billing` simultaneously without merge conflicts.

**What broke in production:** We initially created 42 feature folders, many housing a single component. A mid-sized app with a dozen clear domains like ours didn't need that granularity; it added indirection without value. We later merged related features, turning `chart-renderer`, `export-csv`, and `date-picker` into one `analytics` domain with internal sub-folders. The **best next js folder structure** balances colocation with sanity.

**Real-world lesson:** Only create a feature folder when a distinct user story and a dedicated data source exist. Otherwise, leave it in `src/components/shared`.

## 4\. Hybrid: feature folders inside `app/` route groups, the Next.js power move

**Best for:** teams that want the route-awareness of App Router with the modularity of feature-first, without a separate `features/` bucket. **Tradeoff:** even stricter discipline required; you're one `use client` away from tangling the boundary.

The App Router's [route groups, `(group)/`](https://nextjs.org/docs/app/building-your-application/routing/route-groups) let you colocate feature folders directly next to their pages, without affecting the URL. We experimented with:

```text
src/app/(dashboard)/
├── _features/
│   ├── analytics/
│   └── billing/
├── analytics/page.tsx   # imports from _features/analytics
└── layout.tsx
```

The `_features/` prefix tells Next.js to ignore it as a route, so it becomes pure organization. This felt like the **best next js folder structure** for smaller apps that still want feature isolation but hate the mental model of a separate `src/features/` universe. It also keeps server actions physically close to the page, reducing the "where is this action?" confusion.

**The production scare:** A junior developer accidentally imported a client component from `_features/` into a server layout. The build didn't complain, it just silently made the whole dashboard a client tree, killing our previous SSR performance. We fixed it with a barrel-file convention and a custom ESLint rule, but it reminded us that physical proximity can erode careful boundaries.

**Verdict:** Use this only when you have a rock-solid `use client` boundary rule and a small enough codebase to police it manually.

## 5\. Atomic design plus domain, the enterprise drift

**Best for:** design systems that evolve alongside the app, or when a shared component library must stay independent of any single feature. **Tradeoff:** overwhelming for product engineers; often results in premature abstraction and endless restructuring debates.

We saw the [Reddit thread](https://www.reddit.com/r/nextjs/comments/1psrdiz/i_wrote_a_practical_guide_on_nextjs_folder/) and the [Atomic Design guide](https://profolderai.com/nextjs-project-structure-guide/) and decided to try applying it to our dashboard. The result was a `src/lib/atoms/`, `src/lib/molecules/`, `src/lib/organisms/` hierarchy, with domain logic still living in `src/features/`. The idea was that the design system would be a pure UI layer, and features would compose them.

**What worked:** Our design team loved it because they could see every button, input, and card in a Storybook that mirrored the folder tree. The shared [component structure](https://medium.com/skillstuff/the-scalable-next-js-folder-structure-every-large-project-needs-b440178821f4) kept branding consistent across six external partners who white-labeled the dashboard.

**What broke:** Product engineers started building features *inside* the atomic folders because the boundaries were too abstract. We'd find `analyticsCard` in `molecules/` that imported a server action directly, breaking the separation contract. Eventually, we killed the atomic prefix and kept a plain `src/components/ui/` with a flat structure; feature teams never got lost again.

**Real-world take:** Atomic Design is a design-system pattern first, not a file-system one. Enforce it with tooling, Storybook, ESLint import boundaries, or not at all.

## Structuring decisions that saved us more than any folder name

Regardless of the shape you pick, three rules emerged from our gut punches:

1.  **Colocate by concern, not by type.** Don't put all `actions.ts` in a global `api/` folder; put the actions that serve a feature with that feature. The best next js folder structure is a map of your product, not a taxonomy of file extensions.
    
2.  **Barrel files are your friend.** A single `index.ts` per domain exports only the public API; internal helpers stay private. This gives you a hard module boundary without a monorepo.
    
3.  **Lint your imports.** We added `eslint-plugin-import` rules that forbid feature `A` from importing from feature `B`'s internals. It catches the sprawl early.
    

Still not sure which path fits your app? Our [Next.js development company](https://techpotions.com/solutions/nextjs-development-company) has built 40+ production apps and we pick the structure on the first sprint, so you don't have to refactor three months later. [Explore our web projects](https://techpotions.com/services/web) to see the patterns in action.

## FAQ

### What is the best Next.js folder structure for a large app with many teams?

The most scalable approach for large teams is feature-first in `src/features/`, with co-located route trees, UI components, and data access. It keeps related code together so features can evolve independently without creating merge hell.

### Should I use a `src` folder in my Next.js project?

Yes. If you use the optional `src` folder, only the `app/`, or `pages/`, router lives inside `src` while everything else, like tests, fixtures, and local utils, stays root-level. This keeps your codebase tidy and aligns with the [official convention](https://nextjs.org/docs/app/getting-started/project-structure).

### When should I refactor my existing Next.js folder structure?

If routes are growing fast and server actions are sprinkled across `app/` directories, it's time. A clear sign is when you can't refactor a feature without touching 10 different folders. Extraction into `src/features/` makes boundaries explicit.
