Files
antigravity-skills-reference/skills/frontend-dev-guidelines/resources/file-organization.md

502 lines
12 KiB
Markdown

# File Organization
Proper file and directory structure for maintainable, scalable frontend code in the the application.
---
## features/ vs components/ Distinction
### features/ Directory
**Purpose**: Domain-specific features with their own logic, API, and components
**When to use:**
- Feature has multiple related components
- Feature has its own API endpoints
- Feature has domain-specific logic
- Feature has custom hooks/utilities
**Examples:**
- `features/posts/` - Project catalog/post management
- `features/blogs/` - Blog builder and rendering
- `features/auth/` - Authentication flows
**Structure:**
```
features/
my-feature/
api/
myFeatureApi.ts # API service layer
components/
MyFeatureMain.tsx # Main component
SubComponents/ # Related components
hooks/
useMyFeature.ts # Custom hooks
useSuspenseMyFeature.ts # Suspense hooks
helpers/
myFeatureHelpers.ts # Utility functions
types/
index.ts # TypeScript types
index.ts # Public exports
```
### components/ Directory
**Purpose**: Truly reusable components used across multiple features
**When to use:**
- Component is used in 3+ places
- Component is generic (no feature-specific logic)
- Component is a UI primitive or pattern
**Examples:**
- `components/SuspenseLoader/` - Loading wrapper
- `components/CustomAppBar/` - Application header
- `components/ErrorBoundary/` - Error handling
- `components/LoadingOverlay/` - Loading overlay
**Structure:**
```
components/
SuspenseLoader/
SuspenseLoader.tsx
SuspenseLoader.test.tsx
CustomAppBar/
CustomAppBar.tsx
CustomAppBar.test.tsx
```
---
## Feature Directory Structure (Detailed)
### Complete Feature Example
Based on `features/posts/` structure:
```
features/
posts/
api/
postApi.ts # API service layer (GET, POST, PUT, DELETE)
components/
PostTable.tsx # Main container component
grids/
PostDataGrid/
PostDataGrid.tsx
drawers/
ProjectPostDrawer/
ProjectPostDrawer.tsx
cells/
editors/
TextEditCell.tsx
renderers/
DateCell.tsx
toolbar/
CustomToolbar.tsx
hooks/
usePostQueries.ts # Regular queries
useSuspensePost.ts # Suspense queries
usePostMutations.ts # Mutations
useGridLayout.ts # Feature-specific hooks
helpers/
postHelpers.ts # Utility functions
validation.ts # Validation logic
types/
index.ts # TypeScript types/interfaces
queries/
postQueries.ts # Query key factories (optional)
context/
PostContext.tsx # React context (if needed)
index.ts # Public API exports
```
### Subdirectory Guidelines
#### api/ Directory
**Purpose**: Centralized API calls for the feature
**Files:**
- `{feature}Api.ts` - Main API service
**Pattern:**
```typescript
// features/my-feature/api/myFeatureApi.ts
import apiClient from '@/lib/apiClient';
export const myFeatureApi = {
getItem: async (id: number) => {
const { data } = await apiClient.get(`/blog/items/${id}`);
return data;
},
createItem: async (payload) => {
const { data } = await apiClient.post('/blog/items', payload);
return data;
},
};
```
#### components/ Directory
**Purpose**: Feature-specific components
**Organization:**
- Flat structure if <5 components
- Subdirectories by responsibility if >5 components
**Examples:**
```
components/
MyFeatureMain.tsx # Main component
MyFeatureHeader.tsx # Supporting components
MyFeatureFooter.tsx
# OR with subdirectories:
containers/
MyFeatureContainer.tsx
presentational/
MyFeatureDisplay.tsx
blogs/
MyFeatureBlog.tsx
```
#### hooks/ Directory
**Purpose**: Custom hooks for the feature
**Naming:**
- `use` prefix (camelCase)
- Descriptive of what they do
**Examples:**
```
hooks/
useMyFeature.ts # Main hook
useSuspenseMyFeature.ts # Suspense version
useMyFeatureMutations.ts # Mutations
useMyFeatureFilters.ts # Filters/search
```
#### helpers/ Directory
**Purpose**: Utility functions specific to the feature
**Examples:**
```
helpers/
myFeatureHelpers.ts # General utilities
validation.ts # Validation logic
transblogers.ts # Data transblogations
constants.ts # Constants
```
#### types/ Directory
**Purpose**: TypeScript types and interfaces
**Files:**
```
types/
index.ts # Main types, exported
internal.ts # Internal types (not exported)
```
---
## Import Aliases (Vite Configuration)
### Available Aliases
From `vite.config.ts` lines 180-185:
| Alias | Resolves To | Use For |
|-------|-------------|---------|
| `@/` | `src/` | Absolute imports from src root |
| `~types` | `src/types` | Shared TypeScript types |
| `~components` | `src/components` | Reusable components |
| `~features` | `src/features` | Feature imports |
### Usage Examples
```typescript
// ✅ PREFERRED - Use aliases for absolute imports
import { apiClient } from '@/lib/apiClient';
import { SuspenseLoader } from '~components/SuspenseLoader';
import { postApi } from '~features/posts/api/postApi';
import type { User } from '~types/user';
// ❌ AVOID - Relative paths from deep nesting
import { apiClient } from '../../../lib/apiClient';
import { SuspenseLoader } from '../../../components/SuspenseLoader';
```
### When to Use Which Alias
**@/ (General)**:
- Lib utilities: `@/lib/apiClient`
- Hooks: `@/hooks/useAuth`
- Config: `@/config/theme`
- Shared services: `@/services/authService`
**~types (Type Imports)**:
```typescript
import type { Post } from '~types/post';
import type { User, UserRole } from '~types/user';
```
**~components (Reusable Components)**:
```typescript
import { SuspenseLoader } from '~components/SuspenseLoader';
import { CustomAppBar } from '~components/CustomAppBar';
import { ErrorBoundary } from '~components/ErrorBoundary';
```
**~features (Feature Imports)**:
```typescript
import { postApi } from '~features/posts/api/postApi';
import { useAuth } from '~features/auth/hooks/useAuth';
```
---
## File Naming Conventions
### Components
**Pattern**: PascalCase with `.tsx` extension
```
MyComponent.tsx
PostDataGrid.tsx
CustomAppBar.tsx
```
**Avoid:**
- camelCase: `myComponent.tsx`
- kebab-case: `my-component.tsx`
- All caps: `MYCOMPONENT.tsx`
### Hooks
**Pattern**: camelCase with `use` prefix, `.ts` extension
```
useMyFeature.ts
useSuspensePost.ts
useAuth.ts
useGridLayout.ts
```
### API Services
**Pattern**: camelCase with `Api` suffix, `.ts` extension
```
myFeatureApi.ts
postApi.ts
userApi.ts
```
### Helpers/Utilities
**Pattern**: camelCase with descriptive name, `.ts` extension
```
myFeatureHelpers.ts
validation.ts
transblogers.ts
constants.ts
```
### Types
**Pattern**: camelCase, `index.ts` or descriptive name
```
types/index.ts
types/post.ts
types/user.ts
```
---
## When to Create a New Feature
### Create New Feature When:
- Multiple related components (>3)
- Has own API endpoints
- Domain-specific logic
- Will grow over time
- Reused across multiple routes
**Example:** `features/posts/`
- 20+ components
- Own API service
- Complex state management
- Used in multiple routes
### Add to Existing Feature When:
- Related to existing feature
- Shares same API
- Logically grouped
- Extends existing functionality
**Example:** Adding export dialog to posts feature
### Create Reusable Component When:
- Used across 3+ features
- Generic, no domain logic
- Pure presentation
- Shared pattern
**Example:** `components/SuspenseLoader/`
---
## Import Organization
### Import Order (Recommended)
```typescript
// 1. React and React-related
import React, { useState, useCallback, useMemo } from 'react';
import { lazy } from 'react';
// 2. Third-party libraries (alphabetical)
import { Box, Paper, Button, Grid } from '@mui/material';
import type { SxProps, Theme } from '@mui/material';
import { useSuspenseQuery, useQueryClient } from '@tanstack/react-query';
import { createFileRoute } from '@tanstack/react-router';
// 3. Alias imports (@ first, then ~)
import { apiClient } from '@/lib/apiClient';
import { useAuth } from '@/hooks/useAuth';
import { useMuiSnackbar } from '@/hooks/useMuiSnackbar';
import { SuspenseLoader } from '~components/SuspenseLoader';
import { postApi } from '~features/posts/api/postApi';
// 4. Type imports (grouped)
import type { Post } from '~types/post';
import type { User } from '~types/user';
// 5. Relative imports (same feature)
import { MySubComponent } from './MySubComponent';
import { useMyFeature } from '../hooks/useMyFeature';
import { myFeatureHelpers } from '../helpers/myFeatureHelpers';
```
**Use single quotes** for all imports (project standard)
---
## Public API Pattern
### feature/index.ts
Export public API from feature for clean imports:
```typescript
// features/my-feature/index.ts
// Export main components
export { MyFeatureMain } from './components/MyFeatureMain';
export { MyFeatureHeader } from './components/MyFeatureHeader';
// Export hooks
export { useMyFeature } from './hooks/useMyFeature';
export { useSuspenseMyFeature } from './hooks/useSuspenseMyFeature';
// Export API
export { myFeatureApi } from './api/myFeatureApi';
// Export types
export type { MyFeatureData, MyFeatureConfig } from './types';
```
**Usage:**
```typescript
// ✅ Clean import from feature index
import { MyFeatureMain, useMyFeature } from '~features/my-feature';
// ❌ Avoid deep imports (but OK if needed)
import { MyFeatureMain } from '~features/my-feature/components/MyFeatureMain';
```
---
## Directory Structure Visualization
```
src/
├── features/ # Domain-specific features
│ ├── posts/
│ │ ├── api/
│ │ ├── components/
│ │ ├── hooks/
│ │ ├── helpers/
│ │ ├── types/
│ │ └── index.ts
│ ├── blogs/
│ └── auth/
├── components/ # Reusable components
│ ├── SuspenseLoader/
│ ├── CustomAppBar/
│ ├── ErrorBoundary/
│ └── LoadingOverlay/
├── routes/ # TanStack Router routes
│ ├── __root.tsx
│ ├── index.tsx
│ ├── project-catalog/
│ │ ├── index.tsx
│ │ └── create/
│ └── blogs/
├── hooks/ # Shared hooks
│ ├── useAuth.ts
│ ├── useMuiSnackbar.ts
│ └── useDebounce.ts
├── lib/ # Shared utilities
│ ├── apiClient.ts
│ └── utils.ts
├── types/ # Shared TypeScript types
│ ├── user.ts
│ ├── post.ts
│ └── common.ts
├── config/ # Configuration
│ └── theme.ts
└── App.tsx # Root component
```
---
## Summary
**Key Principles:**
1. **features/** for domain-specific code
2. **components/** for truly reusable UI
3. Use subdirectories: api/, components/, hooks/, helpers/, types/
4. Import aliases for clean imports (@/, ~types, ~components, ~features)
5. Consistent naming: PascalCase components, camelCase utilities
6. Export public API from feature index.ts
**See Also:**
- [component-patterns.md](component-patterns.md) - Component structure
- [data-fetching.md](data-fetching.md) - API service patterns
- [complete-examples.md](complete-examples.md) - Full feature example