# 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 ├── 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*