@jjdenhertog/ai-driven-development
Version:
AI-driven development workflow with learning capabilities for Claude
513 lines (430 loc) • 16.1 kB
Markdown
---
name: "Next.js Project Structure Guide"
description: "Defines the folder structure and file organization patterns for Next.js applications"
ai_instructions: |
When organizing files in a Next.js project:
1. Follow the feature-first organization pattern
2. Keep related files together within feature directories
3. Use proper naming conventions (PascalCase for components, camelCase for utils)
4. Place shared components in /src/components, feature-specific in /src/features/[Feature]/components
5. Always check file placement against the directory structure rules
---
# Next.js Project Structure Guide
<ai-context>
This guide defines how to organize files and directories in Next.js applications using the App Router.
The structure promotes modularity, scalability, and clear separation of concerns through a feature-first approach.
AI should use this guide to determine where to place new files and how to organize code.
</ai-context>
## Overview
This guide defines the folder structure for Next.js applications using App Router. It uses a feature-first approach with clear separation of concerns, promoting modularity and scalability.
## Core Philosophy
- **Feature-First**: Organize code by business domain/feature
- **Domain Grouping**: Group related files by functional domain
- **Environment Clarity**: Clear distinction between client and server code
- **Consistent Naming**: Predictable file naming conventions
- **Progressive Enhancement**: Start simple, add complexity as needed
## Directory Structure
```
project-root/
├── app/ # Next.js App Router
│ ├── (routes)/ # Route groups
│ │ └── [page]/
│ │ └── page.tsx
│ ├── api/ # API routes
│ │ └── [endpoint]/
│ │ └── route.ts
│ └── layout.tsx # Root layout
├── src/ # Application source code
│ ├── components/ # Shared UI components
│ │ └── ui/ # Custom UI library (B-prefixed)
│ ├── features/ # Feature modules
│ │ └── [FeatureName]/
│ │ ├── components/
│ │ ├── hooks/
│ │ ├── utils/
│ │ ├── types/
│ │ └── index.tsx
│ ├── hooks/ # Shared React hooks
│ ├── layouts/ # Reusable layout components
│ ├── lib/ # Core utilities and singletons
│ │ ├── prisma.ts # Prisma client instance
│ │ ├── redis.ts # Redis client instance
│ │ └── auth.ts # NextAuth configuration
│ ├── providers/ # React context providers
│ ├── schemas/ # Zod validation schemas
│ │ └── [domain]/ # Domain-specific schemas
│ ├── services/ # API service layer
│ │ ├── client/
│ │ └── server/
│ ├── stores/ # Zustand state stores
│ │ ├── useAppStore.ts # Global app store
│ │ └── [feature]/ # Feature-specific stores
│ ├── types/ # Global TypeScript types
│ │ └── [domain]/
│ ├── utils/ # Shared utilities
│ │ ├── client/
│ │ ├── server/
│ │ └── shared/
│ └── config/ # App configuration
├── e2e/ # End-to-end tests
│ └── [feature]/ # Tests organized by feature
├── public/ # Static assets
│ ├── img/
│ │ └── icons/
│ └── fonts/
├── prisma/ # Database schema
├── styles/ # Global styles
└── [config files] # Root configuration
```
## File Placement Rules
<ai-rules>
- ALWAYS place page routes in /app directory following Next.js App Router conventions
- NEVER mix client and server code in the same file
- ALWAYS use 'use client' directive for interactive components
- PREFER co-locating tests with their source files
- ALWAYS organize features in self-contained modules under /src/features
</ai-rules>
### 1. Page Routes (`/app`)
<ai-decision-tree>
When creating a new page:
1. Is it a marketing page? → Place in app/(marketing)/
2. Is it a dashboard page? → Place in app/(dashboard)/
3. Is it an API route? → Place in app/api/
4. Does it need a specific layout? → Create layout.tsx in the directory
5. Does it have dynamic segments? → Use [param] syntax
</ai-decision-tree>
App Router page structure:
```
app/
├── (marketing)/ # Route group
│ ├── page.tsx # /
│ ├── about/
│ │ └── page.tsx # /about
│ └── layout.tsx
├── (dashboard)/ # Route group
│ ├── settings/
│ │ └── page.tsx # /settings
│ └── layout.tsx
└── billing/
└── [invoiceId]/
└── page.tsx # /billing/:invoiceId
```
**Route Groups**: Use parentheses to organize without affecting URLs
### 2. API Routes (`/app/api`)
```
app/api/
├── auth/
│ ├── login/
│ │ └── route.ts # POST /api/auth/login
│ └── logout/
│ └── route.ts
├── users/
│ ├── route.ts # GET/POST /api/users
│ └── [id]/
│ └── route.ts # GET/PUT/DELETE /api/users/:id
└── billing/
└── [year_id]/
└── route.ts
```
### 3. Components (`/src/components`)
<code-template name="shared-component">
// src/components/ComponentName.tsx
export const ComponentName = ({ prop1, prop2 }: Props) => {
// Component logic
return (
<div>
{/* Component JSX */}
</div>
);
};
</code-template>
<code-template name="ui-component">
// src/components/ui/BComponentName.tsx
'use client';
import { ComponentProps } from '@mui/material';
export const BComponentName = (props: ComponentProps) => {
// Extended UI component logic
return <MUIComponent {...props} />;
};
</code-template>
**Shared Components** (`/src/components/`)
- Reusable across multiple features
- No feature-specific business logic
- Example: `Button.tsx`, `Modal.tsx`, `Card.tsx`
**Custom UI Library** (`/src/components/ui/`)
- Brand-specific components prefixed with 'B'
- Extends third-party UI libraries
- Usually Client Components (interactive)
- Example: `BTextField.tsx`, `BCheckbox.tsx`, `BTiptap.tsx`
**Server vs Client Components**
- Components are Server Components by default
- Add `'use client'` directive for interactive components
- Server Components can fetch data directly
- Client Components handle user interactions
### 4. Features (`/src/features`)
<validation-schema>
Feature Directory Structure:
- ✅ /src/features/FeatureName/index.tsx (public exports)
- ✅ /src/features/FeatureName/components/ (feature components)
- ✅ /src/features/FeatureName/hooks/ (feature hooks)
- ✅ /src/features/FeatureName/utils/ (feature utilities)
- ✅ /src/features/FeatureName/types/ (feature types)
- ❌ /src/features/featureName/ (must be PascalCase)
- ❌ /src/features/FeatureName/pages/ (pages go in /app)
</validation-schema>
Each feature is a self-contained module:
```
src/features/Billing/
├── index.tsx # Public exports
├── BillingDashboard.tsx # Main component
├── components/
│ ├── InvoiceList.tsx
│ └── PaymentForm.tsx
├── hooks/
│ └── useInvoices.ts
├── utils/
│ └── calculateTax.ts
├── types/
│ └── Invoice.ts
└── constants/
└── billingStatus.ts
```
**When to create a new feature:**
- Represents a distinct business domain
- Has multiple related components
- Contains domain-specific logic
- Has its own data models
### 5. Hooks (`/src/hooks`)
**Shared Hooks** (`/src/hooks/`)
- Generic functionality
- Used across features
- Example: `useDebounce.ts`, `useLocalStorage.ts`
**Feature Hooks** (`/src/features/[FeatureName]/hooks/`)
- Feature-specific logic
- Data fetching
- Example: `useInvoices.ts`, `usePaymentMethods.ts`
### 6. Utilities (`/src/utils`)
Organized by runtime environment:
```
src/utils/
├── client/ # Browser-only
│ ├── dom/
│ ├── validation/
│ └── storage/
├── server/ # Server-only
│ ├── billing/
│ ├── mail/
│ └── database/
└── shared/ # Universal
├── date/
├── string/
└── converter/
```
### 7. Types (`/src/types`)
Domain-based organization:
```
src/types/
├── api/
│ ├── request/
│ └── response/
├── billing/
├── user/
└── common/
├── enums/
└── interfaces/
```
### 8. Services (`/src/services`)
External interactions:
```
src/services/
├── client/ # Client-side services
│ ├── analytics.ts
│ └── storage.ts
├── server/ # Server-side services
│ ├── stripe/
│ └── database/
└── api/ # API clients
├── users.ts
└── billing.ts
```
### 9. State Management (`/src/stores`)
Zustand stores for client-side state:
```
src/stores/
├── useAppStore.ts # Global app state
├── useAuthStore.ts # Authentication state
└── features/ # Feature-specific stores
├── useCartStore.ts
└── useBillingStore.ts
```
**Store Organization**:
- Global stores at root level
- Feature-specific stores in subdirectories
- Each store is a single file with related state and actions
### 10. Validation Schemas (`/src/schemas`)
Zod schemas for runtime validation:
```
src/schemas/
├── auth.ts # Authentication schemas
├── user.ts # User-related schemas
├── billing/ # Billing domain schemas
│ ├── invoice.ts
│ └── payment.ts
└── common.ts # Shared validation rules
```
**Schema Organization**:
- Group by domain when multiple schemas exist
- Co-locate with API routes or forms that use them
- Export both schema and inferred types
### 11. Core Libraries (`/src/lib`)
Singleton instances and core configurations:
```
src/lib/
├── prisma.ts # Prisma client singleton
├── redis.ts # Redis client singleton
├── auth.ts # NextAuth configuration
├── email.ts # Email service setup
└── constants.ts # App-wide constants
```
**Library Files**:
- Single instance configurations
- Third-party service setups
- Core utilities that need single initialization
- App-wide constants and enums
### 12. Tests
TDD with co-location pattern:
**Unit/Component Tests** - Co-located with code:
```
src/components/
├── Button.tsx
└── Button.test.tsx # Test next to component
src/features/Billing/
├── BillingDashboard.tsx
├── BillingDashboard.test.tsx
└── hooks/
├── useInvoices.ts
└── useInvoices.test.ts
```
**Alternative: __tests__ folders** - For multiple test files:
```
src/features/Billing/
└── __tests__/
├── BillingDashboard.test.tsx
└── BillingDashboard.integration.test.tsx
```
**E2E Tests** - Separate directory:
```
e2e/
├── auth/
│ └── login.spec.ts
└── billing/
└── invoice-flow.spec.ts
```
### 13. Providers (`/src/providers`)
Complex providers get their own directories:
```
src/providers/
├── Auth/
│ ├── AuthContext.tsx
│ ├── AuthProvider.tsx
│ └── types.ts
└── BSnackbarProvider.tsx # Simple providers
```
### 14. Layouts (`/src/layouts`)
Reusable layout components:
```
src/layouts/
├── MainNav.tsx
├── Sidebar.tsx
└── Footer.tsx
```
Layout files in App Router:
```
app/
├── layout.tsx # Root layout
├── (marketing)/
│ └── layout.tsx # Section layout
└── (dashboard)/
└── layout.tsx
```
### 15. Configuration (`/src/config`)
```
src/config/
├── app.ts # App settings
├── api.ts # API endpoints
├── features.ts # Feature flags
└── theme.ts # Theme config
```
**Environment Variables**: Root directory
- `.env.local`
- `.env.development`
- `.env.production`
- `.env.example`
**Test Configuration**: Root directory
- `vitest.config.ts`
- `playwright.config.ts`
## Special Patterns
### B-Prefixed Components
Custom UI components are prefixed with 'B':
- `BTextField`, `BCheckbox`, `BTiptap`
- Distinguishes from third-party components
- Located in `/src/components/ui/`
### Barrel Exports
Use index files for clean public APIs:
```typescript
// src/features/Billing/index.tsx
export { BillingDashboard } from './BillingDashboard';
export { useInvoices } from './hooks/useInvoices';
export type { Invoice } from './types';
```
### Private Folders
Use underscore prefix for non-route folders in `/app`:
- `_components` - Components used only in app directory
- `_utils` - App-specific utilities
- Prevents accidental routing
## Naming Conventions
| Type | Convention | Example |
|------|------------|---------|
| Components | PascalCase | `UserProfile.tsx` |
| Custom UI | PascalCase + B | `BTextField.tsx` |
| Hooks | camelCase + use | `useAuth.ts` |
| Utilities | camelCase | `formatDate.ts` |
| Types | PascalCase | `User.ts` |
| Enums | PascalCase + .enum | `UserRole.enum.ts` |
| API Routes | lowercase | `route.ts` |
| Features | PascalCase | `Billing/` |
| Tests | camelCase + .test/.spec | `Button.test.tsx` |
| E2E Tests | kebab-case + .spec | `login-flow.spec.ts` |
## Best Practices
<ai-rules>
- Feature modules should be self-contained and not import from other features
- Shared code goes in the appropriate shared directory (/components, /hooks, /utils)
- Use barrel exports (index.ts) to control the public API of features
- Keep the /app directory lean - only pages, layouts, and route handlers
- Co-locate tests with source files for better maintainability
- Use route groups in /app to organize without affecting URLs
- Prefer absolute imports using @ alias over relative imports
</ai-rules>
<ai-decision-tree>
Where should I place this file?
1. Is it a page or route?
→ YES: /app directory
→ NO: Continue to 2
2. Is it used by multiple features?
→ YES: Is it a component?
→ YES: /src/components
→ NO: Is it a hook?
→ YES: /src/hooks
→ NO: Is it a utility?
→ YES: /src/utils
→ NO: /src/lib or /src/types
→ NO: Continue to 3
3. Is it feature-specific?
→ YES: /src/features/[FeatureName]/[appropriate-subdirectory]
→ NO: Consider if it should be shared
4. Is it configuration or constants?
→ YES: /src/config
→ NO: Review the structure again
</ai-decision-tree>
1. **Feature Independence**: Features don't import from each other
2. **Progressive Complexity**: Add subdirect