1701 lines
69 KiB
Markdown
1701 lines
69 KiB
Markdown
# 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*
|