Files
igny8/docs/06-FEATURE-MODIFICATION-DEVELOPER-GUIDE.md
2025-11-29 22:52:34 +05:00

34 KiB

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
  2. Feature Type Reference Matrix
  3. Frontend Feature Modifications
  4. Backend Feature Modifications
  5. Cross-Module Modifications
  6. Database Schema Changes
  7. Common Workflow Patterns
  8. File Organization Index

Quick Navigation by Feature Type

🎯 Find Your Feature Type


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":

# 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":

# 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":

// 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:

# 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:

# 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:

# 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:

# 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

# 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:

# 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

# 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

# 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:

# 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