
You've just started a new Next.js 15 project, opened up your code editor, and now you're staring at an empty directory structure. The question hits you: "How should I organize all my files and folders to keep this project maintainable as it grows?"
If you're feeling overwhelmed by folder organization in Next.js 15, especially with the App Router, you're not alone. Many developers struggle with questions like:
- Should everything go in the - appfolder, or should I use- src?
- Where should I put my reusable components? 
- How do I organize utilities and libraries? 
- What's the best way to structure a project that might grow into a monorepo? 
This comprehensive guide will walk you through a battle-tested Next.js 15 folder structure that scales well and keeps your codebase maintainable.
Core Project Structure
Let's start with the foundation. Here's a high-level overview of a well-organized Next.js 15 project:
├── src/
│   ├── app/
│   ├── components/
│   ├── lib/
│   ├── utils/
│   └── styles/
├── public/
├── package.json
└── next.config.js
The src Directory Debate
One of the first decisions you'll face is whether to use a src directory. While Next.js works perfectly fine without it, using a src directory offers several benefits:
- Clear separation between source code and configuration files 
- Easier to implement tooling and build processes 
- Cleaner root directory 
- More consistent with other JavaScript/TypeScript projects 
According to discussions in the Next.js community, many developers prefer using a src directory for better organization, especially in larger projects.
The app Directory
With Next.js 15's App Router, the app directory is where your routing magic happens. Here's how to structure it effectively:
src/app/
├── layout.tsx
├── page.tsx
├── (auth)/
│   ├── login/
│   └── register/
├── dashboard/
│   ├── layout.tsx
│   ├── page.tsx
│   └── settings/
└── api/
This structure follows Next.js 15's routing conventions where:
- Files directly in - appaffect the root route
- Folders create new routes 
- Parentheses - ()create route groups that don't affect the URL structure
- Special files like - layout.tsxand- page.tsxserve specific purposes in the routing system
Organizing Components
The components directory is often the heart of your Next.js application. Here's a proven structure that scales well:
src/components/
├── ui/
│   ├── Button/
│   │   ├── Button.tsx
│   │   ├── Button.test.tsx
│   │   └── index.ts
│   ├── Card/
│   └── Modal/
├── layout/
│   ├── Header/
│   ├── Footer/
│   └── Sidebar/
└── features/
    ├── auth/
    └── dashboard/
UI Components
The ui folder contains your basic building blocks - reusable components that aren't tied to specific business logic. These are your buttons, inputs, cards, and modals.
Layout Components
Layout components are larger pieces that form your application's structure. They're typically used across multiple pages but might have more specific functionality than UI components.
Feature Components
Feature components are tied to specific business features or domains. For example, a LoginForm component would go in features/auth/, while a DashboardStats component belongs in features/dashboard/.
Managing Utilities and Libraries
The distinction between utils and lib often causes confusion. Here's how to organize them effectively:
src/
├── utils/
│   ├── formatting.ts
│   ├── validation.ts
│   └── helpers.ts
└── lib/
    ├── auth.ts
    ├── api.ts
    └── database.ts
Utils Directory
The utils directory should contain pure utility functions that:
- Have no side effects 
- Don't depend on external services 
- Can be easily tested in isolation 
Examples include:
- Date formatting functions 
- String manipulation helpers 
- Calculation utilities 
Lib Directory
The lib directory is for more complex functionality that often:
- Interfaces with external services 
- Contains business logic 
- Manages state or side effects 
Common examples include:
- API client configurations 
- Authentication helpers 
- Database connections 
State Management and Models
When using state management solutions like Zustand, organize your store files logically:
src/
├── store/
│   ├── auth.store.ts
│   ├── user.store.ts
│   └── theme.store.ts
└── models/
    ├── user.model.ts
    └── product.model.ts
Store Organization
Each store file should:
- Focus on a specific domain 
- Export a single store instance 
- Include related actions and selectors 
Example of a well-organized store file:
// auth.store.ts
import create from 'zustand'
interface AuthStore {
  isAuthenticated: boolean
  user: User | null
  login: (credentials: Credentials) => Promise<void>
  logout: () => void
}
export const useAuthStore = create<AuthStore>((set) => ({
  isAuthenticated: false,
  user: null,
  login: async (credentials) => {
    // Implementation
  },
  logout: () => set({ isAuthenticated: false, user: null })
}))
Models
The models directory contains TypeScript interfaces and type definitions that are used across your application:
// user.model.ts
export interface User {
  id: string
  email: string
  name: string
  role: 'user' | 'admin'
}
Styling Organization
Next.js 15 supports various styling approaches. Here's how to organize them effectively:
src/
├── styles/
│   ├── global.css
│   ├── variables.css
│   └── themes/
│       ├── light.css
│       └── dark.css
└── components/
    └── Button/
        ├── Button.tsx
        └── Button.module.css
Global Styles
Keep global styles, variables, and theme definitions in the styles directory.
Component Styles
For component-specific styles:
- Use CSS Modules alongside component files 
- Name them matching the component (e.g., - Button.module.cssfor- Button.tsx)
- Keep them in the same folder as the component 
Scaling to a Monorepo
As your project grows, you might consider transitioning to a monorepo structure using tools like pnpm and Turborepo. Here's how to organize a Next.js monorepo effectively:
├── apps/
│   ├── web/
│   │   └── (Next.js app structure)
│   └── admin/
│       └── (Next.js app structure)
├── packages/
│   ├── ui/
│   ├── config/
│   └── utils/
├── pnpm-workspace.yaml
└── turbo.json
Apps Directory
The apps directory contains your Next.js applications. Each app:
- Has its own Next.js configuration 
- Can be deployed independently 
- Shares code with other apps through packages 
Packages Directory
The packages directory contains shared code:
- ui: Shared components library
- config: Common configuration files
- utils: Shared utilities
Workspace Configuration
Use pnpm-workspace.yaml to define your workspace structure:
packages:
  - 'apps/*'
  - 'packages/*'
And turbo.json for build configuration:
{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**"]
    },
    "dev": {
      "cache": false
    }
  }
}
Best Practices and Tips
- Keep It Flat: Avoid deep nesting of folders. If you find yourself creating many levels of subfolders, consider restructuring. 
- Use Index Files: Create index files to export multiple components or utilities: 
// components/ui/index.ts
export * from './Button'
export * from './Card'
export * from './Modal'
- Document Your Structure: Maintain a README.md in your project root explaining the folder structure and conventions. 
- Be Consistent: Once you choose a structure, stick to it throughout the project. 
- Consider Co-location: Keep related files close together. If a component is only used in one feature, keep it in that feature's directory. 
Conclusion
A well-organized Next.js 15 project structure is crucial for maintaining and scaling your application. While there's no one-size-fits-all solution, the structure outlined in this guide provides a solid foundation that can be adapted to your specific needs.
Remember that folder structure should evolve with your project. Don't be afraid to refactor and reorganize as your application grows, but always maintain consistency and document your decisions.
Whether you're building a small application or planning to scale to a monorepo, following these organizational principles will help keep your codebase clean, maintainable, and developer-friendly.



