# Feature Modification & Development Guide
## Complete File Reference for Adding, Modifying, and Removing Features

**Version:** 1.0.0  
**Last Updated:** November 29, 2025  
**Purpose:** Quick reference for developers to locate exactly which files to modify for specific feature types, across both frontend and backend.

---

## Table of Contents

1. [Quick Navigation by Feature Type](#quick-navigation-by-feature-type)
2. [Feature Type Reference Matrix](#feature-type-reference-matrix)
3. [Frontend Feature Modifications](#frontend-feature-modifications)
4. [Backend Feature Modifications](#backend-feature-modifications)
5. [Cross-Module Modifications](#cross-module-modifications)
6. [Database Schema Changes](#database-schema-changes)
7. [Common Workflow Patterns](#common-workflow-patterns)
8. [File Organization Index](#file-organization-index)

---

## Quick Navigation by Feature Type

### 🎯 Find Your Feature Type

- **Adding/Removing/Modifying a Database Column** → [Database Changes](#database-changes)
- **Adding a New Page/List View** → [New Page Feature](#new-page-feature)
- **Adding a Column to a Table/List** → [Table Column Addition](#table-column-addition)
- **Adding a Form Field** → [Form Field Addition](#form-field-addition)
- **Adding an API Endpoint** → [API Endpoint Addition](#api-endpoint-addition)
- **Adding a Filter/Search** → [Filter/Search Addition](#filtersearch-addition)
- **Adding a Status/Choice Field** → [Status Field Addition](#status-field-addition)
- **Modifying API Response** → [API Response Modification](#api-response-modification)
- **Adding Validation** → [Validation Addition](#validation-addition)
- **Adding Background Task** → [Background Task Addition](#background-task-addition)
- **Adding Webhook** → [Webhook Addition](#webhook-addition)
- **Adding Integration** → [Integration Addition](#integration-addition)

---

## Feature Type Reference Matrix

| Feature Type | Frontend Files | Backend Files | Database | Global Config |
|--------------|---|---|---|---|
| **Database Column** | - | Model + Serializer | Migration | - |
| **Table Column** | List Component | ViewSet Filter | - | - |
| **Form Field** | Form Component | Serializer | Model Migration | - |
| **Page/View** | Page Component | ViewSet | - | Routes |
| **API Endpoint** | API Hook | ViewSet + Router | - | urls.py |
| **Status Field** | Select/Enum | Model Choice | Migration | - |
| **Filter/Search** | Filter UI | filterset_fields | Index | - |
| **Validation** | Form Rules | Validator Service | - | - |
| **Background Task** | UI Trigger | Celery Task | - | settings.py |
| **Webhook** | - | Handler Function | WebhookLog Model | urls.py |
| **Integration** | - | Adapter Class | Integration Model | - |

---

## Frontend Feature Modifications

### Directory Structure

```
frontend/src/
├── pages/
│   ├── Planner/
│   │   ├── Dashboard.tsx
│   │   ├── Keywords.tsx
│   │   ├── Clusters.tsx
│   │   ├── ClusterDetail.tsx
│   │   ├── Ideas.tsx
│   │   └── KeywordOpportunities.tsx
│   ├── Writer/
│   │   ├── Dashboard.tsx
│   │   ├── Tasks.tsx
│   │   ├── Content.tsx
│   │   ├── ContentView.tsx
│   │   ├── Drafts.tsx
│   │   ├── Images.tsx
│   │   ├── Published.tsx
│   │   └── Review.tsx
│   ├── Linker/
│   │   └── [Linker Pages]
│   ├── Optimizer/
│   │   └── [Optimizer Pages]
│   ├── Settings/
│   │   └── [Settings Pages]
│   └── [Other Modules]
├── components/
│   ├── common/
│   │   ├── Table.tsx
│   │   ├── Modal.tsx
│   │   ├── Form.tsx
│   │   ├── Button.tsx
│   │   └── [Shared UI Components]
│   ├── [Module-Specific Components]
│   └── [Feature Components]
├── api/
│   ├── client.ts              # Axios setup
│   ├── auth.ts                # Auth API calls
│   ├── planner.ts             # Planner endpoints
│   ├── writer.ts              # Writer endpoints
│   ├── [module].ts            # Module-specific APIs
│   └── hooks/
│       └── useApi.ts          # API hook
├── store/
│   ├── authStore.ts           # Auth state
│   ├── siteStore.ts           # Site/Sector state
│   ├── [module]Store.ts       # Module state
│   └── globalStore.ts         # Global state
├── hooks/
│   ├── useAuth.ts
│   ├── useApi.ts
│   ├── useSite.ts
│   └── [Custom Hooks]
├── types/
│   ├── api.ts                 # API type definitions
│   ├── models.ts              # Data model types
│   └── [Module Types]
└── utils/
    ├── formatters.ts
    ├── validators.ts
    └── [Utility Functions]
```

### Feature: Adding a Column to a List/Table

**Module Example: Writer/Tasks List**

#### Files to Modify:

| Layer | File | Change Type | Action |
|-------|------|-------------|--------|
| **Data Type** | `frontend/src/types/models.ts` | Modify | Add field to Task interface |
| **API Response** | `frontend/src/api/writer.ts` | Auto | API will return new field from backend |
| **Page Component** | `frontend/src/pages/Writer/Tasks.tsx` | Modify | Add column to table columns config |
| **Table Component** | `frontend/src/components/Writer/TasksTable.tsx` | Modify | Render new column in JSX |
| **Backend ViewSet** | `backend/igny8_core/modules/writer/views.py` | Modify | Add to `filterset_fields` if filterable, `ordering_fields` if sortable |
| **Backend Serializer** | `backend/igny8_core/modules/writer/serializers.py` | Modify | Add field to serializer `fields` list |
| **Backend Model** | `backend/igny8_core/business/content/models.py` | Modify | Add field to Tasks model class |
| **Backend Migration** | `backend/igny8_core/migrations/` | Create | `python manage.py makemigrations` |

#### Step-by-Step for "Adding 'priority' column to Tasks list":

```python
# Step 1: Backend Model (models.py)
class Tasks(SiteSectorBaseModel):
    # ... existing fields ...
    priority = models.IntegerField(
        choices=[(1, 'Low'), (2, 'Medium'), (3, 'High')],
        default=2
    )

# Step 2: Backend Serializer (serializers.py)
class TasksSerializer(serializers.ModelSerializer):
    class Meta:
        model = Tasks
        fields = ['id', 'title', 'status', 'priority', ...]  # Add 'priority'

# Step 3: Backend ViewSet (views.py) - if filterable/sortable
class TasksViewSet(SiteSectorModelViewSet):
    filterset_fields = ['status', 'cluster_id', 'priority']  # Add 'priority'
    ordering_fields = ['title', 'created_at', 'priority']     # Add 'priority'

# Step 4: Frontend Type (types/models.ts)
interface Task {
  id: number;
  title: string;
  status: string;
  priority: number;  // Add this
  // ... other fields
}

# Step 5: Frontend API (api/writer.ts) - No changes needed if using generic fetch

# Step 6: Frontend Component (pages/Writer/Tasks.tsx)
const columns = [
  { key: 'id', label: 'ID', width: '10%' },
  { key: 'title', label: 'Title', width: '40%' },
  { key: 'status', label: 'Status', width: '20%' },
  { key: 'priority', label: 'Priority', width: '15%' },  // Add this
];

# Step 7: Database Migration
# bash: python manage.py makemigrations
# bash: python manage.py migrate
```

### Feature: Adding a Form Field

**Module Example: Writer/Tasks Create Form**

#### Files to Modify:

| Layer | File | Change Type | Description |
|-------|------|-------------|-------------|
| **Backend Model** | `backend/.../models.py` | Add | New model field with validators |
| **Backend Serializer** | `backend/.../serializers.py` | Add | Serializer field with validation |
| **Backend ViewSet** | `backend/.../views.py` | Modify | Add to `filterset_fields` if needed |
| **Frontend Type** | `frontend/src/types/models.ts` | Add | Add to interface |
| **Frontend Form Component** | `frontend/src/pages/Writer/[FormPage].tsx` | Add | Add form input JSX |
| **Frontend Validation** | `frontend/src/utils/validators.ts` | Add | Client-side validation rule |
| **Frontend State** | `frontend/src/store/[module]Store.ts` | Add | Add to form state if needed |
| **Database Migration** | `backend/migrations/` | Create | If model field is added |

#### Example: "Adding 'estimatedWordCount' field to Tasks form":

```python
# Step 1: Backend Model
class Tasks(SiteSectorBaseModel):
    # ... existing fields ...
    word_count = models.IntegerField(
        default=1000,
        validators=[MinValueValidator(100), MaxValueValidator(10000)],
        help_text="Target word count (100-10000)"
    )

# Step 2: Backend Serializer
class TasksSerializer(serializers.ModelSerializer):
    word_count = serializers.IntegerField(
        required=False,
        min_value=100,
        max_value=10000
    )
    
    class Meta:
        model = Tasks
        fields = [..., 'word_count']

# Step 3: Frontend Type
interface Task {
  id: number;
  title: string;
  wordCount: number;  // Add this (camelCase)
}

# Step 4: Frontend Form Component
function TaskForm() {
  const [formData, setFormData] = useState({
    title: '',
    wordCount: 1000,  // Add this
  });

  return (
    <form>
      {/* ... other fields ... */}
      <input
        type="number"
        name="wordCount"
        label="Word Count"
        min={100}
        max={10000}
        value={formData.wordCount}
        onChange={e => setFormData({...formData, wordCount: e.target.value})}
      />
    </form>
  );
}

# Step 5: Frontend Validation
export const validateTaskForm = (data) => {
  if (data.wordCount < 100 || data.wordCount > 10000) {
    return 'Word count must be between 100 and 10000';
  }
  return null;
};
```

### Feature: Adding a New Page/View

**Module Example: Adding "Writer/Scheduled" Page**

#### Files to Create/Modify:

| Layer | File | Change Type | Action |
|-------|------|-------------|--------|
| **New Page Component** | `frontend/src/pages/Writer/Scheduled.tsx` | Create | New React component |
| **Page Router** | `frontend/src/App.tsx` | Modify | Add route entry |
| **Navigation** | `frontend/src/layout/Sidebar.tsx` | Modify | Add menu item |
| **API Hooks** | `frontend/src/api/writer.ts` | Modify | Add API call if needed |
| **Type Definitions** | `frontend/src/types/models.ts` | Modify | Add types if needed |

#### Step-by-Step for "Adding Writer/Scheduled Page":

```typescript
// Step 1: Create new page component
// File: frontend/src/pages/Writer/Scheduled.tsx

import React, { useEffect, useState } from 'react';
import { getScheduledContent } from '../../api/writer';
import ContentTable from '../../components/Writer/ContentTable';

export default function ScheduledPage() {
  const [content, setContent] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const loadContent = async () => {
      try {
        const response = await getScheduledContent({
          siteId: currentSite.id,
          sectorId: currentSector.id,
          status: 'scheduled'
        });
        setContent(response.data);
      } catch (error) {
        console.error('Failed to load scheduled content:', error);
      } finally {
        setLoading(false);
      }
    };
    loadContent();
  }, []);

  return (
    <div className="p-6">
      <h1 className="text-2xl font-bold mb-6">Scheduled Content</h1>
      <ContentTable content={content} loading={loading} />
    </div>
  );
}

// Step 2: Add route in App.tsx
import ScheduledPage from './pages/Writer/Scheduled';

function App() {
  return (
    <Routes>
      {/* ... other routes ... */}
      <Route path="/writer/scheduled" element={<ScheduledPage />} />
    </Routes>
  );
}

// Step 3: Add to Sidebar navigation
// File: frontend/src/layout/Sidebar.tsx
<NavItem 
  to="/writer/scheduled" 
  label="Scheduled" 
  icon={<CalendarIcon />}
/>

// Step 4: Add API function if needed
// File: frontend/src/api/writer.ts
export const getScheduledContent = async (params) => {
  return fetchAPI('/api/v1/writer/content/', {
    query: { ...params, status: 'scheduled' }
  });
};
```

### Feature: Adding a Filter/Search

**Module Example: Adding "Priority Filter" to Tasks**

#### Files to Modify:

| Layer | File | Change Type | Description |
|-------|------|-------------|-------------|
| **Backend ViewSet** | `backend/.../views.py` | Modify | Add to `filterset_fields` |
| **Backend Model** | `backend/.../models.py` | Check | Field must have choices |
| **Frontend Filter UI** | `frontend/src/components/Writer/TasksFilter.tsx` | Add | Add filter control |
| **Frontend State** | `frontend/src/store/writerStore.ts` | Modify | Add filter state |

#### Example:

```python
# Backend (views.py)
class TasksViewSet(SiteSectorModelViewSet):
    filterset_fields = ['status', 'cluster_id', 'priority']  # Add 'priority'

# Frontend - Add Filter Component
interface TaskFilter {
  priority?: number;
  status?: string;
}

function TasksFilter() {
  const [filters, setFilters] = useState<TaskFilter>({});

  return (
    <div className="flex gap-4 mb-6">
      <select
        value={filters.priority || ''}
        onChange={(e) => setFilters({...filters, priority: e.target.value})}
      >
        <option value="">All Priorities</option>
        <option value="1">Low</option>
        <option value="2">Medium</option>
        <option value="3">High</option>
      </select>
    </div>
  );
}
```

---

## Backend Feature Modifications

### Directory Structure

```
backend/igny8_core/
├── modules/              # API ViewSets (REST endpoints)
│   ├── planner/
│   │   ├── views.py      # ViewSets
│   │   ├── serializers.py # Serializers
│   │   ├── urls.py       # Route definitions
│   │   └── apps.py
│   ├── writer/
│   │   ├── views.py
│   │   ├── serializers.py
│   │   ├── urls.py
│   │   └── apps.py
│   ├── [other modules]
│   └── urls.py           # Root routing
├── business/             # Business logic & models
│   ├── planning/
│   │   ├── models.py     # Database models
│   │   └── services/     # Business logic
│   ├── content/
│   │   ├── models.py
│   │   └── services/
│   ├── [other domains]
│   └── models.py
├── auth/
│   ├── models.py         # User, Account, Site, Sector
│   ├── views.py
│   ├── serializers.py
│   └── urls.py
├── api/
│   ├── base.py           # Base ViewSet classes
│   ├── response.py       # Response utilities
│   ├── pagination.py
│   ├── permissions.py
│   ├── throttles.py
│   └── exception_handlers.py
├── ai/                   # AI Engine
│   ├── engine.py
│   ├── ai_core.py
│   ├── registry.py
│   └── functions/
├── middleware/
├── utils/
├── tasks/                # Celery tasks
├── migrations/           # Database migrations
├── settings.py           # Django settings
├── urls.py               # Root URL config
└── wsgi.py
```

### Feature: Adding an API Endpoint

**Module Example: Adding "GET /writer/tasks/{id}/brief/" endpoint**

#### Files to Create/Modify:

| File | Change Type | Description |
|------|-------------|-------------|
| `backend/igny8_core/modules/writer/views.py` | Add | Add `@action` method to ViewSet |
| `backend/igny8_core/modules/writer/serializers.py` | Check | Serializer for response |
| `backend/igny8_core/modules/writer/urls.py` | Auto | Routes auto-generated by DRF `DefaultRouter` |

#### Step-by-Step Example:

```python
# Step 1: Add action to ViewSet (views.py)
class TasksViewSet(SiteSectorModelViewSet):
    # ... existing code ...
    
    @action(detail=True, methods=['get'])
    def brief(self, request, pk=None):
        """
        Get task brief
        GET /api/v1/writer/tasks/{id}/brief/
        """
        task = self.get_object()
        
        # Business logic to generate brief
        brief_data = {
            'task_id': task.id,
            'title': task.title,
            'keywords': task.keywords,
            'cluster': task.cluster.name if task.cluster else None,
            'description': task.description
        }
        
        return success_response(
            success=True,
            data=brief_data,
            message='Task brief retrieved'
        )

# Step 2: That's it! DRF auto-generates the route
# URL will be: /api/v1/writer/tasks/123/brief/
# Method: GET
# Response format: { success: true, data: {...}, message: '...' }

# Step 3: Frontend API hook
// frontend/src/api/writer.ts
export const getTaskBrief = async (taskId: number) => {
  return fetchAPI(`/api/v1/writer/tasks/${taskId}/brief/`);
};
```

### Feature: Adding a Status/Choice Field

**Module Example: Adding "priority" choice field to Tasks**

#### Files to Modify:

| Layer | File | Change Type | Action |
|-------|------|-------------|--------|
| **Backend Model** | `backend/.../models.py` | Add | Add field with CHOICES |
| **Database Migration** | `backend/migrations/` | Create | Auto from model |
| **Backend Serializer** | `backend/.../serializers.py` | Auto | Choices auto-included |
| **Backend ViewSet** | `backend/.../views.py` | Modify | Add to filters if needed |
| **Frontend Types** | `frontend/src/types/models.ts` | Add | Add type definition |
| **Frontend Enum/Constant** | `frontend/src/config/constants.ts` | Add | Add choice options |
| **Frontend UI** | Components using field | Use | Render as select/dropdown |

#### Example:

```python
# Step 1: Backend Model (models.py)
class Tasks(SiteSectorBaseModel):
    PRIORITY_CHOICES = [
        (1, 'Low'),
        (2, 'Medium'),
        (3, 'High'),
        (4, 'Urgent'),
    ]
    
    priority = models.IntegerField(
        choices=PRIORITY_CHOICES,
        default=2,
        help_text="Task priority level"
    )

# Step 2: Backend Serializer (serializers.py) - No changes needed!
# DRF automatically includes choices in API response as:
# {
#   "priority": 2,
#   "priority_display": "Medium",
#   "priority_choices": [[1, "Low"], [2, "Medium"], ...]
# }

# Step 3: Frontend Constant (config/constants.ts)
export const TASK_PRIORITIES = {
  LOW: 1,
  MEDIUM: 2,
  HIGH: 3,
  URGENT: 4,
};

export const TASK_PRIORITY_LABELS = {
  1: 'Low',
  2: 'Medium',
  3: 'High',
  4: 'Urgent',
};

# Step 4: Frontend Type (types/models.ts)
interface Task {
  id: number;
  priority: 1 | 2 | 3 | 4;  // Use enum values
}

# Step 5: Frontend Component
function TaskSelect() {
  return (
    <select value={task.priority}>
      <option value={1}>Low</option>
      <option value={2}>Medium</option>
      <option value={3}>High</option>
      <option value={4}>Urgent</option>
    </select>
  );
}
```

### Feature: Adding Validation

**Module Example: Validating task word count (100-10000)**

#### Files to Create/Modify:

| File | Change Type | Description |
|------|-------------|-------------|
| `backend/igny8_core/business/content/services/validation_service.py` | Create | Validation logic |
| `backend/igny8_core/modules/writer/serializers.py` | Modify | Add field validation |
| `frontend/src/utils/validators.ts` | Add | Client-side validation |

#### Example:

```python
# Step 1: Backend Model Field Validators (models.py)
from django.core.validators import MinValueValidator, MaxValueValidator

class Tasks(SiteSectorBaseModel):
    word_count = models.IntegerField(
        default=1000,
        validators=[
            MinValueValidator(100, message="Minimum word count is 100"),
            MaxValueValidator(10000, message="Maximum word count is 10000")
        ]
    )

# Step 2: Backend Serializer Validation (serializers.py)
class TasksSerializer(serializers.ModelSerializer):
    word_count = serializers.IntegerField(
        min_value=100,
        max_value=10000,
        required=False
    )
    
    def validate_word_count(self, value):
        if value and (value < 100 or value > 10000):
            raise serializers.ValidationError(
                "Word count must be between 100 and 10000"
            )
        return value
    
    class Meta:
        model = Tasks
        fields = ['id', 'title', 'word_count', ...]

# Step 3: Frontend Validation (utils/validators.ts)
export const validateTaskWordCount = (wordCount: number): string | null => {
  if (wordCount < 100) {
    return 'Word count must be at least 100';
  }
  if (wordCount > 10000) {
    return 'Word count cannot exceed 10000';
  }
  return null;
};

# Step 4: Frontend Component
function TaskForm() {
  const [wordCount, setWordCount] = useState(1000);
  const [error, setError] = useState('');

  const handleChange = (value) => {
    setWordCount(value);
    const err = validateTaskWordCount(value);
    setError(err || '');
  };

  return (
    <>
      <input
        type="number"
        value={wordCount}
        onChange={(e) => handleChange(Number(e.target.value))}
      />
      {error && <span className="text-red-500">{error}</span>}
    </>
  );
}
```

### Feature: Adding a Background Task (Celery)

**Module Example: Adding "Async content generation" task**

#### Files to Create/Modify:

| File | Change Type | Description |
|------|-------------|-------------|
| `backend/igny8_core/tasks/[domain]_tasks.py` | Create | Celery task function |
| `backend/igny8_core/modules/[module]/views.py` | Modify | Queue task from ViewSet |
| `backend/igny8_core/settings.py` | Check | Celery config (usually pre-configured) |

#### Example: Adding "generate_content_images" async task

```python
# Step 1: Create Celery Task (tasks/writer_tasks.py)
from celery import shared_task
import logging

logger = logging.getLogger(__name__)

@shared_task(bind=True, max_retries=3)
def generate_content_images(self, content_id):
    """
    Generate AI images for content
    """
    from igny8_core.business.content.models import Content
    from igny8_core.ai.engine import AIEngine
    
    logger.info(f"[generate_content_images] 🎬 Starting image generation for content {content_id}")
    
    try:
        content = Content.objects.get(id=content_id)
        
        # Generate images
        engine = AIEngine()
        images = engine.generate_images(
            content_id=content.id,
            title=content.title,
            keywords=content.secondary_keywords
        )
        
        # Save images
        for image_data in images:
            Image.objects.create(
                content=content,
                url=image_data['url'],
                prompt=image_data['prompt']
            )
        
        logger.info(f"[generate_content_images] ✅ Successfully generated {len(images)} images")
        return {'success': True, 'image_count': len(images)}
        
    except Content.DoesNotExist:
        logger.error(f"[generate_content_images] ❌ Content {content_id} not found")
        return {'success': False, 'error': 'Content not found'}
    except Exception as exc:
        logger.error(f"[generate_content_images] ❌ Task failed: {str(exc)}")
        # Retry with exponential backoff
        raise self.retry(exc=exc, countdown=2 ** self.request.retries)

# Step 2: Queue task from ViewSet (views.py)
class ContentViewSet(SiteSectorModelViewSet):
    @action(detail=True, methods=['post'])
    def generate_images(self, request, pk=None):
        """
        Trigger async image generation
        POST /api/v1/writer/content/{id}/generate_images/
        """
        content = self.get_object()
        
        # Queue background task
        from igny8_core.tasks.writer_tasks import generate_content_images
        
        task = generate_content_images.delay(content.id)
        
        return success_response(
            success=True,
            data={'task_id': task.id},
            message='Image generation started'
        )

# Step 3: Frontend to trigger task
// frontend/src/api/writer.ts
export const generateContentImages = async (contentId: number) => {
  return fetchAPI(`/api/v1/writer/content/${contentId}/generate_images/`, {
    method: 'POST'
  });
};

// frontend/src/pages/Writer/Content.tsx
async function handleGenerateImages(contentId) {
  try {
    const response = await generateContentImages(contentId);
    toast.success('Image generation started');
  } catch (error) {
    toast.error('Failed to start image generation');
  }
}
```

---

## Database Schema Changes

### Feature: Adding/Modifying a Database Column

#### Complete Workflow:

```bash
# Step 1: Add field to model
# File: backend/igny8_core/business/content/models.py
class Content(SiteSectorBaseModel):
    # ... existing fields ...
    seo_score = models.IntegerField(
        default=0,
        validators=[MinValueValidator(0), MaxValueValidator(100)],
        help_text="SEO optimization score (0-100)"
    )

# Step 2: Create migration
$ python manage.py makemigrations writer

# Output: Migrations for 'writer':
#   migrations/0015_content_seo_score.py

# Step 3: Review migration (optional)
$ cat migrations/0015_content_seo_score.py

# Step 4: Apply migration
$ python manage.py migrate

# Step 5: Update serializer to include new field
# File: backend/igny8_core/modules/writer/serializers.py
class ContentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Content
        fields = [
            'id', 'title', 'content_html', 'status',
            'seo_score',  # Add this
            # ... other fields ...
        ]

# Step 6: Update frontend types
// frontend/src/types/models.ts
interface Content {
  id: number;
  title: string;
  contentHtml: string;
  seoScore: number;  // Add this
}

# Step 7: Update components to use new field
```

### Feature: Removing a Database Column

```python
# Step 1: Create migration to remove field
$ python manage.py makemigrations writer --remove-field

# Step 2: Or manually edit model - comment out field
class Content(SiteSectorBaseModel):
    # ... existing fields ...
    # seo_score = models.IntegerField(...)  # REMOVED

# Step 3: Auto-create migration
$ python manage.py makemigrations writer

# Step 4: Apply migration
$ python manage.py migrate

# Step 5: Remove from serializer
# backend/igny8_core/modules/writer/serializers.py
# Remove 'seo_score' from fields list

# Step 6: Remove from frontend types and components
```

### Feature: Modifying a Database Column

```python
# Example: Change word_count max value from 10000 to 20000

# Step 1: Update model
class Tasks(SiteSectorBaseModel):
    word_count = models.IntegerField(
        default=1000,
        validators=[MinValueValidator(100), MaxValueValidator(20000)]  # Changed
    )

# Step 2: Create migration
$ python manage.py makemigrations writer

# Step 3: Apply migration
$ python manage.py migrate

# Step 4: Update serializer if validation changed
class TasksSerializer(serializers.ModelSerializer):
    word_count = serializers.IntegerField(
        min_value=100,
        max_value=20000  # Update
    )

# Step 5: Update frontend validation constants
export const MAX_WORD_COUNT = 20000;  // Update
```

---

## Cross-Module Modifications

### Feature: Adding a Relationship Between Modules

**Example: Link Content to Ideas (Writer → Planner)**

#### Files to Modify:

```python
# Step 1: Backend Model - Add ForeignKey
# backend/igny8_core/business/content/models.py
class Content(SiteSectorBaseModel):
    # ... existing fields ...
    idea = models.ForeignKey(
        'planner.ContentIdeas',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='contents',
        help_text="Source content idea"
    )

# Step 2: Create migration
$ python manage.py makemigrations writer

# Step 3: Apply migration
$ python manage.py migrate

# Step 4: Update serializer to include nested relationship
# backend/igny8_core/modules/writer/serializers.py
from igny8_core.modules.planner.serializers import ContentIdeasSerializer

class ContentSerializer(serializers.ModelSerializer):
    idea = ContentIdeasSerializer(read_only=True)
    idea_id = serializers.PrimaryKeyRelatedField(
        queryset=ContentIdeas.objects.all(),
        source='idea',
        write_only=True
    )
    
    class Meta:
        model = Content
        fields = ['id', 'title', 'idea', 'idea_id', ...]

# Step 5: Update ViewSet to support filtering by idea
# backend/igny8_core/modules/writer/views.py
class ContentViewSet(SiteSectorModelViewSet):
    filterset_fields = ['status', 'cluster_id', 'idea_id']  # Add idea_id
    ordering_fields = ['title', 'created_at', 'idea_id']    # Add idea_id

# Step 6: Frontend - Update type
// frontend/src/types/models.ts
interface Content {
  id: number;
  title: string;
  idea?: Idea;  // Add nested object
  ideaId?: number;  // Add ID for create/update
}

# Step 7: Frontend - Display related idea
// frontend/src/pages/Writer/Content.tsx
{content.idea && (
  <div>Idea: {content.idea.ideaTitle}</div>
)}
```

---

## Common Workflow Patterns

### Pattern 1: Adding a Simple Field to List Page

**Timeline: ~15 minutes**

```
1. Backend Model → Add field with validators
2. DB Migration → makemigrations + migrate
3. Backend Serializer → Add to fields list
4. Backend ViewSet → Add to filters/ordering if needed
5. Frontend Type → Add to interface
6. Frontend Component → Add to table columns
7. Test → Verify in both UI and API
```

**Files Modified:**
- `backend/igny8_core/business/*/models.py`
- `backend/igny8_core/migrations/XXXX_*.py`
- `backend/igny8_core/modules/*/serializers.py`
- `backend/igny8_core/modules/*/views.py`
- `frontend/src/types/models.ts`
- `frontend/src/pages/*/[Page].tsx`

### Pattern 2: Adding a New Feature Page

**Timeline: ~1 hour**

```
1. Backend ViewSet/Action → Create endpoint
2. Backend Serializer → Define response format
3. Frontend API Hook → Create fetch function
4. Frontend Type → Define data interface
5. Frontend Page Component → Create page
6. Frontend Router → Add route
7. Frontend Navigation → Add menu item
8. Test → End-to-end flow
```

**Files Modified:**
- `backend/igny8_core/modules/*/views.py`
- `backend/igny8_core/modules/*/serializers.py`
- `frontend/src/api/*.ts`
- `frontend/src/types/models.ts`
- `frontend/src/pages/*/*.tsx`
- `frontend/src/App.tsx`
- `frontend/src/layout/Sidebar.tsx`

### Pattern 3: Adding Async Processing

**Timeline: ~30 minutes**

```
1. Backend Celery Task → Create task function
2. Backend ViewSet Action → Queue task from endpoint
3. Frontend API Hook → Create trigger function
4. Frontend Component → Add button to trigger
5. Frontend Polling/Polling → Show task status
6. Test → Verify task execution and completion
```

**Files Modified:**
- `backend/igny8_core/tasks/*_tasks.py`
- `backend/igny8_core/modules/*/views.py`
- `frontend/src/api/*.ts`
- `frontend/src/pages/*/*.tsx`

---

## File Organization Index

### Module File Structure Template

For each module (Planner, Writer, Linker, etc.):

```
backend/igny8_core/
├── modules/[module]/
│   ├── views.py                 # ViewSets, @actions
│   ├── serializers.py           # Serializers
│   ├── urls.py                  # Route registration
│   └── apps.py
└── business/[domain]/
    ├── models.py                # Data models
    ├── services/
    │   ├── service1.py          # Business logic
    │   └── service2.py
    └── migrations/
        └── XXXX_*.py            # DB migrations

frontend/src/
├── pages/[Module]/
│   ├── Dashboard.tsx            # Overview page
│   ├── [Feature].tsx            # Feature pages
│   └── [Detail].tsx             # Detail views
├── components/[Module]/
│   ├── [Feature]Table.tsx       # Table components
│   ├── [Feature]Form.tsx        # Form components
│   └── [Feature]Filter.tsx      # Filter components
├── api/
│   └── [module].ts              # API calls
├── store/
│   └── [module]Store.ts         # State management
└── types/
    └── models.ts                # Type definitions
```

### Global Files (All Modules)

| File | Purpose | Where Located |
|------|---------|---------------|
| **API Base Classes** | ViewSet, Serializer base | `backend/igny8_core/api/base.py` |
| **Response Format** | Unified responses | `backend/igny8_core/api/response.py` |
| **Permissions** | Role-based access | `backend/igny8_core/api/permissions.py` |
| **Pagination** | List pagination | `backend/igny8_core/api/pagination.py` |
| **Root Router** | Route registration | `backend/igny8_core/urls.py` |
| **Settings** | Django config | `backend/igny8_core/settings.py` |
| **Auth Models** | User, Site, Sector | `backend/igny8_core/auth/models.py` |
| **API Client** | Frontend HTTP | `frontend/src/api/client.ts` |
| **Auth Store** | User state | `frontend/src/store/authStore.ts` |
| **Site Store** | Site/Sector context | `frontend/src/store/siteStore.ts` |
| **App Router** | Frontend routes | `frontend/src/App.tsx` |
| **Sidebar** | Navigation menu | `frontend/src/layout/Sidebar.tsx` |
| **Constants** | Global constants | `frontend/src/config/constants.ts` |
| **Validators** | Validation rules | `frontend/src/utils/validators.ts` |

---

## Quick Checklists

### Adding a New Column: Checklist

- [ ] Add field to Backend Model (`models.py`)
- [ ] Run `makemigrations` 
- [ ] Run `migrate`
- [ ] Add field to Backend Serializer (`serializers.py`)
- [ ] Add to ViewSet `filterset_fields` if filterable
- [ ] Add to ViewSet `ordering_fields` if sortable
- [ ] Add to Frontend Type (`types/models.ts`)
- [ ] Add to Frontend Component columns config
- [ ] Add to Frontend Table JSX rendering
- [ ] Test API response includes field
- [ ] Test frontend displays column
- [ ] Test filter/sort works (if applicable)

### Adding a New Page: Checklist

- [ ] Create new Page component (`pages/[Module]/[Page].tsx`)
- [ ] Create or update API hook (`api/[module].ts`)
- [ ] Add route to router (`App.tsx`)
- [ ] Add menu item to navigation (`layout/Sidebar.tsx`)
- [ ] Add types if needed (`types/models.ts`)
- [ ] Test page loads
- [ ] Test data fetches
- [ ] Test filters/search work
- [ ] Test pagination works
- [ ] Test error states

### Adding an API Endpoint: Checklist

- [ ] Define endpoint action in ViewSet (`views.py`)
- [ ] Use `@action(detail=...)` decorator
- [ ] Define response format using serializer
- [ ] Add permission check if needed
- [ ] Document docstring
- [ ] Test endpoint with API client
- [ ] Verify unified response format
- [ ] Create frontend API hook (`api/[module].ts`)
- [ ] Test from frontend component
- [ ] Verify error handling

---

**End of Document**

For questions on specific features, refer to:
- Architecture: `00-SYSTEM-ARCHITECTURE-MASTER-REFERENCE.md`
- API Details: `01-IGNY8-REST-API-COMPLETE-REFERENCE.md`
- Workflows: `02-PLANNER-WRITER-WORKFLOW-TECHNICAL-GUIDE.md`
