# Planner Module **Last Verified:** December 25, 2025 **Status:** ✅ Active **Backend Path:** `backend/igny8_core/modules/planner/` **Frontend Path:** `frontend/src/pages/Planner/` --- ## Quick Reference | What | File | Key Items | |------|------|-----------| | Models | `modules/planner/models.py` | `Keywords`, `Clusters`, `ContentIdeas` | | Views | `modules/planner/views.py` | `KeywordViewSet`, `ClusterViewSet`, `ContentIdeaViewSet` | | Serializers | `modules/planner/serializers.py` | Keyword/Cluster/Idea serializers | | AI Functions | `ai/functions/clustering.py` | `AutoClusterFunction` | | AI Functions | `ai/functions/ideas.py` | `GenerateIdeasFunction` | | Frontend Pages | `pages/Planner/Keywords.tsx` | Keyword management | | Frontend Pages | `pages/Planner/Clusters.tsx` | Cluster management | | Frontend Pages | `pages/Planner/Ideas.tsx` | Content ideas | --- ## Purpose The Planner module manages the SEO content planning pipeline: ``` SeedKeywords (Global) → Keywords (Site/Sector) → Clusters → ContentIdeas → Tasks ``` --- ## Data Models ### Keywords | Field | Type | Purpose | |-------|------|---------| | account | FK | Owner account | | site | FK | Parent site | | sector | FK | Parent sector | | seed_keyword | FK | Reference to global SeedKeyword | | keyword | CharField | Keyword text | | search_volume | Integer | Monthly search volume | | difficulty | Integer | SEO difficulty (0-100) | | cpc | Decimal | Cost per click | | search_intent | CharField | informational/commercial/transactional/navigational | | status | CharField | new/mapped/used | | cluster | FK | Assigned cluster (nullable) | | created_at | DateTime | Creation date | ### Clusters | Field | Type | Purpose | |-------|------|---------| | account | FK | Owner account | | site | FK | Parent site | | sector | FK | Parent sector | | name | CharField | Cluster name | | description | TextField | Cluster description | | primary_keyword | FK | Main keyword | | status | CharField | draft/active/complete | | keyword_count | Integer | Number of keywords | | created_at | DateTime | Creation date | ### ContentIdeas | Field | Type | Purpose | |-------|------|---------| | account | FK | Owner account | | site | FK | Parent site | | sector | FK | Parent sector | | cluster | FK | Source cluster | | title | CharField | Content title | | description | TextField | Content brief | | target_keywords | JSON | Keywords to target | | content_type | CharField | blog_post/guide/comparison/etc. | | word_count_target | Integer | Target word count | | status | CharField | draft/queued/used | | priority | Integer | Priority score | | created_at | DateTime | Creation date | --- ## API Endpoints ### Keywords | Method | Path | Handler | Purpose | |--------|------|---------|---------| | GET | `/api/v1/planner/keywords/` | `KeywordViewSet.list` | List keywords with filtering | | POST | `/api/v1/planner/keywords/` | `KeywordViewSet.create` | Create single keyword | | GET | `/api/v1/planner/keywords/{id}/` | `KeywordViewSet.retrieve` | Get keyword detail | | PUT | `/api/v1/planner/keywords/{id}/` | `KeywordViewSet.update` | Update keyword | | DELETE | `/api/v1/planner/keywords/{id}/` | `KeywordViewSet.destroy` | Soft delete keyword | | POST | `/api/v1/planner/keywords/bulk_delete/` | `KeywordViewSet.bulk_delete` | Hard delete multiple | | POST | `/api/v1/planner/keywords/bulk_status/` | `KeywordViewSet.bulk_status` | Update status for multiple | | POST | `/api/v1/planner/keywords/add_to_workflow/` | `KeywordViewSet.add_to_workflow` | Add SeedKeywords to workflow | **Filters:** `?site_id=`, `?sector_id=`, `?status=`, `?cluster_id=`, `?difficulty_min=`, `?difficulty_max=`, `?volume_min=`, `?volume_max=` ### Clusters | Method | Path | Handler | Purpose | |--------|------|---------|---------| | GET | `/api/v1/planner/clusters/` | `ClusterViewSet.list` | List clusters | | POST | `/api/v1/planner/clusters/` | `ClusterViewSet.create` | Create cluster manually | | POST | `/api/v1/planner/clusters/auto_cluster/` | `ClusterViewSet.auto_cluster` | AI-powered clustering | | POST | `/api/v1/planner/clusters/generate_ideas/` | `ClusterViewSet.generate_ideas` | Generate ideas from clusters | ### Content Ideas | Method | Path | Handler | Purpose | |--------|------|---------|---------| | GET | `/api/v1/planner/ideas/` | `ContentIdeaViewSet.list` | List ideas | | POST | `/api/v1/planner/ideas/` | `ContentIdeaViewSet.create` | Create idea manually | | POST | `/api/v1/planner/ideas/create_tasks/` | `ContentIdeaViewSet.create_tasks` | Convert ideas to tasks | --- ## Business Logic ### Auto Clustering (AI) **Trigger:** User clicks "Auto Cluster" button **AI Function:** `AutoClusterFunction` **Credit Cost:** Per batch (configurable) **Flow:** 1. User selects keywords (or all unclustered) 2. Frontend calls `POST /clusters/auto_cluster/` 3. Backend validates minimum 5 keywords 4. AIEngine executes `AutoClusterFunction`: - Sends keywords to GPT-4 - AI groups by semantic similarity - Returns cluster assignments 5. Creates/updates `Clusters` records 6. Assigns keywords to clusters 7. Returns created clusters ### Generate Ideas (AI) **Trigger:** User clicks "Generate Ideas" on cluster(s) **AI Function:** `GenerateIdeasFunction` **Credit Cost:** Per idea generated **Flow:** 1. User selects clusters 2. Frontend calls `POST /clusters/generate_ideas/` 3. Backend validates clusters have keywords 4. AIEngine executes `GenerateIdeasFunction`: - Analyzes cluster keywords - Generates content titles + briefs - Suggests word counts and content types 5. Creates `ContentIdeas` records 6. Returns created ideas ### Add Keywords to Workflow **Trigger:** User selects SeedKeywords in setup **Credit Cost:** None **Flow:** 1. User browses global SeedKeywords 2. Selects keywords to add to their sector 3. Frontend calls `POST /keywords/add_to_workflow/` 4. Backend creates `Keywords` records linked to SeedKeywords 5. Keywords appear in Planner for clustering --- ## Frontend Pages ### Keywords Page (`/planner/keywords`) - Table of all keywords with filtering - Bulk actions: delete, update status - Add keywords from SeedKeyword library - Import keywords from CSV - Assign to clusters manually ### Clusters Page (`/planner/clusters`) - Grid/list of clusters - Auto-cluster action (AI) - Generate ideas action (AI) - View keywords in cluster - Cluster status management ### Ideas Page (`/planner/ideas`) - Table of content ideas - Convert to tasks action - Edit idea details - Priority management --- ## Integration Points | From | To | Trigger | |------|----|---------| | SeedKeywords | Keywords | Add to workflow | | Keywords | Clusters | Auto clustering | | Clusters | ContentIdeas | Generate ideas | | ContentIdeas | Tasks | Create tasks | | Automation Stage 1 | Clusters | Automated clustering | | Automation Stage 2 | ContentIdeas | Automated idea generation | --- ## Common Issues | Issue | Cause | Fix | |-------|-------|-----| | Clustering fails | Less than 5 keywords | Ensure minimum keywords | | Ideas not generating | Cluster has no keywords | Assign keywords to cluster | | Keywords not showing | Wrong site/sector filter | Check active site/sector | | Duplicate keywords | Same keyword added twice | Check seed_keyword reference | --- ## Planned Changes | Feature | Status | Description | |---------|--------|-------------| | Keyword import improvements | 🔜 Planned | Better CSV parsing and validation | | Cluster merging | 🔜 Planned | Merge similar clusters | | Idea prioritization | 🔜 Planned | AI-based priority scoring |