Project Structure
A scalable directory layout for React applications.
Directory Layout
- main.tsx
- vite-env.d.ts
Folder Purposes
| Folder | Purpose |
|---|---|
app/ | Application shell - providers, router, main App component |
components/ui/ | Reusable UI primitives (Button, Input, Modal) |
components/layout/ | Page layouts and structural components |
components/common/ | Shared components used across features |
features/ | Feature modules - self-contained business logic |
hooks/ | Shared custom hooks (not feature-specific) |
lib/ | Third-party library configurations and wrappers |
services/ | API clients, external service integrations |
stores/ | Global Zustand stores (not feature-specific) |
types/ | Shared TypeScript types and interfaces |
utils/ | Pure utility functions (date, string, array helpers) |
constants/ | Application constants, route paths, query keys |
assets/ | Static assets - images, icons, fonts |
styles/ | Global CSS, variables, resets |
Structure Rules
Feature Isolation
Each feature module is self-contained with its own components, hooks, services, stores, and types.
- LoginForm.tsx
- SignupForm.tsx
- useAuth.ts
- authService.ts
- authStore.ts
- auth.types.ts
- index.ts
Public API Pattern
Export through index.ts to control what's exposed:
// features/auth/index.ts
export { LoginForm } from './components/LoginForm';
export { useAuth } from './hooks/useAuth';
export type { User, AuthState } from './types/auth.types';This pattern allows you to refactor internal file structure without breaking imports elsewhere.
Colocation
Keep tests and styles next to components:
- Button.tsx
- Button.test.tsx
- Button.stories.tsx
- index.ts
No Circular Dependencies
Use dependency analysis tools to detect and prevent circular imports.
⚠️
Circular dependencies cause bugs and make refactoring difficult. Use tools like
madge to detect them.Maximum Nesting
Limit directory nesting to 4 levels to maintain navigability.
Import Aliases
Configure path aliases for cleaner imports:
// tsconfig.json
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
}
}Use imports like:
import { Button } from '@/components/ui';
import { useAuth } from '@/features/auth';