Files
igny8/docs/plans/final-dev-guides-of-futute-implementation/DocB-Platform-Modules-Dev-Guide.md
2026-03-08 02:36:44 +00:00

1701 lines
69 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Doc B — IGNY8 Platform Modules: Development Guide for Claude Code
**Version:** 1.0
**Date:** March 2026
**For:** Claude Code (Opus 4.6) in VSCode on IGNY8 repo
**Purpose:** Step-by-step implementation guide for all IGNY8 platform module enhancements — Content Types Writing, Taxonomy & Term Content, Optimizer, GSC Integration, Rich Schema & SERP Enhancement, Socializer, and Video Creator
**Rule:** Nothing currently working breaks. All new functionality uses the existing pipeline pattern. All new modules use feature flags. Existing Writer/Planner/Automation pages are enhanced, not replaced.
**Dependency:** Doc A (SAG Architecture) provides the blueprint, cluster, and attribute data that several modules here consume. Content Types Writing and Taxonomy & Term Content should ideally complete before Optimizer, but GSC and Rich Schema can run in parallel.
---
## Table of Contents
1. [System Context — Current Pipeline & Module Structure](#1-system-context)
2. [Implementation Sequence](#2-implementation-sequence)
3. [Module 1: Content Types Writing](#3-content-types-writing)
4. [Module 2: Taxonomy & Term Content](#4-taxonomy--term-content)
5. [Module 3: Optimizer Module](#5-optimizer-module)
6. [Module 4: GSC Integration](#6-gsc-integration)
7. [Module 5: Rich Schema & SERP Enhancement](#7-rich-schema)
8. [Module 6: Socializer](#8-socializer)
9. [Module 7: Video Creator](#9-video-creator)
10. [Updated Automation Pipeline — All Stages](#10-updated-automation-pipeline)
11. [Updated Navigation & Sidebar](#11-updated-navigation)
12. [Complete API Endpoint Registry](#12-api-endpoints)
13. [Complete AI Function Registry](#13-ai-functions)
14. [Complete Celery Task Registry](#14-celery-tasks)
15. [Feature Flag Registry](#15-feature-flags)
16. [Credit Cost Summary](#16-credit-costs)
17. [Cross-Module Dependencies](#17-cross-dependencies)
---
## 1. System Context — Current Pipeline & Module Structure {#1-system-context}
### 1.1 Current Content Pipeline (What Exists)
```
Stage 1: Process New Keywords → modules/planner/ + business/planning/
Stage 2: AI Cluster Keywords → ai/functions/auto_cluster.py
Stage 3: Generate Content Ideas → ai/functions/generate_ideas.py + modules/planner/
Stage 4: Create Writer Tasks → modules/writer/
Stage 5: Generate Article Content → ai/functions/generate_content.py + business/content/
Stage 6: Extract Image Prompts → ai/functions/generate_image_prompts.py
Stage 7: Generate Images → ai/functions/generate_images.py → Review Queue
```
All stages execute via Celery tasks defined in `tasks/`. Automation orchestration lives in `business/automation/`. Configuration per site is in `AutomationConfig`.
### 1.2 Current Content Model Fields (Relevant)
```python
# modules/writer/models.py — Content model (simplified)
class Content(SiteSectorBaseModel):
task = ForeignKey(Tasks)
title = CharField()
slug = SlugField()
content = TextField() # Full HTML
meta_title = CharField()
meta_description = TextField()
status = CharField() # queue, draft, review, published
content_type = CharField() # Currently: 'post', 'page'
word_count = IntegerField()
# ... images, keywords, publishing fields
```
### 1.3 Current Inactive Modules
| Module | Backend | API | Frontend | Flag |
|--------|---------|-----|----------|------|
| Linker | `business/linking/` | `modules/linker/` | `pages/Linker/`, `api/linker.api.ts` | `linker_enabled` |
| Optimizer | `business/optimization/` | `modules/optimizer/` | `pages/Optimizer/`, `api/optimizer.api.ts` | `optimizer_enabled` |
### 1.4 Existing Prompt System
Prompts are stored in `PromptTemplate` model or defaults in code. Templates exist for: `auto_cluster`, `generate_ideas`, `generate_content`, `generate_image_prompts`, `optimize_content` (pending). Users customize via Settings → Prompts (Thinker module).
### 1.5 Existing Integration Architecture
WordPress communication uses:
- `Site.wp_api_key` for authentication
- Webhook endpoints for sync (plugin → IGNY8 and IGNY8 → plugin)
- `business/integration/` for sync services
- `modules/integration/` for API endpoints
- Plugin file: `data/site-collection.php` for data gathering
### 1.6 Existing Credit System
All AI operations deduct credits via `CreditService.check_credits()` → execute → `CreditService.deduct_credits_for_operation()`. Costs configured per model in `AIModelConfig`.
---
## 2. Implementation Sequence {#2-implementation-sequence}
```
MODULE 1 ─── Content Types Writing (FIRST — foundation for all others)
│ Extends Writer pipeline with new content types and structures.
│ No new module — enhances existing Planner + Writer + Publisher.
MODULE 2 ─── Taxonomy & Term Content
│ Depends on Module 1 for content structures.
│ Requires taxonomy sync restoration.
│ Enhances Planner + Writer + Publisher + Integration.
MODULE 3 ─── Optimizer (activate existing module)
│ Depends on Module 1+2 for content type support.
│ Benefits from SAG cluster mapping (Doc A Phase 5).
│ Activates optimizer_enabled flag.
MODULE 4 ─── GSC Integration (CAN PARALLEL with 1-3)
│ Independent of content pipeline changes.
│ New module entirely: OAuth, URL Inspection, metrics.
MODULE 5 ─── Rich Schema & SERP Enhancement (CAN PARALLEL with 4)
│ Enhances content pipeline Stage 5 + adds retroactive engine.
│ Benefits from Module 1 (content type classification).
MODULE 6 ─── Socializer
│ Depends on published content (any type from Module 1+2).
│ New module: OAuth, platform connections, scheduling.
│ New automation Stage 8.
MODULE 7 ─── Video Creator
Depends on Module 6 infrastructure (OAuth, scheduling, media storage).
New module: script generation, TTS, video assembly.
New automation Stage 9.
```
**Parallel tracks:**
- GSC (Module 4) is fully independent — start anytime
- Rich Schema (Module 5) can start alongside GSC
- Socializer OAuth/platform connections can start while earlier modules finish
---
## 3. Module 1: Content Types Writing {#3-content-types-writing}
### 3.1 What This Module Delivers
IGNY8 currently writes blog posts (`content_type='post'`). This module extends the Writer to produce pages, products (WooCommerce), services, company pages, taxonomy landing pages, and cluster hub pages — all through the same pipeline.
### 3.2 Backend: Content Type Expansion
**Modify:** `modules/writer/models.py` — extend `content_type` choices on Content model
```python
# Add new choices to Content.content_type:
CONTENT_TYPE_CHOICES = [
('post', 'Blog Post'), # Existing
('page', 'Page'), # Existing (limited use)
('product', 'Product Page'), # NEW
('service', 'Service Page'), # NEW
('company_page', 'Company Page'), # NEW
('taxonomy_landing', 'Taxonomy Landing'), # NEW
('cluster_hub', 'Cluster Hub Page'), # NEW
('comparison', 'Comparison Page'), # NEW
('brand_page', 'Brand Page'), # NEW
]
```
**Add new field:** `content_structure` on Content model (or extend existing structure field)
```python
# Add to Content model:
content_structure = models.CharField(
max_length=30, null=True, blank=True,
choices=[
# Blog structures (existing, now explicit)
('guide_tutorial', 'Guide/Tutorial'),
('comparison', 'Comparison'),
('review', 'Review'),
('how_to', 'How To'),
('question', 'Question/Answer'),
('top_listicle', 'Top Listicle'),
# Page structures (NEW)
('landing_page', 'Landing Page'),
('about_page', 'About Page'),
('contact_page', 'Contact Page'),
# Product structures (NEW)
('product_single', 'Single Product'),
('product_collection', 'Product Collection'),
# Service structures (NEW)
('service_single', 'Single Service'),
('service_area', 'Service Area Page'),
# Company structures (NEW)
('company_about', 'Company About'),
('company_team', 'Company Team'),
('company_careers', 'Company Careers'),
# Taxonomy structures (NEW)
('category_archive', 'Category Archive'),
('tag_archive', 'Tag Archive'),
('attribute_archive', 'Attribute Archive'),
('cluster_hub', 'Cluster Hub'),
]
)
```
**Modify:** `modules/planner/models.py` — extend ContentIdea model with same fields
```python
# Add to ContentIdea model:
content_type = models.CharField(max_length=30, null=True, blank=True) # Same choices as Content
content_structure = models.CharField(max_length=30, null=True, blank=True)
```
**Modify:** `modules/writer/models.py` — extend Tasks model
```python
# Add to Tasks model:
content_type = models.CharField(max_length=30, default='post')
content_structure = models.CharField(max_length=30, null=True, blank=True)
```
### 3.3 Backend: Type-Specific Prompt Templates
**Location:** Add to existing PromptTemplate system or as defaults in `ai/functions/generate_content.py`
Each content_type × content_structure combination gets a distinct prompt. The prompt includes type-specific section requirements:
| Content Type | Required Sections in Prompt |
|-------------|---------------------------|
| **product** | Features/benefits, specs table, comparison to alternatives, FAQs, CTA, product schema placeholders |
| **service** | Service overview, process steps, outcomes/results, FAQs, local SEO sections (if location-based), CTA |
| **company_page** | Brand mission/values, history, team bios (if team page), FAQ, media/press block |
| **taxonomy_landing** | Intro + topical definition, key subtopics with internal link placeholders, related items, FAQ section |
| **cluster_hub** | Comprehensive guide introduction, section per supporting topic, product/service roundup, FAQ, internal linking sections |
| **comparison** | Head-to-head comparison table, pros/cons per item, winner recommendation, FAQ |
**Register new prompt templates:**
```python
# In PromptTemplate seeding or defaults:
'generate_content_product' # Product page prompt
'generate_content_service' # Service page prompt
'generate_content_company' # Company page prompt
'generate_content_taxonomy_landing' # Taxonomy landing prompt
'generate_content_cluster_hub' # Cluster hub prompt
'generate_content_comparison' # Comparison page prompt
```
### 3.4 Backend: Type-Specific Idea Generation
**Modify:** `ai/functions/generate_ideas.py` — enhance `GenerateContentIdeas`
When generating ideas, the system now considers content_type:
- Product ideas: features/specs/benefits angle, "Best X for Y" format
- Service ideas: process/outcomes angle, "How [Service] Works" format
- Company page ideas: mission/team/careers angle
- Taxonomy landing ideas: topical overview, "Complete Guide to [Term]" format
The existing function stays but gets an additional parameter: `target_content_type`. If provided, idea generation is type-aware. If not provided (legacy), defaults to blog post ideas.
### 3.5 Backend: Publishing Enhancement
**Modify:** `business/publishing/` — extend publishing to handle content types
```python
# business/publishing/wordpress_publisher.py — extend publish logic:
def publish_content(content):
if content.content_type == 'post':
# Existing: publish as WordPress post
pass
elif content.content_type == 'page':
# Publish as WordPress page
pass
elif content.content_type == 'product':
# Publish as WooCommerce product (requires WooCommerce API)
pass
elif content.content_type == 'service':
# Publish as custom post type 'service' (requires theme/plugin CPT)
pass
elif content.content_type == 'taxonomy_landing':
# Publish as term description content (Module 2 handles this)
pass
elif content.content_type == 'cluster_hub':
# Publish as WordPress page with hub template
pass
```
**Plugin side:** The IGNY8 Bridge plugin needs enhanced content receiving:
```
igny8-plugin/includes/modules/content-sync/
├── class-content-mapper.php # MODIFY: map IGNY8 content_type to WP post type
```
Mapping:
| IGNY8 content_type | WordPress post_type | Template |
|-------------------|--------------------|---------|
| post | post | Standard |
| page | page | Default page |
| product | product (WooCommerce) | Product template |
| service | service (CPT from theme) | Service template |
| company_page | page | Company page template |
| taxonomy_landing | term description | Term archive template |
| cluster_hub | page | Hub page template |
| comparison | post | Standard (with comparison CSS) |
### 3.6 Frontend: Writer UI Enhancement
**Location:** `pages/Writer/` — enhance existing views
**Task Creation — Add content type selector:**
```
pages/Writer/
├── components/
│ ├── TaskCreationForm.tsx # MODIFY: add content_type dropdown + content_structure dropdown
│ └── ContentTypeSelector.tsx # NEW: visual card selector for content type
```
When creating a new task (manual mode), user sees:
- Content Type dropdown: Blog Post, Page, Product, Service, Company Page, Taxonomy Landing, Cluster Hub, Comparison
- Content Structure dropdown: dynamically filtered based on content_type selection
- Existing fields (title, keywords, cluster, sector) remain unchanged
**Content List — Show type badge:**
```
pages/Writer/
├── components/
│ └── ContentListItem.tsx # MODIFY: add content_type badge next to title
```
Each content item in Queue/Drafts/Review/Published shows a small badge: "Post", "Product", "Hub", "Service", etc.
**Ideas List — Show type:**
```
pages/Planner/
├── components/
│ └── IdeaListItem.tsx # MODIFY: show content_type and content_structure
```
### 3.7 Frontend: No New Pages
Module 1 adds NO new pages to the sidebar. Everything happens within existing Planner and Writer pages. The changes are:
- Dropdowns added to task creation
- Badges added to list items
- Type-specific preview in content review
---
## 4. Module 2: Taxonomy & Term Content {#4-taxonomy--term-content}
### 4.1 What This Module Delivers
Every taxonomy term (WordPress categories, tags, WooCommerce product categories/attributes, custom taxonomies from SAG) becomes a rich SEO landing page generated through the same pipeline as posts.
### 4.2 Backend: Restore Taxonomy Sync
**Current state:** Taxonomy sync was partially implemented then removed ("legacy removed"). `ContentTaxonomy` model exists. WordPress client knows how to fetch categories/tags/WooCommerce attributes.
**Restore and enhance in:** `business/integration/`
```python
# business/integration/taxonomy_sync_service.py # RESTORE/REWRITE
class TaxonomySyncService:
def sync_taxonomies(self, site):
"""Fetch all taxonomies + terms from WordPress and sync to ContentTaxonomy."""
# 1. Fetch via plugin API: categories, tags, WooCommerce product_cat,
# product_tag, all pa_* attributes, custom taxonomies (from SAG)
# 2. Create/update ContentTaxonomy records
# 3. Map terms to clusters where possible (using SAG blueprint if active)
pass
def publish_term_content(self, content_taxonomy, content):
"""Push generated content back to WordPress term description."""
# 1. Content → term description HTML
# 2. POST to plugin endpoint: /wp-json/igny8/v1/terms/{term_id}/content
# 3. Update ContentTaxonomy sync status
pass
```
**Plugin endpoint needed:**
```
POST /wp-json/igny8/v1/terms/{term_id}/content
Body: {description: "HTML content", meta: {igny8_term_content, igny8_term_faq, ...}}
```
### 4.3 Backend: Term-to-Cluster Mapping Service
```python
# business/planning/cluster_mapping_service.py # NEW
class ClusterMappingService:
def map_term_to_cluster(self, term_name, term_description, site):
"""Match a taxonomy term to the best SAG cluster."""
# If SAG blueprint active: match term to cluster by attribute value overlap
# If no blueprint: use AI semantic similarity to existing clusters
# Return: cluster_id, confidence_score
pass
def bulk_map_terms(self, terms, site):
"""Map all terms for a site to clusters."""
pass
```
### 4.4 Backend: Term Content Generation
The key insight: term content generation follows the SAME pipeline as post content. The difference is in content_type and publishing destination.
**Idea generation for terms:**
```python
# business/planning/ — extend idea generation
def generate_term_ideas(site, terms):
"""For each taxonomy term without content, create a ContentIdea."""
for term in terms:
idea = ContentIdea(
title=f"Complete Guide to {term.name}",
content_type='taxonomy_landing',
content_structure='category_archive', # or tag_archive, attribute_archive
cluster=term.mapped_cluster,
idea_source='sag_blueprint' if site.sag_blueprint_id else 'keyword_clustering',
# ... sector, keywords
)
```
**Task creation and content generation** use the same pipeline as Module 1 — the content_type='taxonomy_landing' selects the appropriate prompt template.
**Publishing** goes to term description instead of post content (handled by `TaxonomySyncService.publish_term_content()`).
### 4.5 Backend: ContentTaxonomy Model Enhancement
**Modify:** existing `ContentTaxonomy` model (if it exists) or create:
```python
# modules/planner/models.py or modules/integration/models.py
class ContentTaxonomy(SiteSectorBaseModel):
# Existing fields...
external_taxonomy = models.CharField(max_length=100) # 'category', 'post_tag', 'pa_color', etc.
external_term_id = models.IntegerField()
name = models.CharField(max_length=200)
slug = models.SlugField(max_length=200)
description = models.TextField(blank=True)
parent_term_id = models.IntegerField(null=True, blank=True)
post_count = models.IntegerField(default=0)
# NEW fields:
mapped_cluster_id = models.ForeignKey('sag.SAGCluster', null=True, blank=True, on_delete=models.SET_NULL)
has_generated_content = models.BooleanField(default=False)
generated_content_id = models.ForeignKey('writer.Content', null=True, blank=True, on_delete=models.SET_NULL)
content_sync_status = models.CharField(max_length=20, default='pending',
choices=[('pending','Pending'),('synced','Synced'),('failed','Failed')])
last_synced_at = models.DateTimeField(null=True, blank=True)
```
### 4.6 Frontend: Taxonomy Management UI
**Location:** Add to Planner section
```
frontend/src/pages/Planner/
├── Taxonomies.tsx # NEW — list all synced taxonomies + terms
├── components/
│ ├── TaxonomyList.tsx # Taxonomy groups with term counts
│ ├── TermList.tsx # Terms within a taxonomy with content status
│ ├── TermClusterMapper.tsx # Assign/reassign cluster per term
│ └── TermContentStatus.tsx # Content generated? Published? Sync status?
```
**Sidebar integration:** Add "Taxonomies" as a sub-item under Planner:
```
WORKFLOW
├── Planner
│ ├── Keywords
│ ├── Clusters
│ ├── Ideas
│ └── Taxonomies (NEW)
├── Writer
...
```
**Taxonomy List view:**
- Shows all synced taxonomies grouped: WordPress Default (categories, tags), WooCommerce (product_cat, product_tag, pa_*), Custom/SAG (from blueprint)
- Per taxonomy: term count, terms with content, terms without content
- "Sync Taxonomies" button to trigger fresh sync from WordPress
- "Generate All Term Content" button to batch-create ideas for all unmapped terms
**Term Detail view:**
- Term name, slug, description, post count
- Cluster mapping: current cluster (or "Unmapped"), dropdown to change
- Content status: Not generated / Draft / Review / Published
- "Generate Content" button for individual term
- Preview of generated content
### 4.7 Frontend: Automation Integration
When automation runs with taxonomy content enabled:
- Stage 3 (Idea Generation) includes term ideas alongside post ideas
- Ideas list in Planner shows term ideas with "Taxonomy Landing" badge
- Writer Queue/Drafts show term content alongside post content
- Publishing routes term content to term description instead of creating a new post
---
## 5. Module 3: Optimizer Module {#5-optimizer-module}
### 5.1 What This Module Delivers
Activates the existing `optimizer_enabled` module. Analyzes and optimizes existing published content: maps to clusters, rewrites structure for intent alignment, refreshes SEO metadata, generates schema markup.
### 5.2 Backend: Implement OptimizeContent AI Function
**Location:** `ai/functions/optimize_content.py` — currently PENDING, implement it
```python
class OptimizeContent:
"""
Takes existing content and produces an optimized version:
- Maps to best-matching cluster
- Rewrites structure for intent alignment
- Refreshes meta title/description
- Adds missing sections (FAQs, comparisons, etc.)
- Generates schema JSON-LD
"""
def execute(self, content, cluster=None, optimization_config=None):
# 1. If no cluster provided, call ClusterMappingService to find best match
# 2. Analyze current content: heading structure, keyword density, missing sections
# 3. Generate optimized version with SAG context
# 4. Generate before/after scores
# 5. Return: optimized_content, meta, schema, scores, diff_summary
pass
```
### 5.3 Backend: Optimizer Service
```python
# business/optimization/optimizer_service.py # IMPLEMENT (file exists, logic pending)
class OptimizerService:
def analyze_content(self, content):
"""Score content against its cluster targets. Return analysis report."""
# Keyword coverage score
# Heading structure score
# Content length assessment
# Missing sections detection
# Internal link opportunities
# Schema coverage
pass
def optimize_content(self, content, apply_mode='manual'):
"""Generate optimized version. apply_mode: 'manual' (review first) or 'auto'."""
pass
def batch_optimize(self, site, content_ids):
"""Queue batch optimization as Celery tasks."""
pass
def generate_schema(self, content):
"""Generate appropriate JSON-LD schema based on content_type."""
pass
```
### 5.4 Backend: Optimizer Models
**Modify/create in:** `modules/optimizer/models.py`
```python
class OptimizationJob(SiteSectorBaseModel):
"""Tracks a single optimization operation."""
content = models.ForeignKey('writer.Content', on_delete=models.CASCADE)
status = models.CharField(max_length=20, choices=[
('pending', 'Pending'),
('analyzing', 'Analyzing'),
('optimized', 'Optimized'),
('applied', 'Applied'),
('rejected', 'Rejected'),
], default='pending')
original_score = models.FloatField(null=True, blank=True)
optimized_score = models.FloatField(null=True, blank=True)
cluster_match = models.ForeignKey('sag.SAGCluster', null=True, blank=True, on_delete=models.SET_NULL)
cluster_confidence = models.FloatField(null=True, blank=True)
optimized_content = models.TextField(blank=True)
optimized_meta_title = models.CharField(max_length=300, blank=True)
optimized_meta_description = models.TextField(blank=True)
generated_schema = models.JSONField(default=dict, blank=True)
diff_summary = models.JSONField(default=dict, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
applied_at = models.DateTimeField(null=True, blank=True)
```
### 5.5 Backend: Optimizer API
**Enhance:** `modules/optimizer/views.py`
```python
# POST /api/v1/optimizer/analyze/
# Input: {content_id}
# Output: {score, cluster_match, recommendations}
# POST /api/v1/optimizer/optimize/
# Input: {content_id, cluster_id (optional override)}
# Output: {job_id, optimized_preview}
# POST /api/v1/optimizer/apply/{job_id}/
# Input: {job_id}
# Output: {success, updated_content}
# POST /api/v1/optimizer/batch/
# Input: {content_ids: [...]}
# Output: {jobs: [{content_id, job_id}]}
# GET /api/v1/optimizer/jobs/
# List all optimization jobs with status
```
### 5.6 Frontend: Optimizer Page
**Location:** `pages/Optimizer/` — existing but INACTIVE, implement UI
```
frontend/src/pages/Optimizer/
├── OptimizerDashboard.tsx # IMPLEMENT — overview of optimization opportunities
│ ├── ContentScoreList.tsx # All content sorted by optimization score (lowest first)
│ ├── ClusterCoverage.tsx # Which clusters have optimized vs unoptimized content
│ └── OptimizationQueue.tsx # Active/pending optimization jobs
├── OptimizeContent.tsx # IMPLEMENT — single content optimization view
│ ├── BeforeAfterView.tsx # Side-by-side original vs optimized
│ ├── ScoreComparison.tsx # Score breakdown: before vs after
│ ├── ClusterMatcher.tsx # Show matched cluster, allow override
│ ├── SchemaPreview.tsx # Preview generated JSON-LD
│ └── ApplyRejectButtons.tsx # Apply optimization or reject
└── BatchOptimize.tsx # IMPLEMENT — select multiple, batch optimize
```
**Sidebar:** Optimizer appears under WORKFLOW when `optimizer_enabled = True` (existing behavior, now with actual UI).
### 5.7 Settings Integration
**Location:** `pages/Settings/` — add Optimizer settings tab
Settings for Optimizer module:
- Enable/disable Optimizer
- Default schema type per content type (Article, Product, FAQ, etc.)
- Keyword density targets (percentage range)
- Content length guidelines (min/max per content type)
- Auto-apply vs manual review toggle
- Exclude content from optimization (by ID or date range)
---
## 6. Module 4: GSC Integration {#6-gsc-integration}
### 6.1 What This Module Delivers
Google Search Console integration: OAuth connection, URL Inspection API, auto-indexing pipeline, search metrics dashboard, plugin status sync.
### 6.2 Backend: New Django App
```
backend/igny8_core/
├── gsc/ # NEW Django app
│ ├── __init__.py
│ ├── apps.py
│ ├── models.py # GSCConnection, URLTrackingRecord, SearchMetric
│ ├── serializers.py
│ ├── views.py # OAuth flow, inspection, metrics endpoints
│ ├── urls.py # /api/v1/gsc/*
│ ├── admin.py
│ ├── services/
│ │ ├── __init__.py
│ │ ├── oauth_service.py # Google OAuth token management
│ │ ├── site_mapping_service.py # Map IGNY8 sites to GSC properties
│ │ ├── inspection_service.py # URL Inspection API calls
│ │ ├── indexing_service.py # Auto-indexing queue + pipeline
│ │ ├── metrics_service.py # Search Analytics API data fetch
│ │ └── quota_service.py # Daily quota tracking (2,000/day)
│ ├── tasks.py # Celery tasks for queue processing
│ └── migrations/
```
### 6.3 Backend: Models
```python
# gsc/models.py
class GSCConnection(AccountBaseModel):
"""One Google OAuth connection per account. Manages all sites."""
google_email = models.EmailField()
access_token = models.TextField()
refresh_token = models.TextField()
token_expiry = models.DateTimeField()
scopes = models.JSONField(default=list)
is_active = models.BooleanField(default=True)
connected_at = models.DateTimeField(auto_now_add=True)
last_refreshed = models.DateTimeField(null=True, blank=True)
class GSCSiteMapping(models.Model):
"""Maps an IGNY8 site to a GSC property."""
site = models.OneToOneField('auth.Site', on_delete=models.CASCADE, related_name='gsc_mapping')
gsc_property = models.CharField(max_length=300, help_text='e.g., sc-domain:example.com')
property_type = models.CharField(max_length=20, choices=[
('domain', 'Domain Property'),
('url_prefix', 'URL Prefix'),
])
status = models.CharField(max_length=20, choices=[
('matched', 'Auto-Matched'),
('manual', 'Manually Mapped'),
('not_found', 'Not Found in GSC'),
])
verified = models.BooleanField(default=False)
mapped_at = models.DateTimeField(auto_now_add=True)
class URLTrackingRecord(SiteSectorBaseModel):
"""Tracks indexing status for each URL."""
url = models.URLField()
content = models.ForeignKey('writer.Content', null=True, blank=True, on_delete=models.SET_NULL)
is_igny8_content = models.BooleanField(default=True)
# Inspection results
index_status = models.CharField(max_length=30, choices=[
('unknown', 'Unknown'),
('indexed', 'Indexed'),
('not_indexed', 'Not Indexed'),
('indexing_requested', 'Indexing Requested'),
('error', 'Error'),
('noindex', 'Noindex Detected'),
], default='unknown')
coverage_state = models.CharField(max_length=100, blank=True)
last_crawl_time = models.DateTimeField(null=True, blank=True)
crawl_status = models.CharField(max_length=50, blank=True)
# Queue management
queue_priority = models.IntegerField(default=50)
next_check_at = models.DateTimeField(null=True, blank=True)
check_count = models.IntegerField(default=0)
max_checks = models.IntegerField(default=4)
last_inspected_at = models.DateTimeField(null=True, blank=True)
indexing_requested_at = models.DateTimeField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
class SearchMetricSnapshot(SiteSectorBaseModel):
"""Daily/weekly search metrics from GSC Search Analytics API."""
date = models.DateField()
dimension = models.CharField(max_length=20, choices=[
('page', 'Page'), ('query', 'Query'),
('country', 'Country'), ('device', 'Device'),
])
dimension_value = models.CharField(max_length=500)
clicks = models.IntegerField(default=0)
impressions = models.IntegerField(default=0)
ctr = models.FloatField(default=0.0)
position = models.FloatField(default=0.0)
is_igny8_content = models.BooleanField(default=False)
```
### 6.4 Backend: Queue Processing
```python
# gsc/tasks.py
@shared_task
def process_indexing_queue():
"""Process URL inspection/indexing queue. Runs every 5 minutes."""
# 1. Check daily quota (2,000 inspections, resets midnight PT)
# 2. Pick next item from queue by priority
# 3. Call URL Inspection API
# 4. Parse response: indexed? → done. Not indexed? → request indexing
# 5. Schedule re-inspection (24h, 3d, 6d, 13d)
# 6. Wait 3 seconds between calls
# 7. Sync status to WordPress plugin
pass
@shared_task
def fetch_search_metrics(site_id):
"""Fetch search analytics data from GSC. Runs daily."""
pass
@shared_task
def auto_index_published_content(content_id):
"""Triggered when content is published to WordPress. Adds to indexing queue."""
pass
@shared_task
def sync_index_status_to_plugin(site_id):
"""Batch sync index statuses to WordPress plugin. Runs every 5 min."""
pass
```
### 6.5 Backend: API Endpoints
```python
# gsc/urls.py
# OAuth
POST /api/v1/gsc/connect/ # Initiate OAuth flow
GET /api/v1/gsc/callback/ # OAuth callback
DELETE /api/v1/gsc/disconnect/ # Revoke connection
GET /api/v1/gsc/status/ # Connection status
# Site mapping
GET /api/v1/gsc/sites/ # List GSC properties + mapping status
POST /api/v1/gsc/sites/map/ # Manually map IGNY8 site to GSC property
POST /api/v1/gsc/sites/auto-map/ # Auto-detect and map
# URL Inspection
GET /api/v1/gsc/urls/ # List tracked URLs with index status
POST /api/v1/gsc/urls/inspect/ # Manual inspect a URL
POST /api/v1/gsc/urls/request-index/ # Manual request indexing
GET /api/v1/gsc/urls/queue/ # Queue status (pending, quota remaining)
# Search Metrics
GET /api/v1/gsc/metrics/ # Search metrics with date range + dimensions
GET /api/v1/gsc/metrics/top-pages/ # Top pages by clicks
GET /api/v1/gsc/metrics/top-queries/ # Top queries
GET /api/v1/gsc/metrics/igny8-only/ # IGNY8-published content metrics only
```
### 6.6 Frontend: GSC Pages
```
frontend/src/pages/
└── SearchConsole/ # NEW page
├── GSCConnect.tsx # OAuth connection flow + welcome screen
├── SiteMapping.tsx # Map IGNY8 sites to GSC properties
├── IndexingDashboard.tsx # URL list, index status, queue status
│ ├── IndexStatusTable.tsx # Filterable URL table
│ ├── QueueStatus.tsx # Quota remaining, items in queue
│ └── ManualInspect.tsx # Inspect any URL manually
├── PerformanceMetrics.tsx # Search analytics dashboard
│ ├── MetricsSummary.tsx # Clicks, impressions, CTR, position cards
│ ├── TopPages.tsx # Top pages table with IGNY8 star markers
│ ├── TopQueries.tsx # Top queries table
│ └── DateRangePicker.tsx # Date range selector
└── components/
└── IndexStatusBadge.tsx # Reusable status badge component
```
**Sidebar addition:**
```
WORKFLOW
├── Planner
├── Writer
├── Automation
├── Blueprint (if SAG active)
├── Linker (if linker_enabled)
├── Campaigns (if campaign_enabled)
├── Search Console (NEW — if gsc_enabled)
└── Optimizer (if optimizer_enabled)
```
**Feature flag:** `gsc_enabled`
### 6.7 Plugin Side Enhancement
```
igny8-plugin/includes/modules/gsc/
├── class-gsc-module.php # Module entry
├── class-gsc-status-display.php # Index status column in WP admin content list
├── class-gsc-metabox.php # Edit screen metabox showing index status
└── views/
└── gsc-metabox.php # Metabox template
```
Plugin receives index status updates from IGNY8 app via:
```
POST /wp-json/igny8/v1/gsc/status-sync
Body: {urls: [{url, index_status, last_inspected, coverage_state}]}
```
---
## 7. Module 5: Rich Schema & SERP Enhancement {#7-rich-schema}
### 7.1 What This Module Delivers
Automated JSON-LD schema injection and on-page SERP elements (TL;DR boxes, TOC, definition blocks, comparison tables, PAA subheadings) into content — both during generation and retroactively for existing pages.
### 7.2 Backend: Schema Service
```
backend/igny8_core/
├── schema/ # NEW (or extend within modules/writer/)
│ ├── __init__.py
│ ├── services/
│ │ ├── schema_generator.py # Core: content → schema JSON-LD
│ │ ├── content_classifier.py # Classify content type for schema mapping
│ │ ├── faq_generator.py # AI: extract/generate FAQ pairs
│ │ ├── howto_extractor.py # AI: detect procedural content → HowTo
│ │ ├── review_analyzer.py # AI: sentiment analysis → Review schema
│ │ ├── proscons_generator.py # AI: generate pros/cons from content
│ │ ├── toc_generator.py # Parse H2/H3 → TOC with jump links
│ │ ├── tldr_generator.py # AI: generate TL;DR summary
│ │ ├── definition_extractor.py # AI: extract key terms → definition blocks
│ │ ├── paa_integrator.py # AI: generate PAA-style subheadings
│ │ └── validator.py # JSON-LD structural validation
│ └── ai_functions/
│ ├── generate_schema_elements.py # Combined AI function for all schema/SERP elements
│ └── retroactive_analyzer.py # AI: analyze existing page → what's missing
```
### 7.3 Backend: Content Type → Schema Mapping
This is the core decision engine. For each content classification, determine which schemas and elements apply:
```python
# schema/services/schema_generator.py
SCHEMA_MAP = {
'blog_article': {
'schemas': ['faq', 'article', 'author_person', 'breadcrumb'],
'elements': ['tldr', 'toc', 'definition_blocks', 'paa_subheadings'],
},
'tutorial_guide': {
'schemas': ['faq', 'howto', 'article', 'author_person', 'breadcrumb'],
'elements': ['tldr', 'toc', 'definition_blocks', 'paa_subheadings'],
},
'product_review': {
'schemas': ['faq', 'review_rating', 'pros_cons', 'article', 'author_person', 'breadcrumb'],
'elements': ['tldr', 'toc', 'paa_subheadings'],
},
'service_page': {
'schemas': ['faq', 'breadcrumb', 'service'],
'elements': ['definition_blocks'],
},
'comparison_post': {
'schemas': ['faq', 'review_rating', 'pros_cons', 'article', 'author_person', 'breadcrumb'],
'elements': ['tldr', 'toc', 'comparison_table', 'paa_subheadings'],
},
'product_page': {
'schemas': ['faq', 'product', 'review_rating', 'breadcrumb'],
'elements': [],
},
}
```
### 7.4 Backend: Pipeline Integration
**Enhance Stage 5 (Content Generation):**
After AI generates content body, a post-processing step generates schema and on-page elements:
```python
# business/content/ — extend content generation flow
def post_process_content(content):
"""After content body is generated, add schema and SERP elements."""
# 1. Classify content type
content_class = content_classifier.classify(content)
# 2. Get applicable schemas and elements from SCHEMA_MAP
applicable = SCHEMA_MAP.get(content_class, {})
# 3. Generate each applicable schema
schemas = {}
if 'faq' in applicable['schemas']:
schemas['faq'] = faq_generator.generate(content)
if 'howto' in applicable['schemas']:
schemas['howto'] = howto_extractor.extract(content)
# ... etc
# 4. Generate on-page elements
elements = {}
if 'tldr' in applicable['elements']:
elements['tldr'] = tldr_generator.generate(content)
if 'toc' in applicable['elements']:
elements['toc'] = toc_generator.generate(content)
# ... etc
# 5. Store on Content model
content.schema_data = schemas # NEW JSON field
content.serp_elements = elements # NEW JSON field
content.save()
```
**New fields on Content model:**
```python
# Add to modules/writer/models.py — Content model:
schema_data = models.JSONField(null=True, blank=True, help_text='Generated JSON-LD schemas')
serp_elements = models.JSONField(null=True, blank=True, help_text='Generated SERP elements (TL;DR, TOC, etc.)')
```
### 7.5 Backend: Retroactive Enhancement Engine
```python
# schema/services/retroactive_engine.py
class RetroactiveEngine:
def scan_site(self, site):
"""Fetch all published pages via plugin, classify, identify missing schemas."""
# 1. GET site inventory from plugin
# 2. For each page: classify content type, check existing schema
# 3. Return: [{url, content_type, missing_schemas, missing_elements}]
pass
def generate_enhancements(self, site, pages):
"""For each page with missing schemas, generate them."""
# AI analyzes page content → generates applicable schemas + elements
# Returns review-ready enhancement set
pass
def push_enhancements(self, site, approved_enhancements):
"""Push approved schemas to WordPress via plugin bulk endpoint."""
# POST /wp-json/igny8/v1/schema/bulk-update
pass
```
### 7.6 Backend: Validation Pipeline
```python
# schema/services/validator.py
class SchemaValidator:
def validate_structural(self, schema_json):
"""Check JSON-LD syntax and schema.org conformance."""
pass
def validate_rich_results(self, url, schema_json):
"""Check against Google Rich Results Test API."""
pass
```
### 7.7 Frontend: Schema Module UI
```
frontend/src/pages/
└── Schema/ # NEW page (or sub-section of Optimizer)
├── SchemaOverview.tsx # Site-wide schema coverage dashboard
│ ├── SchemaCoverage.tsx # % of pages with each schema type
│ ├── MissingSchemaList.tsx # Pages missing applicable schemas
│ └── ValidationStatus.tsx # Schema validation results
├── RetroactiveEnhancer.tsx # Scan existing site, review/approve enhancements
│ ├── SiteScanResults.tsx # Classified pages with enhancement recommendations
│ ├── EnhancementPreview.tsx # Preview schema + elements per page
│ └── BulkApprove.tsx # Approve all / select and approve
└── SchemaSettings.tsx # Per-content-type schema defaults
```
**Sidebar:** Can be a sub-page under Optimizer or a standalone item if `schema_enabled` flag is set.
### 7.8 Plugin Side Enhancement
```
igny8-plugin/includes/modules/schema/ # Already planned in Plugin Build Plan
├── class-schema-module.php
├── class-schema-generator.php # JSON-LD output in <head>
├── class-schema-renderer.php # On-page element renderer (shortcodes/blocks)
```
Plugin stores schemas in post meta (`igny8_schema_faq`, `igny8_schema_howto`, etc.) and renders them in `wp_head` hook.
On-page elements (FAQ section, TOC, TL;DR box) rendered via shortcodes or automatic injection based on content type.
**Bulk update endpoint:**
```
POST /wp-json/igny8/v1/schema/bulk-update
Body: {pages: [{post_id, schemas: {faq: {...}, article: {...}}, elements: {tldr: "...", toc: [...]}}]}
```
---
## 8. Module 6: Socializer {#8-socializer}
### 8.1 What This Module Delivers
Adapts published content into social posts and schedules across 5 platforms: LinkedIn, Twitter/X, Facebook, Instagram, TikTok.
### 8.2 Backend: New Django App
```
backend/igny8_core/
├── socializer/ # NEW Django app
│ ├── __init__.py
│ ├── apps.py
│ ├── models.py # SocialAccount, SocialPost, SocialSchedule
│ ├── serializers.py
│ ├── views.py
│ ├── urls.py # /api/v1/socializer/*
│ ├── admin.py
│ ├── services/
│ │ ├── __init__.py
│ │ ├── oauth_service.py # OAuth2 flows per platform
│ │ ├── content_adapter.py # AI: adapt content for each platform
│ │ ├── image_resizer.py # Resize/crop per platform specs
│ │ ├── publisher.py # Publish to platform APIs
│ │ ├── scheduler.py # Schedule management, best-time slots
│ │ └── metrics_service.py # Fetch engagement metrics
│ ├── platforms/ # Platform-specific API clients
│ │ ├── __init__.py
│ │ ├── linkedin.py
│ │ ├── twitter.py
│ │ ├── facebook.py
│ │ ├── instagram.py
│ │ └── tiktok.py
│ ├── ai_functions/
│ │ ├── adapt_for_social.py # AI: content → platform-specific post
│ │ └── generate_hashtags.py # AI: generate relevant hashtags
│ ├── tasks.py # Celery tasks for scheduled posting + metrics
│ └── migrations/
```
### 8.3 Backend: Models
```python
# socializer/models.py
class SocialAccount(AccountBaseModel):
"""Connected social media account/page."""
platform = models.CharField(max_length=20, choices=[
('linkedin', 'LinkedIn'), ('twitter', 'Twitter/X'),
('facebook', 'Facebook'), ('instagram', 'Instagram'),
('tiktok', 'TikTok'),
])
account_name = models.CharField(max_length=200)
account_id = models.CharField(max_length=200)
access_token = models.TextField()
refresh_token = models.TextField(blank=True)
token_expiry = models.DateTimeField(null=True, blank=True)
page_id = models.CharField(max_length=200, blank=True, help_text='For Facebook Pages, LinkedIn Company Pages')
is_active = models.BooleanField(default=True)
connected_at = models.DateTimeField(auto_now_add=True)
class SocialPost(SiteSectorBaseModel):
"""A social post generated from IGNY8 content."""
source_content = models.ForeignKey('writer.Content', on_delete=models.CASCADE, related_name='social_posts')
platform = models.CharField(max_length=20)
social_account = models.ForeignKey(SocialAccount, on_delete=models.CASCADE)
post_type = models.CharField(max_length=30, choices=[
('announcement', 'Announcement'),
('highlight', 'Key Highlights'),
('quote_card', 'Quote Card'),
('faq_snippet', 'FAQ Snippet'),
('thread', 'Thread (Twitter)'),
])
text_content = models.TextField()
hashtags = models.JSONField(default=list)
image_url = models.URLField(blank=True)
link_url = models.URLField(blank=True)
# Scheduling
status = models.CharField(max_length=20, choices=[
('draft', 'Draft'), ('scheduled', 'Scheduled'),
('published', 'Published'), ('failed', 'Failed'),
], default='draft')
scheduled_at = models.DateTimeField(null=True, blank=True)
published_at = models.DateTimeField(null=True, blank=True)
platform_post_id = models.CharField(max_length=200, blank=True)
# Metrics
clicks = models.IntegerField(default=0)
likes = models.IntegerField(default=0)
shares = models.IntegerField(default=0)
comments = models.IntegerField(default=0)
impressions = models.IntegerField(default=0)
metrics_updated_at = models.DateTimeField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
```
### 8.4 Backend: Automation Pipeline Stage 8
```python
# business/automation/stages/stage_8_socializer.py # NEW
# After content is published to WordPress (Stage 7 + publish):
# 1. Check if socializer_enabled for this site
# 2. Load connected social accounts
# 3. For each active platform:
# a. AI adapts content for platform (tone, length, format)
# b. Resize image for platform specs
# c. Generate hashtags
# d. Create SocialPost (status=scheduled)
# e. Queue for scheduled publishing
```
Add to `AutomationConfig` choices:
```python
# Stage 8: Socializer (if socializer_enabled)
```
### 8.5 Backend: Celery Tasks
```python
# socializer/tasks.py
@shared_task
def publish_scheduled_posts():
"""Every 5 min: check for posts due for publishing, publish them."""
pass
@shared_task
def fetch_engagement_metrics():
"""Every 6 hours: fetch metrics for recently published posts."""
pass
@shared_task
def refresh_social_tokens():
"""Daily: refresh OAuth tokens approaching expiry."""
pass
```
### 8.6 Frontend: Socializer Pages
```
frontend/src/pages/
└── Socializer/ # NEW page
├── SocialAccounts.tsx # Connected accounts management
│ ├── ConnectAccount.tsx # OAuth connect flow per platform
│ └── AccountList.tsx # List connected accounts with status
├── SocialPosts.tsx # All social posts with status
│ ├── PostList.tsx # Filterable by platform, status, date
│ ├── PostPreview.tsx # Platform-specific preview card
│ └── PostEditor.tsx # Edit text/image before scheduling
├── SocialCalendar.tsx # Calendar view of scheduled posts
└── SocialAnalytics.tsx # Engagement metrics per platform/post
```
**Sidebar addition:**
```
WORKFLOW
├── ...
├── Socializer (NEW — if socializer_enabled)
└── ...
```
**Feature flag:** `socializer_enabled`
---
## 9. Module 7: Video Creator {#9-video-creator}
### 9.1 What This Module Delivers
Converts published articles into video content and publishes to YouTube, Instagram Reels, TikTok, YouTube Shorts.
### 9.2 Backend: New Django App
```
backend/igny8_core/
├── video/ # NEW Django app
│ ├── __init__.py
│ ├── apps.py
│ ├── models.py # VideoProject, VideoScript, VideoAsset, VideoRender
│ ├── serializers.py
│ ├── views.py
│ ├── urls.py # /api/v1/video/*
│ ├── admin.py
│ ├── services/
│ │ ├── __init__.py
│ │ ├── script_service.py # AI script generation from content
│ │ ├── tts_service.py # Text-to-speech (OpenAI, ElevenLabs, self-hosted)
│ │ ├── asset_service.py # Stock footage/image fetching (Pexels, Pixabay)
│ │ ├── composer_service.py # FFmpeg + MoviePy video assembly
│ │ ├── subtitle_service.py # SRT caption generation
│ │ ├── thumbnail_service.py # AI thumbnail generation
│ │ ├── seo_service.py # Video titles, descriptions, tags per platform
│ │ └── publisher_service.py # Publish to YouTube, Instagram, TikTok
│ ├── platforms/
│ │ ├── youtube.py # YouTube Data API v3
│ │ ├── instagram.py # Instagram Graph API (Reels)
│ │ └── tiktok.py # TikTok Content Posting API
│ ├── ai_functions/
│ │ ├── generate_script.py # AI: content → VideoScript
│ │ ├── generate_video_seo.py # AI: script → platform-specific SEO
│ │ └── generate_thumbnail.py # AI: content → thumbnail image
│ ├── tasks.py # Celery tasks (separate queue for rendering)
│ └── migrations/
```
### 9.3 Backend: Models
```python
# video/models.py
class VideoProject(SiteSectorBaseModel):
"""A video project generated from IGNY8 content."""
source_content = models.ForeignKey('writer.Content', on_delete=models.CASCADE, related_name='video_projects')
video_type = models.CharField(max_length=20, choices=[
('short', 'Short Form (30-90s)'),
('medium', 'Medium (60-180s)'),
('long', 'Long Form (5-15 min)'),
])
status = models.CharField(max_length=20, choices=[
('script_draft', 'Script Draft'),
('script_approved', 'Script Approved'),
('rendering', 'Rendering'),
('rendered', 'Rendered'),
('published', 'Published'),
('failed', 'Failed'),
], default='script_draft')
target_platforms = models.JSONField(default=list, help_text='["youtube", "instagram", "tiktok"]')
render_preset = models.CharField(max_length=30, choices=[
('youtube_long', '1920×1080 3-15min'),
('youtube_short', '1080×1920 30-60s'),
('instagram_reel', '1080×1920 30-90s'),
('tiktok', '1080×1920 30-180s'),
])
created_at = models.DateTimeField(auto_now_add=True)
class VideoScript(models.Model):
"""AI-generated narration script for a video project."""
project = models.OneToOneField(VideoProject, on_delete=models.CASCADE, related_name='script')
sections = models.JSONField(help_text='[{type: "hook"|"intro"|"point"|"cta", text, visual_cue, duration_seconds}]')
total_duration_seconds = models.IntegerField(default=0)
voice_id = models.CharField(max_length=100, blank=True)
voice_provider = models.CharField(max_length=30, blank=True)
seo_title = models.JSONField(default=dict, help_text='{youtube: "...", instagram: "...", tiktok: "..."}')
seo_description = models.JSONField(default=dict)
seo_tags = models.JSONField(default=list)
chapter_markers = models.JSONField(default=list, help_text='For YouTube chapters')
created_at = models.DateTimeField(auto_now_add=True)
class VideoRender(models.Model):
"""A rendered video file for a specific platform."""
project = models.ForeignKey(VideoProject, on_delete=models.CASCADE, related_name='renders')
platform = models.CharField(max_length=20)
file_url = models.URLField(blank=True, help_text='S3/storage URL')
file_size_bytes = models.BigIntegerField(default=0)
duration_seconds = models.IntegerField(default=0)
resolution = models.CharField(max_length=20)
thumbnail_url = models.URLField(blank=True)
subtitle_url = models.URLField(blank=True, help_text='SRT file URL')
status = models.CharField(max_length=20, choices=[
('queued', 'Queued'), ('rendering', 'Rendering'),
('complete', 'Complete'), ('failed', 'Failed'),
], default='queued')
platform_video_id = models.CharField(max_length=200, blank=True)
published_at = models.DateTimeField(null=True, blank=True)
render_started_at = models.DateTimeField(null=True, blank=True)
render_completed_at = models.DateTimeField(null=True, blank=True)
```
### 9.4 Backend: Celery Tasks (Separate Queue)
Video rendering is CPU/memory intensive — use a separate Celery queue.
```python
# video/tasks.py
@shared_task(queue='video_render')
def render_video(project_id, platform):
"""Heavy task: assemble and render video. Runs on dedicated worker."""
# 1. Load script + assets
# 2. TTS: generate voiceover audio
# 3. Fetch stock footage/images for visual cues
# 4. Compose video with FFmpeg/MoviePy
# 5. Add subtitles
# 6. Upload to S3/storage
# 7. Update VideoRender record
pass
@shared_task
def publish_video(render_id):
"""Publish rendered video to platform."""
pass
@shared_task
def generate_video_thumbnail(project_id):
"""AI-generate thumbnail from content."""
pass
```
**Celery config addition:**
```python
# celery.py — add video_render queue
CELERY_TASK_ROUTES = {
'igny8_core.video.tasks.render_video': {'queue': 'video_render'},
}
```
### 9.5 Backend: Automation Pipeline Stage 9
```python
# business/automation/stages/stage_9_video.py # NEW
# After socializer (Stage 8) or after publish:
# 1. Check if video_enabled for this site
# 2. If auto-video enabled: generate script → queue for rendering
# 3. If manual: create project in script_draft status for user review
```
### 9.6 Frontend: Video Creator Pages
```
frontend/src/pages/
└── VideoCreator/ # NEW page
├── VideoProjects.tsx # List all video projects with status
├── ScriptEditor.tsx # View/edit AI-generated script
│ ├── ScriptSections.tsx # Section-by-section editor
│ ├── VoiceSelector.tsx # Choose TTS voice + preview
│ └── VisualCueEditor.tsx # Edit visual cues per section
├── VideoPreview.tsx # Preview rendered video
├── VideoPublisher.tsx # Select platforms + publish
└── VideoAnalytics.tsx # View/engagement metrics per video
```
**Sidebar addition:**
```
WORKFLOW
├── ...
├── Socializer (if socializer_enabled)
├── Video Creator (NEW — if video_enabled)
└── ...
```
**Feature flag:** `video_enabled`
---
## 10. Updated Automation Pipeline — All Stages {#10-updated-automation-pipeline}
After all modules are implemented, the full pipeline becomes:
```
Stage 0: Blueprint Check (if SAG active — from Doc A)
Stage 1: Process New Keywords
Stage 2: AI Cluster Keywords (or SAG cluster mapping)
Stage 3: Generate Content Ideas (type-aware, blueprint-guided)
Stage 4: Create Writer Tasks (with content_type + content_structure)
Stage 5: Generate Article Content (type-specific prompts + schema/SERP post-processing)
Stage 6: Extract Image Prompts
Stage 7: Generate Images → Review Queue
--- After publish to WordPress ---
Stage 7.5: Auto-Index via GSC (if gsc_enabled)
Stage 8: Linker — Generate SAG links (if linker_enabled — from Doc A)
Stage 9: Socializer — Generate social posts (if socializer_enabled)
Stage 10: Video Creator — Generate video project (if video_enabled)
```
Each stage beyond 7 is independently enabled/disabled. The pipeline gracefully skips disabled stages.
**AutomationConfig** model extends to include stage enable/disable per site:
```python
# Add to AutomationConfig or AutomationSettings:
gsc_auto_index = models.BooleanField(default=True)
auto_generate_links = models.BooleanField(default=True)
auto_generate_social = models.BooleanField(default=False)
auto_generate_video = models.BooleanField(default=False)
```
---
## 11. Updated Navigation & Sidebar {#11-updated-navigation}
After all modules implemented:
```
Dashboard (with GSC indexing widget, social metrics widget, video status widget)
SETUP
├── Add Keywords (optional when SAG active)
├── Content Settings
├── Sites
└── Thinker (admin only)
WORKFLOW
├── Planner
│ ├── Keywords
│ ├── Clusters
│ ├── Ideas
│ └── Taxonomies (if taxonomy sync active — Module 2)
├── Writer (Queue → Drafts → Images → Review → Published, all content types)
├── Automation (Stages 1-10 visualization, per-stage toggle)
├── Blueprint (if SAG active — from Doc A)
├── Linker (if linker_enabled — from Doc A)
├── Campaigns (if campaign_enabled — from Doc A)
├── Search Console (if gsc_enabled — Module 4)
├── Optimizer (if optimizer_enabled — Module 3)
├── Schema (if schema_enabled — Module 5, or nested under Optimizer)
├── Socializer (if socializer_enabled — Module 6)
└── Video Creator (if video_enabled — Module 7)
ACCOUNT
├── Account Settings
├── Plans & Billing
├── Usage
└── AI Models (admin only)
ADMIN (admin only)
└── Sector Templates
HELP
└── Help & Docs
```
---
## 12. Complete API Endpoint Registry {#12-api-endpoints}
### Content Types Writing (Module 1 — no new endpoints, enhances existing)
```
Existing writer/tasks/ and writer/content/ endpoints — now accept content_type and content_structure fields
```
### Taxonomy & Term Content (Module 2)
```
GET /api/v1/planner/taxonomies/ # List synced taxonomies
POST /api/v1/planner/taxonomies/sync/ # Trigger taxonomy sync from WordPress
GET /api/v1/planner/taxonomies/{id}/terms/ # List terms within taxonomy
POST /api/v1/planner/taxonomies/terms/{id}/map/ # Map term to cluster
POST /api/v1/planner/taxonomies/terms/{id}/generate/ # Generate content for term
POST /api/v1/planner/taxonomies/bulk-generate/ # Batch generate term content
```
### Optimizer (Module 3)
```
POST /api/v1/optimizer/analyze/ # Analyze content
POST /api/v1/optimizer/optimize/ # Generate optimized version
POST /api/v1/optimizer/apply/{job_id}/ # Apply optimization
POST /api/v1/optimizer/reject/{job_id}/ # Reject optimization
POST /api/v1/optimizer/batch/ # Batch optimize
GET /api/v1/optimizer/jobs/ # List optimization jobs
GET /api/v1/optimizer/settings/ # Module settings
PUT /api/v1/optimizer/settings/ # Update settings
```
### GSC Integration (Module 4)
```
POST /api/v1/gsc/connect/ # OAuth initiate
GET /api/v1/gsc/callback/ # OAuth callback
DELETE /api/v1/gsc/disconnect/ # Revoke
GET /api/v1/gsc/status/ # Connection status
GET /api/v1/gsc/sites/ # GSC properties
POST /api/v1/gsc/sites/map/ # Manual mapping
POST /api/v1/gsc/sites/auto-map/ # Auto-detect
GET /api/v1/gsc/urls/ # Tracked URLs
POST /api/v1/gsc/urls/inspect/ # Manual inspect
POST /api/v1/gsc/urls/request-index/ # Manual index request
GET /api/v1/gsc/urls/queue/ # Queue status
GET /api/v1/gsc/metrics/ # Search metrics
GET /api/v1/gsc/metrics/top-pages/ # Top pages
GET /api/v1/gsc/metrics/top-queries/ # Top queries
GET /api/v1/gsc/metrics/igny8-only/ # IGNY8 content only
```
### Rich Schema (Module 5)
```
GET /api/v1/schema/coverage/ # Site-wide schema coverage stats
POST /api/v1/schema/generate/{content_id}/ # Generate schema for content
POST /api/v1/schema/scan-site/ # Retroactive: scan site
POST /api/v1/schema/generate-bulk/ # Retroactive: generate for multiple pages
POST /api/v1/schema/push-bulk/ # Push approved schemas to WordPress
POST /api/v1/schema/validate/{content_id}/ # Validate schema
GET /api/v1/schema/settings/ # Schema settings
PUT /api/v1/schema/settings/ # Update settings
```
### Socializer (Module 6)
```
GET /api/v1/socializer/accounts/ # List connected accounts
POST /api/v1/socializer/accounts/connect/{platform}/ # OAuth initiate
DELETE /api/v1/socializer/accounts/{id}/ # Disconnect
GET /api/v1/socializer/posts/ # List social posts
POST /api/v1/socializer/posts/generate/ # Generate posts from content
PATCH /api/v1/socializer/posts/{id}/ # Edit post text/schedule
POST /api/v1/socializer/posts/{id}/publish/ # Publish now
DELETE /api/v1/socializer/posts/{id}/ # Delete draft
GET /api/v1/socializer/calendar/ # Calendar view data
GET /api/v1/socializer/analytics/ # Engagement metrics
GET /api/v1/socializer/settings/ # Scheduling rules, defaults
PUT /api/v1/socializer/settings/ # Update settings
```
### Video Creator (Module 7)
```
GET /api/v1/video/projects/ # List video projects
POST /api/v1/video/projects/create/ # Create project from content
GET /api/v1/video/projects/{id}/ # Project detail
PATCH /api/v1/video/projects/{id}/script/ # Edit script
POST /api/v1/video/projects/{id}/approve-script/ # Approve script, start render
POST /api/v1/video/projects/{id}/render/ # Queue rendering
GET /api/v1/video/projects/{id}/renders/ # List renders per platform
POST /api/v1/video/projects/{id}/publish/ # Publish to platforms
GET /api/v1/video/analytics/ # Video metrics
GET /api/v1/video/voices/ # Available TTS voices
```
---
## 13. Complete AI Function Registry {#13-ai-functions}
| Function Key | Module | Location | Input | Output |
|-------------|--------|----------|-------|--------|
| `generate_content_product` | 1 | `ai/functions/generate_content.py` (extend) | Task + product context | Product page HTML |
| `generate_content_service` | 1 | same | Task + service context | Service page HTML |
| `generate_content_taxonomy` | 1 | same | Task + term context | Term landing HTML |
| `generate_content_hub` | 1 | same | Task + cluster context | Hub page HTML |
| `optimize_content` | 3 | `ai/functions/optimize_content.py` (implement) | Content + cluster | Optimized content + schema |
| `generate_faq_pairs` | 5 | `schema/ai_functions/` | Content body | FAQ Q&A pairs |
| `extract_howto_steps` | 5 | `schema/ai_functions/` | Content body | HowTo steps |
| `generate_pros_cons` | 5 | `schema/ai_functions/` | Content body | Pros and cons lists |
| `generate_tldr` | 5 | `schema/ai_functions/` | Content body | TL;DR summary |
| `adapt_for_social` | 6 | `socializer/ai_functions/adapt_for_social.py` | Content + platform | Platform-adapted text |
| `generate_hashtags` | 6 | `socializer/ai_functions/generate_hashtags.py` | Content + platform | Hashtag list |
| `generate_video_script` | 7 | `video/ai_functions/generate_script.py` | Content + video_type | VideoScript sections |
| `generate_video_seo` | 7 | `video/ai_functions/generate_video_seo.py` | Script + platform | SEO title/desc/tags |
| `generate_thumbnail` | 7 | `video/ai_functions/generate_thumbnail.py` | Content | Thumbnail image prompt |
---
## 14. Complete Celery Task Registry {#14-celery-tasks}
| Task | Module | Schedule | Queue |
|------|--------|----------|-------|
| `process_indexing_queue` | GSC | Every 5 min | default |
| `fetch_search_metrics` | GSC | Daily | default |
| `auto_index_published_content` | GSC | On demand (after publish) | default |
| `sync_index_status_to_plugin` | GSC | Every 5 min | default |
| `refresh_gsc_token` | GSC | Daily | default |
| `publish_scheduled_posts` | Socializer | Every 5 min | default |
| `fetch_engagement_metrics` | Socializer | Every 6 hours | default |
| `refresh_social_tokens` | Socializer | Daily | default |
| `render_video` | Video | On demand | video_render (separate) |
| `publish_video` | Video | On demand | default |
| `generate_video_thumbnail` | Video | On demand | default |
---
## 15. Feature Flag Registry {#15-feature-flags}
| Flag | Module | Controls | Default |
|------|--------|---------|---------|
| `optimizer_enabled` | Optimizer | Optimizer page, optimization API, automation integration | `False` (exists) |
| `gsc_enabled` | GSC | Search Console page, OAuth, auto-indexing | `False` |
| `schema_enabled` | Rich Schema | Schema generation in pipeline, retroactive engine | `False` |
| `socializer_enabled` | Socializer | Socializer page, OAuth, social posting, Stage 9 | `False` |
| `video_enabled` | Video Creator | Video Creator page, rendering, Stage 10 | `False` |
Content Types Writing and Taxonomy & Term Content have **no feature flags** — they extend existing pipeline capabilities and are always available once deployed.
---
## 16. Credit Cost Summary {#16-credit-costs}
| Operation | Module | Credits |
|-----------|--------|---------|
| Generate product/service/hub content | Content Types | Same as articles (5 per 100 words) |
| Generate taxonomy landing content | Taxonomy | Same as articles |
| Analyze content for optimization | Optimizer | 2 |
| Optimize content (rewrite) | Optimizer | 5 per 100 words |
| Generate schema elements | Rich Schema | 2 per page |
| Retroactive scan + generate | Rich Schema | 1 per page scanned + 2 per page enhanced |
| Adapt content for 1 platform | Socializer | 1 |
| Generate hashtags | Socializer | 0.5 |
| Generate Twitter thread | Socializer | 2 |
| Generate social image | Socializer | 3-10 |
| Full social suite (5 platforms) | Socializer | 15-25 per content item |
| Generate video script | Video | 5 |
| TTS voiceover | Video | 10/min (standard), 20/min (HD), 2/min (self-hosted) |
| Visual assets per video | Video | 15-50 |
| Thumbnail generation | Video | 3-10 |
| Video composition (render) | Video | 5 per render |
| Video SEO metadata | Video | 1 per platform |
| Full short-form video | Video | ~40-80 total |
| Full long-form video | Video | ~100-250 total |
---
## 17. Cross-Module Dependencies {#17-cross-dependencies}
```
Content Types Writing (Module 1)
└── feeds → Taxonomy & Term Content (content structures for term pages)
└── feeds → Optimizer (supports all content types)
└── feeds → Rich Schema (content type classification drives schema mapping)
└── feeds → Socializer (any content type can be socialized)
└── feeds → Video Creator (any content type can become a video)
Taxonomy & Term Content (Module 2)
└── feeds → Optimizer (term pages can be optimized)
└── feeds → Rich Schema (term pages get schema)
└── depends on → Content Types Writing (Module 1)
└── depends on → SAG Blueprint (Doc A) for cluster mapping
Optimizer (Module 3)
└── feeds → Rich Schema (schema generation is part of optimization)
└── depends on → Content Types Writing (Module 1)
└── depends on → SAG clusters (Doc A) for cluster matching
GSC Integration (Module 4)
└── feeds → SAG Backlink Campaigns (Doc A Phase 10) for KPI data
└── feeds → Blueprint Health (Doc A Phase 8) for indexed page tracking
└── INDEPENDENT — no dependencies on other modules
Rich Schema (Module 5)
└── feeds → WordPress plugin (schema storage + rendering)
└── depends on → Content Types Writing (Module 1) for type classification
└── benefits from → GSC (Module 4) for schema error monitoring
Socializer (Module 6)
└── depends on → Published content (any module)
└── shares OAuth patterns with → Video Creator (Module 7)
Video Creator (Module 7)
└── depends on → Published content (any module)
└── depends on → Socializer (Module 6) for shared infrastructure
└── requires → S3/media storage, FFmpeg, separate Celery queue
```
---
## Reference Documents
| Document | Purpose |
|----------|---------|
| **IGNY8-Consolidated-Module-Plans.md** | Strategic plans for all modules — source for this guide |
| **IGNY8-Rich-Schema-SERP-Enhancement-Module.docx** | Detailed schema types, mapping matrix, rollout plan |
| **IGNY8-Current-State.md** | Current platform state — all file paths, models, modules |
| **Doc A — SAG Architecture Dev Guide** | SAG models, blueprint, clusters — consumed by Modules 2, 3, 5 |
---
*End of Doc B — IGNY8 Platform Modules Development Guide*