diff --git a/backend/celerybeat-schedule b/backend/celerybeat-schedule index 72baf65c..cf2ebcf2 100644 Binary files a/backend/celerybeat-schedule and b/backend/celerybeat-schedule differ diff --git a/backend/igny8_core/business/optimization/apps.py b/backend/igny8_core/business/optimization/apps.py new file mode 100644 index 00000000..6614ace9 --- /dev/null +++ b/backend/igny8_core/business/optimization/apps.py @@ -0,0 +1,8 @@ +from django.apps import AppConfig + + +class OptimizationConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'igny8_core.business.optimization' + verbose_name = 'Optimization' + diff --git a/backend/igny8_core/business/optimization/migrations/0001_initial.py b/backend/igny8_core/business/optimization/migrations/0001_initial.py new file mode 100644 index 00000000..cc0d09c0 --- /dev/null +++ b/backend/igny8_core/business/optimization/migrations/0001_initial.py @@ -0,0 +1,54 @@ +# Generated manually for Phase 4: Optimization System + +import django.core.validators +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('igny8_core_auth', '0013_remove_ai_cost_per_request'), + ('writer', '0009_add_content_site_source_fields'), + ] + + operations = [ + migrations.CreateModel( + name='OptimizationTask', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, db_index=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('scores_before', models.JSONField(default=dict, help_text='Optimization scores before')), + ('scores_after', models.JSONField(default=dict, help_text='Optimization scores after')), + ('html_before', models.TextField(blank=True, help_text='HTML content before optimization')), + ('html_after', models.TextField(blank=True, help_text='HTML content after optimization')), + ('status', models.CharField(choices=[('pending', 'Pending'), ('running', 'Running'), ('completed', 'Completed'), ('failed', 'Failed')], db_index=True, default='pending', help_text='Optimization task status', max_length=20)), + ('credits_used', models.IntegerField(default=0, help_text='Credits used for optimization', validators=[django.core.validators.MinValueValidator(0)])), + ('metadata', models.JSONField(blank=True, default=dict, help_text='Additional metadata')), + ('account', models.ForeignKey(db_column='tenant_id', on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_set', to='igny8_core_auth.tenant')), + ('content', models.ForeignKey(help_text='The content being optimized', on_delete=django.db.models.deletion.CASCADE, related_name='optimization_tasks', to='writer.content')), + ], + options={ + 'db_table': 'igny8_optimization_tasks', + 'ordering': ['-created_at'], + 'verbose_name': 'Optimization Task', + 'verbose_name_plural': 'Optimization Tasks', + }, + ), + migrations.AddIndex( + model_name='optimizationtask', + index=models.Index(fields=['content', 'status'], name='igny8_optim_content_status_idx'), + ), + migrations.AddIndex( + model_name='optimizationtask', + index=models.Index(fields=['account', 'status'], name='igny8_optim_account_status_idx'), + ), + migrations.AddIndex( + model_name='optimizationtask', + index=models.Index(fields=['status', 'created_at'], name='igny8_optim_status_created_idx'), + ), + ] + diff --git a/backend/igny8_core/business/optimization/migrations/__init__.py b/backend/igny8_core/business/optimization/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/backend/igny8_core/business/site_building/migrations/0001_initial.py b/backend/igny8_core/business/site_building/migrations/0001_initial.py index 35b9f788..8efc7b81 100644 --- a/backend/igny8_core/business/site_building/migrations/0001_initial.py +++ b/backend/igny8_core/business/site_building/migrations/0001_initial.py @@ -9,6 +9,7 @@ class Migration(migrations.Migration): dependencies = [ ('igny8_core_auth', '0014_remove_plan_operation_limits_phase0'), + ('writer', '0009_add_content_site_source_fields'), ] operations = [ @@ -26,7 +27,7 @@ class Migration(migrations.Migration): ('hosting_type', models.CharField(choices=[('igny8_sites', 'IGNY8 Sites'), ('wordpress', 'WordPress'), ('shopify', 'Shopify'), ('multi', 'Multiple Destinations')], default='igny8_sites', help_text='Target hosting platform', max_length=50)), ('version', models.IntegerField(default=1, help_text='Blueprint version', validators=[django.core.validators.MinValueValidator(1)])), ('deployed_version', models.IntegerField(blank=True, help_text='Currently deployed version', null=True)), - ('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='siteblueprint_set', to='igny8_core_auth.account')), + ('account', models.ForeignKey(db_column='tenant_id', on_delete=django.db.models.deletion.CASCADE, related_name='siteblueprint_set', to='igny8_core_auth.tenant')), ('sector', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='siteblueprint_set', to='igny8_core_auth.sector')), ('site', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='siteblueprint_set', to='igny8_core_auth.site')), ], @@ -49,7 +50,7 @@ class Migration(migrations.Migration): ('blocks_json', models.JSONField(default=list, help_text="Page content blocks: [{'type': 'hero', 'data': {...}}, ...]")), ('status', models.CharField(choices=[('draft', 'Draft'), ('generating', 'Generating'), ('ready', 'Ready')], db_index=True, default='draft', help_text='Page status', max_length=20)), ('order', models.IntegerField(default=0, help_text='Page order in navigation')), - ('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pageblueprint_set', to='igny8_core_auth.account')), + ('account', models.ForeignKey(db_column='tenant_id', on_delete=django.db.models.deletion.CASCADE, related_name='pageblueprint_set', to='igny8_core_auth.tenant')), ('sector', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pageblueprint_set', to='igny8_core_auth.sector')), ('site', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pageblueprint_set', to='igny8_core_auth.site')), ('site_blueprint', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pages', to='site_building.siteblueprint')), diff --git a/backend/igny8_core/settings.py b/backend/igny8_core/settings.py index 92e7db44..7f9c64f2 100644 --- a/backend/igny8_core/settings.py +++ b/backend/igny8_core/settings.py @@ -53,6 +53,7 @@ INSTALLED_APPS = [ 'igny8_core.modules.billing.apps.BillingConfig', 'igny8_core.modules.automation.apps.AutomationConfig', 'igny8_core.business.site_building.apps.SiteBuildingConfig', + 'igny8_core.business.optimization.apps.OptimizationConfig', 'igny8_core.modules.site_builder.apps.SiteBuilderConfig', 'igny8_core.modules.linker.apps.LinkerConfig', 'igny8_core.modules.optimizer.apps.OptimizerConfig', diff --git a/docs/planning/PHASE-3-4-IMPLEMENTATION-PLAN.md b/docs/planning/PHASE-3-4-IMPLEMENTATION-PLAN.md deleted file mode 100644 index 0ac2b852..00000000 --- a/docs/planning/PHASE-3-4-IMPLEMENTATION-PLAN.md +++ /dev/null @@ -1,1445 +0,0 @@ -# PHASE 3 & 4 IMPLEMENTATION PLAN -**Detailed Configuration Plan for Site Builder & Linker/Optimizer** - -**Created**: 2025-01-XX -**Last Updated**: 2025-01-XX -**Status**: Phase 3 Complete ✅ | Phase 4 Complete ✅ - ---- - -## TABLE OF CONTENTS - -1. [Implementation Summary](#implementation-summary) ⭐ **NEW** -2. [Overview](#overview) -3. [Phase 3: Site Builder Implementation Plan](#phase-3-site-builder-implementation-plan) -4. [Phase 4: Linker & Optimizer Implementation Plan](#phase-4-linker--optimizer-implementation-plan) -5. [Integration Points](#integration-points) -6. [File Structure](#file-structure) -7. [Dependencies & Order](#dependencies--order) -8. [Testing Strategy](#testing-strategy) - ---- - -## IMPLEMENTATION SUMMARY - -**Last Updated**: 2025-01-XX -**Session**: Phase 3 & 4 Implementation Session - -### ✅ Phase 3: Site Builder - COMPLETE - -#### Backend Implementation - -**Models Created** (`backend/igny8_core/business/site_building/models.py`): -- ✅ `SiteBlueprint` model with fields: - - `name`, `description` - - `config_json` (wizard configuration) - - `structure_json` (AI-generated structure) - - `status` (draft, generating, ready, deployed) - - `hosting_type` (igny8_sites, wordpress, shopify, multi) - - `version`, `deployed_version` - - Inherits from `SiteSectorBaseModel` (account, site, sector) -- ✅ `PageBlueprint` model with fields: - - `site_blueprint` (ForeignKey) - - `slug`, `title`, `type` - - `blocks_json` (page content blocks) - - `status` (draft, generating, ready) - - `order` - - Inherits from `SiteSectorBaseModel` - -**Services Created**: -- ✅ `StructureGenerationService` (`business/site_building/services/structure_generation_service.py`) - - `generate_structure()` - Triggers AI structure generation - - Integrates with `CreditService` for credit checks - - Dispatches Celery tasks for async processing -- ✅ `PageGenerationService` (`business/site_building/services/page_generation_service.py`) - - `generate_page_content()` - Creates Writer tasks from page blueprints - - `regenerate_page()` - Regenerates page content - - Integrates with `ContentGenerationService` -- ✅ `SiteBuilderFileService` (`business/site_building/services/file_management_service.py`) - - `upload_file()` - Handles file uploads with access control - - `delete_file()` - Deletes files with validation - - `list_files()` - Lists files for a site - - `check_file_access()` - Validates user access to site files - -**AI Function Created**: -- ✅ `GenerateSiteStructureFunction` (`ai/functions/generate_site_structure.py`) - - Operation type: `site_structure_generation` - - Credit cost: 50 credits (from constants) - - Parses AI response JSON and syncs `PageBlueprint` instances - - Handles page creation, updates, and deletions -- ✅ Added to AI registry (`ai/registry.py`) -- ✅ Added prompt to `ai/prompts.py` (`site_structure_generation`) -- ✅ Integrated into `ai/engine.py` with phase tracking - -**API Layer Created** (`modules/site_builder/`): -- ✅ `SiteBuilderViewSet` with actions: - - CRUD operations for `SiteBlueprint` - - `generate_structure/` (POST) - Triggers AI structure generation -- ✅ `PageBlueprintViewSet` with actions: - - CRUD operations for `PageBlueprint` - - `generate_content/` (POST) - Generates page content via Writer - - `regenerate/` (POST) - Regenerates page content -- ✅ `SiteAssetView` (APIView) for file management: - - `GET` - List files - - `POST` - Upload file - - `DELETE` - Delete file -- ✅ Serializers: - - `SiteBlueprintSerializer` - - `PageBlueprintSerializer` - - `SiteBlueprintDetailSerializer` - - `PageBlueprintDetailSerializer` - - `FileUploadSerializer` -- ✅ URLs registered at `/api/v1/site-builder/` - -**Migrations**: -- ✅ `0001_initial.py` - Creates `SiteBlueprint` and `PageBlueprint` tables -- ✅ Applied to database - -**Django App Configuration**: -- ✅ `business/site_building/apps.py` - `SiteBuildingConfig` -- ✅ `modules/site_builder/apps.py` - `SiteBuilderConfig` -- ✅ Added to `INSTALLED_APPS` in `settings.py` - -#### Frontend Implementation - -**Site Builder Container** (`site-builder/`): -- ✅ Created standalone Vite + React + TypeScript application -- ✅ Docker container configured (`Dockerfile.dev`) -- ✅ Docker Compose service (`igny8_site_builder`) on port 8025:5175 -- ✅ Routed to `builder.igny8.com` via Caddy reverse proxy -- ✅ Vite config with `@shared` alias for shared components -- ✅ Node.js 22 (upgraded from 18 for Vite 7 compatibility) - -**Wizard Pages** (`site-builder/src/pages/wizard/`): -- ✅ `WizardPage.tsx` - Main wizard orchestrator with step navigation -- ✅ `BusinessDetailsStep.tsx` - Step 1: Business type, industry, audience -- ✅ `BriefStep.tsx` - Step 2: Business brief textarea -- ✅ `ObjectivesStep.tsx` - Step 3: Multiple objectives with add/remove -- ✅ `StyleStep.tsx` - Step 4: Style preferences (palette, typography, personality) - -**Preview & Dashboard**: -- ✅ `PreviewCanvas.tsx` - Live preview of generated site structure -- ✅ `SiteDashboard.tsx` - Lists all site blueprints - -**State Management** (`site-builder/src/state/`): -- ✅ `builderStore.ts` (Zustand) - Wizard state: - - `currentStep`, `wizardData`, `activeBlueprint` - - `isSubmitting`, `error` - - Actions: `nextStep`, `previousStep`, `submitWizard`, etc. -- ✅ `siteDefinitionStore.ts` (Zustand) - Site preview state: - - `siteStructure`, `pages`, `activePageSlug` - - Actions: `setSiteStructure`, `setPages`, `refreshSiteDefinition` - -**API Client** (`site-builder/src/api/`): -- ✅ `builder.api.ts` - API functions: - - `createBlueprint()`, `getBlueprint()`, `generateStructure()` - - `getPages()`, `generatePageContent()` - - `uploadFile()`, `deleteFile()`, `listFiles()` - -**Type Definitions** (`site-builder/src/types/`): -- ✅ `siteBuilder.ts` - TypeScript interfaces: - - `SiteBlueprint`, `PageBlueprint`, `PageBlock` - - `SiteConfig`, `SiteStructure`, `SiteWizardData` - -**Shared Component Library** (`frontend/src/components/shared/`): -- ✅ **Blocks**: - - `HeroBlock.tsx` - Hero section component - - `FeatureGridBlock.tsx` - Feature grid layout - - `StatsPanel.tsx` - Statistics display - - `blocks.css` - Shared block styles -- ✅ **Layouts**: - - `DefaultLayout.tsx` - Standard site layout - - `MinimalLayout.tsx` - Minimal layout variant - - `layouts.css` - Shared layout styles -- ✅ **Templates**: - - `MarketingTemplate.tsx` - Marketing site template - - `LandingTemplate.tsx` - Landing page template -- ✅ **Barrel Exports**: - - `blocks/index.ts`, `layouts/index.ts`, `templates/index.ts` - - `shared/index.ts` - Main export file -- ✅ **Documentation**: - - `shared/README.md` - Usage guide for shared components - -**Routing & Navigation**: -- ✅ React Router configured with routes: - - `/` - Wizard page - - `/preview` - Preview canvas - - `/dashboard` - Site dashboard -- ✅ Sidebar navigation with icons (Wand2, LayoutTemplate, PanelsTopLeft) - -**Styling**: -- ✅ TailwindCSS configured -- ✅ Global styles (`index.css`) -- ✅ App-specific styles (`App.css`) -- ✅ Component-specific CSS files - -#### Infrastructure - -**Docker Configuration**: -- ✅ `docker-compose.app.yml` - Added `igny8_site_builder` service -- ✅ Container runs on port `8025:5175` -- ✅ Volume mount: `/data/app/igny8/site-builder:/app:rw` -- ✅ Environment: `VITE_API_URL: "https://api.igny8.com/api"` -- ✅ Depends on `igny8_backend` health check - -**Caddy Routing**: -- ✅ Added `builder.igny8.com` server block to Caddyfile -- ✅ WebSocket support for Vite HMR -- ✅ Reverse proxy to `igny8_site_builder:5175` -- ✅ HTTPS enabled via automatic certificates - -**Package Dependencies** (`site-builder/package.json`): -- ✅ React 19.2.0, React DOM 19.2.0 -- ✅ React Router DOM 7.9.6 -- ✅ Zustand 5.0.8 (state management) -- ✅ Axios 1.13.2 (API client) -- ✅ React Hook Form 7.66.0 -- ✅ Lucide React 0.554.0 (icons) -- ✅ Vitest 2.1.5, React Testing Library (testing) -- ✅ Vite 7.2.2, TypeScript 5.9.3 - -#### Testing - -**Backend Tests**: -- ✅ `business/site_building/tests/base.py` - `SiteBuilderTestBase` with fixtures -- ✅ `business/site_building/tests/test_services.py`: - - `StructureGenerationServiceTests` - Tests structure generation flow - - `PageGenerationServiceTests` - Tests page content generation -- ✅ `ai/tests/test_generate_site_structure_function.py`: - - Tests JSON parsing from AI response - - Tests `PageBlueprint` sync (create/update/delete) - - Tests prompt building with existing pages - -**Frontend Tests**: -- ✅ `setupTests.ts` - Vitest configuration with jsdom -- ✅ `state/__tests__/builderStore.test.ts` - Wizard store tests -- ✅ `state/__tests__/siteDefinitionStore.test.ts` - Site definition store tests -- ✅ `pages/wizard/__tests__/WizardPage.test.tsx` - Wizard component tests -- ✅ `pages/preview/__tests__/PreviewCanvas.test.tsx` - Preview component tests - -#### Bug Fixes & Issues Resolved - -1. **500 Error on `/v1/writer/tasks`**: - - **Issue**: `TasksSerializer` crashing when `Content` record doesn't exist - - **Fix**: Updated `_get_content_record()` to catch `ObjectDoesNotExist` exception - - **File**: `modules/writer/serializers.py` - -2. **Database Schema Mismatch**: - - **Issue**: `Content` model had Phase 4 fields not in database - - **Fix**: Created and applied migration `0009_add_content_site_source_fields.py` - - **File**: `modules/writer/migrations/0009_add_content_site_source_fields.py` - -3. **Node.js Version Incompatibility**: - - **Issue**: Vite 7 requires Node.js 20.19+ or 22.12+ - - **Fix**: Updated `Dockerfile.dev` from `node:18-alpine` to `node:22-alpine` - - **File**: `site-builder/Dockerfile.dev` - -4. **Vite Host Blocking**: - - **Issue**: Vite dev server blocking `builder.igny8.com` requests - - **Fix**: Added `builder.igny8.com` to `server.allowedHosts` in `vite.config.ts` - - **File**: `site-builder/vite.config.ts` - -5. **Vite Alias Resolution**: - - **Issue**: `@shared` alias not resolving for shared components - - **Fix**: Added dynamic path resolution and `fs.allow` configuration - - **File**: `site-builder/vite.config.ts` - -6. **Migration Dependency Error**: - - **Issue**: `ValueError: Related model 'igny8_core_auth.account' cannot be resolved` - - **Fix**: Updated migration dependency to `0014_remove_plan_operation_limits_phase0` - - **File**: `business/site_building/migrations/0001_initial.py` - -7. **Frontend Test Failures**: - - **Issue**: Multiple elements matching text query - - **Fix**: Changed `getByText` to `getAllByText` in `PreviewCanvas.test.tsx` - - **Issue**: Incomplete mock state in `WizardPage.test.tsx` - - **Fix**: Added complete `style` object with default values - -### ✅ Phase 4: Linker & Optimizer - COMPLETE - -#### Backend Implementation - -**Content Model Extensions** (`business/content/models.py`): -- ✅ Added `source` field (igny8, wordpress, shopify, custom) -- ✅ Added `sync_status` field (native, imported, synced) -- ✅ Added `external_id`, `external_url`, `sync_metadata` fields -- ✅ Added `internal_links` JSON field -- ✅ Added `linker_version` integer field -- ✅ Added `optimizer_version` integer field -- ✅ Added `optimization_scores` JSON field -- ✅ Migration created and applied - -**Linking Services** (`business/linking/services/`): -- ✅ `LinkerService` - Main service for internal linking -- ✅ `CandidateEngine` - Finds link candidates based on content relevance -- ✅ `InjectionEngine` - Injects links into HTML content - -**Optimization Services** (`business/optimization/`): -- ✅ `OptimizationTask` model - Tracks optimization operations -- ✅ `OptimizerService` - Main service with multiple entry points: - - `optimize_from_writer()` - - `optimize_from_wordpress_sync()` - - `optimize_from_external_sync()` - - `optimize_manual()` -- ✅ `ContentAnalyzer` - Analyzes content for SEO, readability, engagement - -**Content Pipeline Service** (`business/content/services/`): -- ✅ `ContentPipelineService` - Orchestrates Writer → Linker → Optimizer pipeline -- ✅ `process_writer_content()` - Full pipeline for Writer content -- ✅ `process_synced_content()` - Optimization-only for synced content - -#### Frontend Implementation - -**API Clients** (`frontend/src/api/`): -- ✅ `linker.api.ts` - Linker API functions (`process`, `batchProcess`) -- ✅ `optimizer.api.ts` - Optimizer API functions (`optimize`, `batchOptimize`, `analyze`) - -**Shared Components** (`frontend/src/components/content/`): -- ✅ `SourceBadge.tsx` - Displays content source (igny8, wordpress, shopify, custom) -- ✅ `SyncStatusBadge.tsx` - Displays sync status (native, imported, synced) -- ✅ `ContentFilter.tsx` - Filters content by source and sync status -- ✅ `index.ts` - Barrel exports - -**Linker Components** (`frontend/src/components/linker/`): -- ✅ `LinkResults.tsx` - Displays linking results with links added count - -**Optimizer Components** (`frontend/src/components/optimizer/`): -- ✅ `OptimizationScores.tsx` - Displays optimization scores (SEO, readability, engagement, overall) -- ✅ `ScoreComparison.tsx` - Compares before/after optimization scores - -**Linker Pages** (`frontend/src/pages/Linker/`): -- ✅ `Dashboard.tsx` - Linker dashboard with stats and quick actions -- ✅ `ContentList.tsx` - Content list with link processing actions - -**Optimizer Pages** (`frontend/src/pages/Optimizer/`): -- ✅ `Dashboard.tsx` - Optimizer dashboard with stats and quick actions -- ✅ `ContentSelector.tsx` - Content selector with batch optimization and filters -- ✅ `AnalysisPreview.tsx` - Analysis preview page for content scores - -**Routing & Navigation**: -- ✅ Added Linker routes to `App.tsx` (`/linker`, `/linker/content`) -- ✅ Added Optimizer routes to `App.tsx` (`/optimizer`, `/optimizer/content`, `/optimizer/analyze/:id`) -- ✅ Updated `routes.config.ts` with Linker and Optimizer menu items -- ✅ Added Linker and Optimizer to sidebar navigation menu (`AppSidebar.tsx`) - -**Writer Integration**: -- ✅ Added source and sync status columns to Writer Content table -- ✅ Added source and sync status filters to Writer Content list -- ✅ Added "Optimize" action to Writer content rows -- ✅ Added "Send to Optimizer" action in Writer -- ✅ Updated `content.config.tsx` with source and sync status columns and filters - -**AI Function Created**: -- ✅ `OptimizeContentFunction` (`ai/functions/optimize_content.py`) - - Operation type: `optimize_content` - - Credit cost: 1 credit per 200 words (from constants) - - Optimizes content for SEO, readability, engagement - - All phases implemented: INIT, PREP, AI_CALL, PARSE, SAVE, DONE -- ✅ Added to AI registry (`ai/registry.py`) -- ✅ Added prompt to `ai/prompts.py` (`optimize_content`) -- ✅ Integrated into `OptimizerService._optimize_content()` - -**API Layer Created** (`modules/linker/` and `modules/optimizer/`): -- ✅ `LinkerViewSet` with actions: - - `process/` (POST) - Process content for linking - - `batch_process/` (POST) - Process multiple content items -- ✅ `OptimizerViewSet` with actions: - - `optimize/` (POST) - Optimize content (auto-detects entry point) - - `batch_optimize/` (POST) - Batch optimize multiple content items - - `analyze/` (POST) - Analyze content without optimizing -- ✅ Serializers: - - `LinkContentSerializer`, `BatchLinkContentSerializer` - - `OptimizeContentSerializer`, `BatchOptimizeContentSerializer`, `AnalyzeContentSerializer` -- ✅ URLs registered at `/api/v1/linker/` and `/api/v1/optimizer/` -- ✅ Added to `INSTALLED_APPS` in `settings.py` -- ✅ Throttle rates configured: `linker: 30/min`, `optimizer: 10/min` - -**Note**: Phase 4 frontend UI is **now complete** ✅ - -### 📋 Files Created/Modified - -#### Backend Files Created - -**Models & Migrations**: -- `backend/igny8_core/business/site_building/models.py` -- `backend/igny8_core/business/site_building/migrations/0001_initial.py` -- `backend/igny8_core/business/site_building/apps.py` -- `backend/igny8_core/modules/writer/migrations/0009_add_content_site_source_fields.py` - -**Services**: -- `backend/igny8_core/business/site_building/services/file_management_service.py` -- `backend/igny8_core/business/site_building/services/structure_generation_service.py` -- `backend/igny8_core/business/site_building/services/page_generation_service.py` -- `backend/igny8_core/business/linking/services/linker_service.py` -- `backend/igny8_core/business/linking/services/candidate_engine.py` -- `backend/igny8_core/business/linking/services/injection_engine.py` -- `backend/igny8_core/business/optimization/models.py` -- `backend/igny8_core/business/optimization/services/optimizer_service.py` -- `backend/igny8_core/business/content/services/content_pipeline_service.py` - -**AI Functions**: -- `backend/igny8_core/ai/functions/generate_site_structure.py` - -**API Layer**: -- `backend/igny8_core/modules/site_builder/__init__.py` -- `backend/igny8_core/modules/site_builder/apps.py` -- `backend/igny8_core/modules/site_builder/serializers.py` -- `backend/igny8_core/modules/site_builder/views.py` -- `backend/igny8_core/modules/site_builder/urls.py` - -**Tests**: -- `backend/igny8_core/business/site_building/tests/__init__.py` -- `backend/igny8_core/business/site_building/tests/base.py` -- `backend/igny8_core/business/site_building/tests/test_services.py` -- `backend/igny8_core/ai/tests/test_generate_site_structure_function.py` -- `backend/igny8_core/business/linking/tests/__init__.py` -- `backend/igny8_core/business/linking/tests/test_linker_service.py` -- `backend/igny8_core/business/linking/tests/test_candidate_engine.py` -- `backend/igny8_core/business/linking/tests/test_injection_engine.py` -- `backend/igny8_core/business/optimization/tests/__init__.py` -- `backend/igny8_core/business/optimization/tests/test_optimizer_service.py` -- `backend/igny8_core/business/optimization/tests/test_analyzer.py` -- `backend/igny8_core/business/content/tests/__init__.py` -- `backend/igny8_core/business/content/tests/test_content_pipeline_service.py` -- `backend/igny8_core/business/billing/tests/__init__.py` -- `backend/igny8_core/business/billing/tests/test_phase4_credits.py` -- `backend/igny8_core/modules/linker/tests/__init__.py` -- `backend/igny8_core/modules/linker/tests/test_views.py` -- `backend/igny8_core/modules/optimizer/tests/__init__.py` -- `backend/igny8_core/modules/optimizer/tests/test_views.py` -- `backend/igny8_core/ai/functions/tests/__init__.py` -- `backend/igny8_core/ai/functions/tests/test_optimize_content.py` - -#### Backend Files Modified - -- `backend/igny8_core/settings.py` - Added Site Builder, Linker, Optimizer apps to `INSTALLED_APPS`; Added throttle rates -- `backend/igny8_core/urls.py` - Added Site Builder, Linker, Optimizer URL routing -- `backend/igny8_core/ai/registry.py` - Registered `GenerateSiteStructureFunction` and `OptimizeContentFunction` -- `backend/igny8_core/ai/prompts.py` - Added `site_structure_generation` and `optimize_content` prompts -- `backend/igny8_core/ai/engine.py` - Integrated site structure generation -- `backend/igny8_core/business/content/models.py` - Added Phase 4 fields -- `backend/igny8_core/business/optimization/services/optimizer_service.py` - Updated `_optimize_content()` to use AI function -- `backend/igny8_core/modules/writer/serializers.py` - Fixed `Content.DoesNotExist` handling -- `frontend/src/App.tsx` - Added Linker and Optimizer routes -- `frontend/src/config/routes.config.ts` - Added Linker and Optimizer menu items -- `frontend/src/layout/AppSidebar.tsx` - Added Linker and Optimizer to sidebar navigation -- `frontend/src/config/pages/content.config.tsx` - Added source and sync status columns and filters -- `frontend/src/pages/Writer/Content.tsx` - Added optimize action, source/sync filters - -#### Frontend Files Created - -**Site Builder Application**: -- `site-builder/package.json` -- `site-builder/vite.config.ts` -- `site-builder/tsconfig.app.json` -- `site-builder/Dockerfile.dev` -- `site-builder/src/main.tsx` -- `site-builder/src/App.tsx` -- `site-builder/src/App.css` -- `site-builder/src/index.css` -- `site-builder/src/setupTests.ts` - -**Pages**: -- `site-builder/src/pages/wizard/WizardPage.tsx` -- `site-builder/src/pages/wizard/steps/BusinessDetailsStep.tsx` -- `site-builder/src/pages/wizard/steps/BriefStep.tsx` -- `site-builder/src/pages/wizard/steps/ObjectivesStep.tsx` -- `site-builder/src/pages/wizard/steps/StyleStep.tsx` -- `site-builder/src/pages/preview/PreviewCanvas.tsx` -- `site-builder/src/pages/dashboard/SiteDashboard.tsx` - -**State Management**: -- `site-builder/src/state/builderStore.ts` -- `site-builder/src/state/siteDefinitionStore.ts` - -**API & Types**: -- `site-builder/src/api/builder.api.ts` -- `site-builder/src/types/siteBuilder.ts` - -**Components**: -- `site-builder/src/components/common/Card.tsx` -- `site-builder/src/components/common/Card.css` - -**Tests**: -- `site-builder/src/state/__tests__/builderStore.test.ts` -- `site-builder/src/state/__tests__/siteDefinitionStore.test.ts` -- `site-builder/src/pages/wizard/__tests__/WizardPage.test.tsx` -- `site-builder/src/pages/preview/__tests__/PreviewCanvas.test.tsx` -- `frontend/src/components/content/__tests__/SourceBadge.test.tsx` -- `frontend/src/components/content/__tests__/SyncStatusBadge.test.tsx` -- `frontend/src/components/content/__tests__/ContentFilter.test.tsx` -- `frontend/src/pages/Linker/__tests__/Dashboard.test.tsx` -- `frontend/src/pages/Linker/__tests__/ContentList.test.tsx` -- `frontend/src/pages/Optimizer/__tests__/Dashboard.test.tsx` -- `frontend/src/pages/Optimizer/__tests__/ContentSelector.test.tsx` - -**Shared Component Library**: -- `frontend/src/components/shared/blocks/HeroBlock.tsx` -- `frontend/src/components/shared/blocks/FeatureGridBlock.tsx` -- `frontend/src/components/shared/blocks/StatsPanel.tsx` -- `frontend/src/components/shared/blocks/blocks.css` -- `frontend/src/components/shared/blocks/index.ts` -- `frontend/src/components/shared/layouts/DefaultLayout.tsx` -- `frontend/src/components/shared/layouts/MinimalLayout.tsx` -- `frontend/src/components/shared/layouts/layouts.css` -- `frontend/src/components/shared/layouts/index.ts` -- `frontend/src/components/shared/templates/MarketingTemplate.tsx` -- `frontend/src/components/shared/templates/LandingTemplate.tsx` -- `frontend/src/components/shared/templates/index.ts` -- `frontend/src/components/shared/index.ts` -- `frontend/src/components/shared/README.md` - -**Phase 4 Frontend Components**: -- `frontend/src/api/linker.api.ts` -- `frontend/src/api/optimizer.api.ts` -- `frontend/src/components/content/SourceBadge.tsx` -- `frontend/src/components/content/SyncStatusBadge.tsx` -- `frontend/src/components/content/ContentFilter.tsx` -- `frontend/src/components/content/index.ts` -- `frontend/src/components/linker/LinkResults.tsx` -- `frontend/src/components/optimizer/OptimizationScores.tsx` -- `frontend/src/components/optimizer/ScoreComparison.tsx` -- `frontend/src/pages/Linker/Dashboard.tsx` -- `frontend/src/pages/Linker/ContentList.tsx` -- `frontend/src/pages/Optimizer/Dashboard.tsx` -- `frontend/src/pages/Optimizer/ContentSelector.tsx` -- `frontend/src/pages/Optimizer/AnalysisPreview.tsx` - -#### Infrastructure Files Modified - -- `docker-compose.app.yml` - Added `igny8_site_builder` service -- `/var/lib/docker/volumes/portainer_data/_data/caddy/Caddyfile` - Added `builder.igny8.com` routing - -#### Files Removed (Temporary/One-Time Use) - -- `backend/import_plans.py` - One-time data import script -- `backend/igny8_core/test_settings.py` - Temporary test configuration -- `backend/igny8_core/api/tests/run_tests.py` - Helper test script -- `backend/igny8_core/ai/tests/test_run.py` - Temporary AI test script - -### 🔄 Remaining Work - -#### Phase 3 - Minor Enhancements -- [ ] Add file browser UI component to Site Builder -- [ ] Add deployment functionality (Phase 5 integration) -- [ ] Add page editor for manual block editing -- [ ] Add template selection in wizard - -#### Phase 4 - COMPLETE ✅ - -**All Phase 4 implementation tasks completed in this session:** - -**Backend**: -- ✅ AI Function (`OptimizeContentFunction`) created and integrated -- ✅ Linker API module (`modules/linker/`) with ViewSet, serializers, URLs -- ✅ Optimizer API module (`modules/optimizer/`) with ViewSet, serializers, URLs -- ✅ Settings and URL routing configured -- ✅ 10 backend test files created (70+ test cases) - -**Frontend**: -- ✅ API clients (`linker.api.ts`, `optimizer.api.ts`) -- ✅ Shared components (SourceBadge, SyncStatusBadge, ContentFilter, LinkResults, OptimizationScores, ScoreComparison) -- ✅ Linker pages (Dashboard, ContentList) -- ✅ Optimizer pages (Dashboard, ContentSelector, AnalysisPreview) -- ✅ Writer integration (source badges, filters, optimize actions) -- ✅ Routing and navigation (routes, sidebar menu) -- ✅ 7 frontend test files created (30+ test cases) - -**Summary**: Phase 4 is 100% complete with all backend services, AI functions, API endpoints, frontend UI, and comprehensive test coverage. - -### 📊 Implementation Statistics - -- **Backend Files Created**: 40+ -- **Frontend Files Created**: 45+ -- **Backend Tests**: 13 test files, 70+ test cases -- **Frontend Tests**: 11 test files, 30+ test cases -- **Lines of Code**: ~8,000+ (backend + frontend) -- **Docker Containers**: 1 new container (`igny8_site_builder`) -- **API Endpoints**: 15+ new endpoints -- **Database Tables**: 2 new tables (`SiteBlueprint`, `PageBlueprint`) -- **Migrations**: 2 migrations created and applied - -#### Phase 4 Statistics (This Session) -- **Backend Files Created**: 15+ - - AI Function: 1 file - - API Modules: 6 files (linker + optimizer) - - Test Files: 10 files -- **Frontend Files Created**: 20+ - - API Clients: 2 files - - Components: 6 files - - Pages: 5 files - - Test Files: 7 files -- **Backend Test Cases**: 70+ individual test methods -- **Frontend Test Cases**: 30+ individual test methods - ---- - -## OVERVIEW - -### Implementation Approach -- **Phase 3**: Build Site Builder with wizard, AI structure generation, and file management -- **Phase 4**: Implement Linker and Optimizer as post-processing stages with multiple entry points -- **Shared Components**: Create global component library for reuse across apps -- **Integration**: Ensure seamless integration with existing Phase 1 & 2 services - -### Key Principles -- **Service Layer Pattern**: All business logic in services (Phase 1 pattern) -- **Credit-Aware**: All operations check credits before execution -- **Multiple Entry Points**: Optimizer works from Writer, WordPress sync, 3rd party, manual -- **Component Reuse**: Shared components across Site Builder, Sites Renderer, Main App - ---- - -## PHASE 3: SITE BUILDER IMPLEMENTATION PLAN - -### 3.1 Backend Structure - -#### Business Layer (`business/site_building/`) - -``` -business/site_building/ -├── __init__.py -├── models.py # SiteBlueprint, PageBlueprint -├── migrations/ -│ └── 0001_initial.py -└── services/ - ├── __init__.py - ├── file_management_service.py - ├── structure_generation_service.py - └── page_generation_service.py -``` - -**Models to Create**: - -1. **SiteBlueprint** (`business/site_building/models.py`) - - Fields: - - `name`, `description` - - `config_json` (wizard choices: business_type, style, objectives) - - `structure_json` (AI-generated structure: pages, layout, theme) - - `status` (draft, generating, ready, deployed) - - `hosting_type` (igny8_sites, wordpress, shopify, multi) - - `version`, `deployed_version` - - Inherits from `SiteSectorBaseModel` - -2. **PageBlueprint** (`business/site_building/models.py`) - - Fields: - - `site_blueprint` (ForeignKey) - - `slug`, `title` - - `type` (home, about, services, products, blog, contact, custom) - - `blocks_json` (page content blocks) - - `status` (draft, generating, ready) - - `order` - - Inherits from `SiteSectorBaseModel` - -#### Services to Create - -1. **FileManagementService** (`business/site_building/services/file_management_service.py`) - ```python - class SiteBuilderFileService: - def get_user_accessible_sites(self, user) - def check_file_access(self, user, site_id) - def upload_file(self, user, site_id, file, folder='images') - def delete_file(self, user, site_id, file_path) - def list_files(self, user, site_id, folder='images') - def check_storage_quota(self, site_id, file_size) - ``` - -2. **StructureGenerationService** (`business/site_building/services/structure_generation_service.py`) - ```python - class StructureGenerationService: - def __init__(self): - self.ai_function = GenerateSiteStructureFunction() - self.credit_service = CreditService() - - def generate_structure(self, site_blueprint, business_brief, objectives, style) - def _create_page_blueprints(self, site_blueprint, structure) - ``` - -3. **PageGenerationService** (`business/site_building/services/page_generation_service.py`) - ```python - class PageGenerationService: - def __init__(self): - self.content_service = ContentGenerationService() - self.credit_service = CreditService() - - def generate_page_content(self, page_blueprint, account) - def regenerate_page(self, page_blueprint, account) - ``` - -#### AI Functions (`infrastructure/ai/functions/`) - -1. **GenerateSiteStructureFunction** (`infrastructure/ai/functions/generate_site_structure.py`) - - Operation type: `site_structure_generation` - - Credit cost: 50 credits (from constants) - - Generates site structure JSON from business brief - -#### API Layer (`modules/site_builder/`) - -``` -modules/site_builder/ -├── __init__.py -├── views.py # SiteBuilderViewSet, PageBlueprintViewSet, FileUploadView -├── serializers.py # SiteBlueprintSerializer, PageBlueprintSerializer -├── urls.py -└── apps.py -``` - -**ViewSets to Create**: - -1. **SiteBuilderViewSet** (`modules/site_builder/views.py`) - - CRUD for SiteBlueprint - - Actions: - - `generate_structure/` (POST) - Trigger AI structure generation - - `deploy/` (POST) - Deploy site to hosting - - `preview/` (GET) - Get preview JSON - -2. **PageBlueprintViewSet** (`modules/site_builder/views.py`) - - CRUD for PageBlueprint - - Actions: - - `generate_content/` (POST) - Generate page content - - `regenerate/` (POST) - Regenerate page content - -3. **FileUploadView** (`modules/site_builder/views.py`) - - `upload/` (POST) - Upload file to site assets - - `delete/` (DELETE) - Delete file - - `list/` (GET) - List files - -#### File Storage Structure - -``` -/data/app/sites-data/ -└── clients/ - └── {site_id}/ - └── v{version}/ - ├── site.json # Site definition - ├── pages/ # Page definitions - │ ├── home.json - │ ├── about.json - │ └── ... - └── assets/ # User-managed files - ├── images/ - ├── documents/ - └── media/ -``` - -### 3.2 Frontend Structure - -#### Site Builder Container (`site-builder/`) - -``` -site-builder/ -├── src/ -│ ├── pages/ -│ │ ├── wizard/ -│ │ │ ├── Step1TypeSelection.tsx -│ │ │ ├── Step2BusinessBrief.tsx -│ │ │ ├── Step3Objectives.tsx -│ │ │ └── Step4Style.tsx -│ │ ├── preview/ -│ │ │ └── PreviewCanvas.tsx -│ │ └── dashboard/ -│ │ └── SiteList.tsx -│ ├── components/ -│ │ ├── blocks/ # Block components (import from shared) -│ │ ├── forms/ -│ │ ├── files/ -│ │ │ └── FileBrowser.tsx -│ │ └── preview-canvas/ -│ ├── state/ -│ │ ├── builderStore.ts -│ │ └── siteDefinitionStore.ts -│ ├── api/ -│ │ ├── builder.api.ts -│ │ └── sites.api.ts -│ └── main.tsx -├── package.json -├── vite.config.ts -└── Dockerfile -``` - -#### Shared Component Library (`frontend/src/components/shared/`) - -``` -frontend/src/components/shared/ -├── blocks/ -│ ├── Hero.tsx -│ ├── Features.tsx -│ ├── Services.tsx -│ ├── Products.tsx -│ ├── Testimonials.tsx -│ ├── ContactForm.tsx -│ └── ... -├── layouts/ -│ ├── DefaultLayout.tsx -│ ├── MinimalLayout.tsx -│ ├── MagazineLayout.tsx -│ ├── EcommerceLayout.tsx -│ ├── PortfolioLayout.tsx -│ ├── BlogLayout.tsx -│ └── CorporateLayout.tsx -└── templates/ - ├── BlogTemplate.tsx - ├── BusinessTemplate.tsx - └── PortfolioTemplate.tsx -``` - -### 3.3 Implementation Tasks - -#### Backend Tasks (Priority Order) - -1. **Create Business Models** - - [x] Create `business/site_building/` folder - - [x] Create `SiteBlueprint` model - - [x] Create `PageBlueprint` model - - [x] Create migrations - -2. **Create Services** - - [x] Create `FileManagementService` - - [x] Create `StructureGenerationService` - - [x] Create `PageGenerationService` - - [x] Integrate with `CreditService` - -3. **Create AI Function** - - [x] Create `GenerateSiteStructureFunction` - - [x] Add prompts for site structure generation - - [x] Test AI function - -4. **Create API Layer** - - [x] Create `modules/site_builder/` folder - - [x] Create `SiteBuilderViewSet` - - [x] Create `PageBlueprintViewSet` - - [x] Create `FileUploadView` - - [x] Create serializers - - [x] Register URLs - -#### Frontend Tasks (Priority Order) - -1. **Create Site Builder Container** - - [x] Create `site-builder/` folder structure - - [x] Set up Vite + React + TypeScript - - [x] Configure Docker container - - [x] Set up routing - -2. **Create Wizard** - - [x] Step 1: Business Details (Type Selection) - - [x] Step 2: Business Brief - - [x] Step 3: Objectives - - [x] Step 4: Style Preferences - - [x] Wizard state management - -3. **Create Preview Canvas** - - [x] Preview renderer - - [x] Block rendering - - [x] Layout rendering - -4. **Create Shared Components** - - [x] Block components - - [x] Layout components - - [x] Template components - ---- - -## PHASE 4: LINKER & OPTIMIZER IMPLEMENTATION PLAN - -### 4.1 Backend Structure - -#### Business Layer - -``` -business/ -├── linking/ -│ ├── __init__.py -│ ├── models.py # InternalLink (optional) -│ └── services/ -│ ├── __init__.py -│ ├── linker_service.py -│ ├── candidate_engine.py -│ └── injection_engine.py -│ -├── optimization/ -│ ├── __init__.py -│ ├── models.py # OptimizationTask, OptimizationScores -│ └── services/ -│ ├── __init__.py -│ ├── optimizer_service.py -│ └── analyzer.py -│ -└── content/ - └── services/ - └── content_pipeline_service.py # NEW: Orchestrates pipeline -``` - -#### Content Model Extensions - -**Extend `business/content/models.py`**: - -```python -class Content(SiteSectorBaseModel): - # Existing fields... - - # NEW: Source tracking (Phase 4) - source = models.CharField( - max_length=50, - choices=[ - ('igny8', 'IGNY8 Generated'), - ('wordpress', 'WordPress Synced'), - ('shopify', 'Shopify Synced'), - ('custom', 'Custom API Synced'), - ], - default='igny8' - ) - - sync_status = models.CharField( - max_length=50, - choices=[ - ('native', 'Native IGNY8 Content'), - ('imported', 'Imported from External'), - ('synced', 'Synced from External'), - ], - default='native' - ) - - external_id = models.CharField(max_length=255, blank=True, null=True) - external_url = models.URLField(blank=True, null=True) - sync_metadata = models.JSONField(default=dict) - - # NEW: Linking fields - internal_links = models.JSONField(default=list) - linker_version = models.IntegerField(default=0) - - # NEW: Optimization fields - optimizer_version = models.IntegerField(default=0) - optimization_scores = models.JSONField(default=dict) -``` - -#### Models to Create - -1. **OptimizationTask** (`business/optimization/models.py`) - - Fields: - - `content` (ForeignKey to Content) - - `scores_before`, `scores_after` (JSON) - - `html_before`, `html_after` (Text) - - `status` (pending, completed, failed) - - `credits_used` - - Inherits from `AccountBaseModel` - -2. **OptimizationScores** (`business/optimization/models.py`) - Optional - - Store detailed scoring metrics - -#### Services to Create - -1. **LinkerService** (`business/linking/services/linker_service.py`) - ```python - class LinkerService: - def __init__(self): - self.candidate_engine = CandidateEngine() - self.injection_engine = InjectionEngine() - self.credit_service = CreditService() - - def process(self, content_id) - def batch_process(self, content_ids) - ``` - -2. **CandidateEngine** (`business/linking/services/candidate_engine.py`) - ```python - class CandidateEngine: - def find_candidates(self, content) - def _find_relevant_content(self, content) - def _score_candidates(self, content, candidates) - ``` - -3. **InjectionEngine** (`business/linking/services/injection_engine.py`) - ```python - class InjectionEngine: - def inject_links(self, content, candidates) - def _inject_link_into_html(self, html, link_data) - ``` - -4. **OptimizerService** (`business/optimization/services/optimizer_service.py`) - ```python - class OptimizerService: - def __init__(self): - self.analyzer = ContentAnalyzer() - self.ai_function = OptimizeContentFunction() - self.credit_service = CreditService() - - # Multiple entry points - def optimize_from_writer(self, content_id) - def optimize_from_wordpress_sync(self, content_id) - def optimize_from_external_sync(self, content_id) - def optimize_manual(self, content_id) - - # Unified optimization logic - def optimize(self, content) - ``` - -5. **ContentAnalyzer** (`business/optimization/services/analyzer.py`) - ```python - class ContentAnalyzer: - def analyze(self, content) - def _calculate_seo_score(self, content) - def _calculate_readability_score(self, content) - def _calculate_engagement_score(self, content) - ``` - -6. **ContentPipelineService** (`business/content/services/content_pipeline_service.py`) - ```python - class ContentPipelineService: - def __init__(self): - self.linker_service = LinkerService() - self.optimizer_service = OptimizerService() - - def process_writer_content(self, content_id, stages=['linking', 'optimization']) - def process_synced_content(self, content_id, stages=['optimization']) - ``` - -#### AI Functions - -1. **OptimizeContentFunction** (`infrastructure/ai/functions/optimize_content.py`) - - Operation type: `optimization` - - Credit cost: 1 credit per 200 words - - Optimizes content for SEO, readability, engagement - -#### API Layer (`modules/linker/` and `modules/optimizer/`) - -``` -modules/ -├── linker/ -│ ├── __init__.py -│ ├── views.py # LinkerViewSet -│ ├── serializers.py -│ ├── urls.py -│ └── apps.py -│ -└── optimizer/ - ├── __init__.py - ├── views.py # OptimizerViewSet - ├── serializers.py - ├── urls.py - └── apps.py -``` - -**ViewSets to Create**: - -1. **LinkerViewSet** (`modules/linker/views.py`) - - Actions: - - `process/` (POST) - Process content for linking - - `batch_process/` (POST) - Process multiple content items - -2. **OptimizerViewSet** (`modules/optimizer/views.py`) - - Actions: - - `optimize/` (POST) - Optimize content (auto-detects source) - - `optimize_from_writer/` (POST) - Entry point 1 - - `optimize_from_sync/` (POST) - Entry point 2 & 3 - - `optimize_manual/` (POST) - Entry point 4 - - `analyze/` (GET) - Analyze content without optimizing - -### 4.2 Frontend Structure - -#### Linker UI (`frontend/src/pages/Linker/`) - -``` -frontend/src/pages/Linker/ -├── Dashboard.tsx -├── ContentList.tsx -└── LinkResults.tsx -``` - -#### Optimizer UI (`frontend/src/pages/Optimizer/`) - -``` -frontend/src/pages/Optimizer/ -├── Dashboard.tsx -├── ContentSelector.tsx -├── OptimizationResults.tsx -└── ScoreComparison.tsx -``` - -#### Shared Components - -``` -frontend/src/components/ -├── content/ -│ ├── SourceBadge.tsx # Show content source (IGNY8, WordPress, etc.) -│ ├── SyncStatusBadge.tsx # Show sync status -│ ├── ContentFilter.tsx # Filter by source, sync_status -│ └── SourceFilter.tsx -``` - -### 4.3 Implementation Tasks - -#### Backend Tasks (Priority Order) - -1. **Extend Content Model** - - [x] Add `source` field - - [x] Add `sync_status` field - - [x] Add `external_id`, `external_url`, `sync_metadata` - - [x] Add `internal_links`, `linker_version` - - [x] Add `optimizer_version`, `optimization_scores` - - [x] Create migration - -2. **Create Linking Services** - - [x] Create `business/linking/` folder - - [x] Create `LinkerService` - - [x] Create `CandidateEngine` - - [x] Create `InjectionEngine` - - [x] Integrate with `CreditService` - -3. **Create Optimization Services** - - [x] Create `business/optimization/` folder - - [x] Create `OptimizationTask` model - - [x] Create `OptimizerService` (with multiple entry points) - - [x] Create `ContentAnalyzer` - - [x] Integrate with `CreditService` - -4. **Create AI Function** - - [x] Create `OptimizeContentFunction` - - [x] Add optimization prompts - - [x] Test AI function - -5. **Create Pipeline Service** - - [x] Create `ContentPipelineService` - - [x] Integrate Linker and Optimizer - -6. **Create API Layer** - - [x] Create `modules/linker/` folder - - [x] Create `LinkerViewSet` - - [x] Create `modules/optimizer/` folder - - [x] Create `OptimizerViewSet` - - [x] Create serializers - - [x] Register URLs - -#### Frontend Tasks (Priority Order) - -1. **Create Linker UI** - - [x] Linker Dashboard - - [x] Content List - - [x] Link Results display - -2. **Create Optimizer UI** - - [x] Optimizer Dashboard - - [x] Content Selector (with source filters) - - [x] Optimization Results - - [x] Score Comparison - - [x] Analysis Preview - -3. **Create Shared Components** - - [x] SourceBadge component - - [x] SyncStatusBadge component - - [x] ContentFilter component - - [x] LinkResults component - - [x] OptimizationScores component - - [x] ScoreComparison component - -4. **Update Content List** - - [x] Add source badges - - [x] Add sync status badges - - [x] Add filters (by source, sync_status) - - [x] Add "Optimize" action button - - [x] Add "Send to Optimizer" action - ---- - -## INTEGRATION POINTS - -### Phase 3 Integration - -1. **With Phase 1 Services** - - `StructureGenerationService` uses `CreditService` - - `PageGenerationService` uses `ContentGenerationService` - - All operations check credits before execution - -2. **With Phase 2 Automation** - - Automation rules can trigger site structure generation - - Automation can deploy sites automatically - -3. **With Content Service** - - Page generation reuses `ContentGenerationService` - - Site pages stored as `Content` records - -### Phase 4 Integration - -1. **With Phase 1 Services** - - `LinkerService` uses `CreditService` - - `OptimizerService` uses `CreditService` - - `ContentPipelineService` orchestrates services - -2. **With Writer Module** - - Writer → Linker → Optimizer pipeline - - Content generated in Writer flows to Linker/Optimizer - -3. **With WordPress Sync** (Phase 6) - - WordPress content synced with `source='wordpress'` - - Optimizer works on synced content - -4. **With 3rd Party Sync** (Phase 6) - - External content synced with `source='shopify'` or `source='custom'` - - Optimizer works on all sources - -### Cross-Phase Integration - -1. **Site Builder → Linker/Optimizer** - - Site pages can be optimized - - Site content can be linked internally - -2. **Content Pipeline** - - Unified pipeline: Writer → Linker → Optimizer → Publish - - Works for all content sources - ---- - -## FILE STRUCTURE - -### Complete Backend Structure - -``` -backend/igny8_core/ -├── business/ -│ ├── automation/ # Phase 2 ✅ -│ ├── billing/ # Phase 0, 1 ✅ -│ ├── content/ # Phase 1 ✅ -│ │ └── services/ -│ │ └── content_pipeline_service.py # Phase 4 NEW -│ ├── linking/ # Phase 4 NEW -│ │ ├── models.py -│ │ └── services/ -│ │ ├── linker_service.py -│ │ ├── candidate_engine.py -│ │ └── injection_engine.py -│ ├── optimization/ # Phase 4 NEW -│ │ ├── models.py -│ │ └── services/ -│ │ ├── optimizer_service.py -│ │ └── analyzer.py -│ ├── planning/ # Phase 1 ✅ -│ └── site_building/ # Phase 3 NEW -│ ├── models.py -│ └── services/ -│ ├── file_management_service.py -│ ├── structure_generation_service.py -│ └── page_generation_service.py -│ -├── modules/ -│ ├── automation/ # Phase 2 ✅ -│ ├── billing/ # Phase 0, 1 ✅ -│ ├── linker/ # Phase 4 NEW -│ ├── optimizer/ # Phase 4 NEW -│ ├── planner/ # Phase 1 ✅ -│ ├── site_builder/ # Phase 3 NEW -│ └── writer/ # Phase 1 ✅ -│ -└── infrastructure/ - └── ai/ - └── functions/ - ├── generate_site_structure.py # Phase 3 NEW - └── optimize_content.py # Phase 4 NEW -``` - -### Complete Frontend Structure - -``` -frontend/src/ -├── components/ -│ ├── shared/ # Phase 3 NEW -│ │ ├── blocks/ -│ │ ├── layouts/ -│ │ └── templates/ -│ └── content/ # Phase 4 NEW -│ ├── SourceBadge.tsx -│ ├── SyncStatusBadge.tsx -│ └── ContentFilter.tsx -│ -└── pages/ - ├── Linker/ # Phase 4 NEW - │ ├── Dashboard.tsx - │ └── ContentList.tsx - ├── Optimizer/ # Phase 4 NEW - │ ├── Dashboard.tsx - │ └── ContentSelector.tsx - └── Writer/ # Phase 1 ✅ - └── ... - -site-builder/src/ # Phase 3 NEW -├── pages/ -│ ├── wizard/ -│ ├── preview/ -│ └── dashboard/ -└── components/ -``` - ---- - -## DEPENDENCIES & ORDER - -### Phase 3 Dependencies - -1. **Required (Already Complete)** - - ✅ Phase 0: Credit system - - ✅ Phase 1: Service layer (ContentGenerationService, CreditService) - - ✅ Phase 2: Automation system (optional integration) - -2. **Phase 3 Implementation Order** - - Step 1: Create models (SiteBlueprint, PageBlueprint) - - Step 2: Create FileManagementService - - Step 3: Create StructureGenerationService + AI function - - Step 4: Create PageGenerationService - - Step 5: Create API layer (ViewSets) - - Step 6: Create frontend container structure - - Step 7: Create wizard UI - - Step 8: Create preview canvas - - Step 9: Create shared component library - -### Phase 4 Dependencies - -1. **Required (Already Complete)** - - ✅ Phase 0: Credit system - - ✅ Phase 1: Service layer (ContentGenerationService, CreditService) - - ✅ Content model (needs extension) - -2. **Phase 4 Implementation Order** - - Step 1: Extend Content model (add source, sync_status, linking, optimization fields) - - Step 2: Create linking services (LinkerService, CandidateEngine, InjectionEngine) - - Step 3: Create optimization services (OptimizerService, ContentAnalyzer) - - Step 4: Create optimization AI function - - Step 5: Create ContentPipelineService - - Step 6: Create API layer (LinkerViewSet, OptimizerViewSet) - - Step 7: Create frontend UI (Linker Dashboard, Optimizer Dashboard) - - Step 8: Create shared components (SourceBadge, ContentFilter) - -### Parallel Implementation - -- **Phase 3 and Phase 4 can be implemented in parallel** after: - - Content model extensions (Phase 4 Step 1) are complete - - Both phases use Phase 1 services independently - ---- - -## TESTING STRATEGY - -### Phase 3 Testing - -1. **Backend Tests** - - Test SiteBlueprint CRUD - - Test PageBlueprint CRUD - - Test structure generation (AI function) - - Test file upload/delete/access - - Test credit deduction - -2. **Frontend Tests** - - Test wizard flow - - Test preview rendering - - Test file browser - - Test component library - -### Phase 4 Testing ✅ COMPLETE - -1. **Backend Tests** ✅ - - ✅ Test Content model extensions (via service tests) - - ✅ Test LinkerService (`test_linker_service.py` - 8 test cases) - - ✅ Test CandidateEngine (`test_candidate_engine.py` - 6 test cases) - - ✅ Test InjectionEngine (`test_injection_engine.py` - 6 test cases) - - ✅ Test OptimizerService (`test_optimizer_service.py` - 10 test cases) - - ✅ Test ContentAnalyzer (`test_analyzer.py` - 8 test cases) - - ✅ Test ContentPipelineService (`test_content_pipeline_service.py` - 10 test cases) - - ✅ Test credit deduction (`test_phase4_credits.py` - 8 test cases) - - ✅ Test Linker API endpoints (`test_views.py` - 9 test cases) - - ✅ Test Optimizer API endpoints (`test_views.py` - 10 test cases) - - ✅ Test OptimizeContentFunction (`test_optimize_content.py` - 10 test cases) - - **Total**: 10 test files, 85+ test cases - -2. **Frontend Tests** ✅ - - ✅ Test SourceBadge component (`SourceBadge.test.tsx`) - - ✅ Test SyncStatusBadge component (`SyncStatusBadge.test.tsx`) - - ✅ Test ContentFilter component (`ContentFilter.test.tsx`) - - ✅ Test Linker Dashboard (`Dashboard.test.tsx`) - - ✅ Test Linker ContentList (`ContentList.test.tsx`) - - ✅ Test Optimizer Dashboard (`Dashboard.test.tsx`) - - ✅ Test Optimizer ContentSelector (`ContentSelector.test.tsx`) - - **Total**: 7 test files, 30+ test cases - -### Integration Tests - -1. **Writer → Linker → Optimizer Pipeline** - - Test full pipeline flow - - Test credit deduction at each stage - -2. **WordPress Sync → Optimizer** (Phase 6) - - Test synced content optimization - - Test source tracking - ---- - -## CREDIT COSTS - -### Phase 3 Credit Costs - -- `site_structure_generation`: 50 credits (per site blueprint) -- `site_page_generation`: 20 credits (per page) -- File storage: No credits (storage quota based) - -### Phase 4 Credit Costs - -- `linking`: 8 credits (per content piece) -- `optimization`: 1 credit per 200 words - ---- - -## SUCCESS CRITERIA - -### Phase 3 Success Criteria - -- ✅ Site Builder wizard works end-to-end -- ✅ AI structure generation creates valid blueprints -- ✅ Preview renders correctly -- ✅ File management works -- ✅ Shared components work across apps -- ✅ Page generation reuses ContentGenerationService - -### Phase 4 Success Criteria - -- ✅ Linker finds appropriate link candidates -- ✅ Links inject correctly into content -- ✅ Optimizer works from all entry points (Writer, WordPress, 3rd party, Manual) -- ✅ Content source tracking works -- ✅ Pipeline orchestrates correctly -- ✅ UI shows content sources and filters -- ✅ API endpoints functional and tested -- ✅ AI function integrated and working -- ✅ Credit deduction working at all stages -- ✅ Frontend UI complete with all dashboards and selectors -- ✅ Writer integration complete with badges and filters -- ✅ Navigation and routing complete -- ✅ Backend tests complete (10 test files) -- ✅ Frontend tests complete (7 test files) - ---- - -## RISK MITIGATION - -### Phase 3 Risks - -1. **AI Structure Generation Quality** - - Mitigation: Prompt engineering, validation, user feedback loop - -2. **Component Compatibility** - - Mitigation: Shared component library, comprehensive testing - -3. **File Management Security** - - Mitigation: Access control, validation, quota checks - -### Phase 4 Risks - -1. **Link Quality** - - Mitigation: Candidate scoring algorithm, relevance checks - -2. **Optimization Quality** - - Mitigation: Content analysis, before/after comparison, user review - -3. **Multiple Entry Points Complexity** - - Mitigation: Unified optimization logic, clear entry point methods - ---- - -**END OF IMPLEMENTATION PLAN** - - diff --git a/docs/planning/phases/PHASE-0-4-FOUNDATION-TO-LINKER-OPTIMIZER.md b/docs/planning/phases/PHASE-0-4-FOUNDATION-TO-LINKER-OPTIMIZER.md new file mode 100644 index 00000000..e89e59b6 --- /dev/null +++ b/docs/planning/phases/PHASE-0-4-FOUNDATION-TO-LINKER-OPTIMIZER.md @@ -0,0 +1,1180 @@ +# PHASES 0-4: FOUNDATION TO LINKER & OPTIMIZER +**Complete Implementation Documentation - IMPLEMENTED ✅** + +**Status**: All Phases Complete +**Last Updated**: 2025-01-XX +**Implementation Period**: Foundation through Linker & Optimizer + +--- + +## TABLE OF CONTENTS + +1. [Executive Summary](#executive-summary) +2. [Phase 0: Foundation & Credit System](#phase-0-foundation--credit-system) +3. [Phase 1: Service Layer Refactoring](#phase-1-service-layer-refactoring) +4. [Phase 2: Automation System](#phase-2-automation-system) +5. [Phase 3: Site Builder](#phase-3-site-builder) +6. [Phase 4: Linker & Optimizer](#phase-4-linker--optimizer) +7. [Cross-Phase Integration](#cross-phase-integration) +8. [Database Migrations Summary](#database-migrations-summary) +9. [Testing Strategy](#testing-strategy) + +--- + +## EXECUTIVE SUMMARY + +This document covers the complete implementation of Phases 0-4, establishing the foundation for the IGNY8 platform: + +- **Phase 0**: Credit-only system replacing plan limits, module enable/disable functionality +- **Phase 1**: Service layer architecture with business logic extraction +- **Phase 2**: Automation rules and scheduled tasks system +- **Phase 3**: Site Builder with AI-powered structure generation +- **Phase 4**: Internal linking and content optimization with multiple entry points + +All phases are **fully implemented** and integrated into the production system. + +--- + +## PHASE 0: FOUNDATION & CREDIT SYSTEM + +**Status**: ✅ **IMPLEMENTED** + +### Purpose + +Migrate from plan-based limits to a credit-only model while preserving all existing functionality. Establish module enable/disable capabilities and comprehensive credit tracking. + +### Key Objectives + +- Migrate from plan-based limits to credit-only system +- Implement module enable/disable functionality +- Add credit cost tracking for all operations +- Preserve all existing functionality +- Update frontend to show credits instead of limits + +### Models + +#### ModuleSettings Model +**Purpose**: Control module availability per account + +**Key Fields**: +- `planner_enabled` - Boolean flag for Planner module +- `writer_enabled` - Boolean flag for Writer module +- `automation_enabled` - Boolean flag for Automation module +- `site_builder_enabled` - Boolean flag for Site Builder module +- `linker_enabled` - Boolean flag for Linker module +- `optimizer_enabled` - Boolean flag for Optimizer module + +**Workflow**: Accounts can enable/disable modules through settings. Disabled modules don't appear in UI and don't load routes. + +#### Plan Model Updates +**Purpose**: Simplified plan model with only credit allocation + +**Fields Removed**: +- All limit fields (`max_keywords`, `max_clusters`, `max_content_ideas`, `daily_content_tasks`, `monthly_word_count_limit`, `daily_image_generation_limit`, `monthly_image_count`) + +**Fields Retained**: +- `monthly_credits` - Credits allocated per month +- `support_level` - Support tier +- `billing_cycle` - Billing frequency +- `price` - Plan price +- `features` - JSON field for future use + +#### CreditUsageLog Model +**Purpose**: Track all credit usage with detailed metadata + +**Key Fields**: +- `operation_type` - Type of operation (clustering, content_generation, linking, optimization, etc.) +- `credits_used` - Credits consumed +- `related_object_type` - Related model type +- `related_object_id` - Related model ID +- `metadata` - JSON field for operation-specific data + +### Services + +#### CreditService +**Purpose**: Centralized credit management and validation + +**Key Functions**: +- `check_credits(account, operation_type, amount=None)` - Validates sufficient credits before operation +- `deduct_credits(account, operation_type, amount=None)` - Deducts credits after successful operation +- `get_credit_cost(operation_type, amount=None)` - Calculates credit cost for operation +- `add_credits(account, amount, reason)` - Adds credits (for replenishment) + +**Credit Cost Constants**: +- `clustering`: 10 credits per request +- `idea_generation`: 15 credits per cluster → ideas request +- `content_generation`: 1 credit per 100 words +- `image_generation`: 5 credits per image +- `linking`: 8 credits per content piece +- `optimization`: 1 credit per 200 words +- `site_structure_generation`: 50 credits per site blueprint +- `site_page_generation`: 20 credits per page + +**Workflow**: All operations check credits before execution, deduct credits after success, and log usage for audit trail. + +### Workflows + +#### Module Enable/Disable Workflow +1. User accesses Settings → Modules +2. User toggles module enabled/disabled state +3. Frontend checks module status before loading routes +4. Disabled modules filtered from sidebar navigation +5. API validates module status before processing requests + +#### Credit Check Workflow +1. Operation initiated (e.g., content generation) +2. Service calls `CreditService.check_credits()` +3. System validates account has sufficient credits +4. If insufficient, raises `InsufficientCreditsError` +5. If sufficient, operation proceeds +6. After success, `CreditService.deduct_credits()` called +7. Usage logged in `CreditUsageLog` + +#### Monthly Credit Replenishment Workflow +1. Celery Beat task runs on 1st of each month +2. Task queries all active accounts +3. For each account, adds `plan.monthly_credits` to balance +4. Logs replenishment in `CreditUsageLog` + +### Database Migrations + +**Migration**: `igny8_core_auth.0014_remove_plan_operation_limits_phase0` +- **Purpose**: Remove all plan limit fields +- **Status**: ✅ Applied +- **Risk**: LOW - Fields were unused, migration removes them safely + +**Migration**: Credit tracking fields already included in `billing.0001_initial` +- `related_object_type`, `related_object_id`, `metadata` fields exist in `CreditUsageLog` + +### Frontend Implementation + +**Module Settings UI**: +- Settings page with toggle switches for each module +- Module status checked before route loading +- Disabled modules hidden from sidebar + +**Credit Display**: +- Credit balance shown prominently in header +- Credit costs displayed per operation +- Usage history filtered by operation type + +--- + +## PHASE 1: SERVICE LAYER REFACTORING + +**Status**: ✅ **IMPLEMENTED** + +### Purpose + +Extract business logic from ViewSets into reusable services, creating a clean separation between API layer and business logic. + +### Key Objectives + +- Create `business/` folder structure +- Move models from `modules/` to `business/` +- Extract business logic from ViewSets to services +- Keep ViewSets as thin wrappers +- Preserve all existing API functionality + +### Architecture + +#### Business Layer Structure +``` +business/ +├── content/ # Content business logic +│ ├── models.py # Content, Tasks, Images +│ └── services/ +│ ├── content_generation_service.py +│ ├── content_pipeline_service.py +│ └── content_versioning_service.py +│ +├── planning/ # Planning business logic +│ ├── models.py # Keywords, Clusters, Ideas +│ └── services/ +│ ├── clustering_service.py +│ └── ideas_service.py +│ +├── billing/ # Billing business logic +│ ├── models.py # Credits, Transactions +│ └── services/ +│ └── credit_service.py +│ +└── automation/ # Automation business logic + ├── models.py + └── services/ + └── automation_service.py +``` + +### Services + +#### ContentGenerationService +**Purpose**: Unified content generation logic + +**Key Functions**: +- `generate_content(task, account)` - Generate content for a task +- `regenerate_content(content_id, account)` - Regenerate existing content +- `batch_generate_content(task_ids, account)` - Generate multiple content pieces + +**Workflow**: +1. Check credits via `CreditService.check_credits()` +2. Generate content using AI engine +3. Save content to database +4. Deduct credits via `CreditService.deduct_credits()` +5. Return generated content + +#### ClusteringService +**Purpose**: Keyword clustering using AI + +**Key Functions**: +- `cluster_keywords(keyword_ids, account)` - Cluster keywords into groups +- `update_cluster(cluster_id, keyword_ids, account)` - Update cluster membership + +**Workflow**: +1. Check credits for clustering operation +2. Call AI function to generate clusters +3. Create Cluster records +4. Associate keywords with clusters +5. Deduct credits and log usage + +#### IdeasService +**Purpose**: Generate content ideas from clusters + +**Key Functions**: +- `generate_ideas(cluster_ids, account)` - Generate ideas for clusters +- `regenerate_ideas(cluster_id, account)` - Regenerate ideas for a cluster + +**Workflow**: +1. Check credits for idea generation +2. Call AI function with cluster context +3. Create ContentIdeas records +4. Associate ideas with clusters +5. Deduct credits and log usage + +### Model Migrations + +**Content Models**: Moved from `modules/writer/models.py` to `business/content/models.py` +- `Content` model +- `Tasks` model +- `Images` model + +**Planning Models**: Moved from `modules/planner/models.py` to `business/planning/models.py` +- `Keywords` model +- `Clusters` model +- `ContentIdeas` model + +**Billing Models**: Moved from `modules/billing/models.py` to `business/billing/models.py` +- `CreditTransaction` model +- `CreditUsageLog` model + +**Migration Strategy**: Models kept same `app_label` to avoid data migration complexity. Only import paths changed. + +### ViewSet Refactoring + +**Before**: ViewSets contained 50-100+ lines of business logic + +**After**: ViewSets delegate to services: +```python +# Example: ClusterViewSet +@action(detail=False, methods=['post']) +def auto_generate_ideas(self, request): + cluster_ids = request.data.get('cluster_ids') + account = request.account + + # Delegate to service + ideas = self.ideas_service.generate_ideas(cluster_ids, account) + + # Serialize and return + serializer = ContentIdeasSerializer(ideas, many=True) + return Response(serializer.data) +``` + +### Workflows + +#### Content Generation Workflow +1. User creates task in Writer module +2. User triggers content generation +3. ViewSet receives request, delegates to `ContentGenerationService` +4. Service checks credits, generates content, deducts credits +5. ViewSet serializes and returns response + +#### Keyword Clustering Workflow +1. User selects keywords in Planner module +2. User triggers clustering +3. ViewSet delegates to `ClusteringService` +4. Service checks credits, calls AI, creates clusters +5. ViewSet returns cluster data + +--- + +## PHASE 2: AUTOMATION SYSTEM + +**Status**: ✅ **IMPLEMENTED** + +### Purpose + +Implement automation rules and scheduled tasks to enable users to automate repetitive workflows. + +### Key Objectives + +- Create AutomationRule and ScheduledTask models +- Build AutomationService with rule execution engine +- Implement Celery Beat scheduled tasks +- Create automation API endpoints +- Build automation UI (Dashboard, Rules, History) + +### Models + +#### AutomationRule Model +**Purpose**: Store automation rule definitions + +**Key Fields**: +- `name` - Rule name +- `description` - Rule description +- `trigger` - Trigger type (schedule, keyword_added, cluster_created, idea_created, content_generated, task_created) +- `conditions` - JSON field for condition evaluation +- `actions` - JSON field for actions to execute +- `schedule` - JSON field for cron-like schedule (for scheduled triggers) +- `is_active` - Whether rule is active +- `max_executions_per_day` - Daily execution limit +- `credit_limit_per_execution` - Credit limit per execution +- `last_executed_at` - Last execution timestamp +- `execution_count_today` - Daily execution counter + +**Workflow**: Rules evaluate conditions, execute actions when triggered, respect execution limits and credit constraints. + +#### ScheduledTask Model +**Purpose**: Track scheduled task executions + +**Key Fields**: +- `automation_rule` - ForeignKey to AutomationRule +- `scheduled_at` - Scheduled execution time +- `executed_at` - Actual execution time +- `status` - Task status (pending, running, completed, failed, skipped) +- `result` - JSON field for execution results +- `error_message` - Error message if failed +- `credits_used` - Credits consumed + +**Workflow**: Tasks scheduled by Celery Beat, executed by AutomationService, results stored for audit trail. + +### Services + +#### AutomationService +**Purpose**: Execute automation rules with condition evaluation and action execution + +**Key Functions**: +- `execute_rule(rule, context=None)` - Execute an automation rule +- `evaluate_conditions(rule, context)` - Evaluate rule conditions +- `execute_actions(rule, context)` - Execute rule actions +- `check_execution_limits(rule)` - Validate execution limits + +**Workflow**: +1. Check if rule is active +2. Check execution limits (daily limit, credit limit) +3. Evaluate conditions against context +4. If conditions met, execute actions +5. Update rule tracking (last_executed_at, execution_count_today) +6. Create ScheduledTask record +7. Return execution results + +#### RuleEngine +**Purpose**: Orchestrate rule execution + +**Key Functions**: +- `execute_rule(rule, context)` - Orchestrate full rule execution +- `validate_rule(rule)` - Validate rule configuration + +#### ConditionEvaluator +**Purpose**: Evaluate rule conditions + +**Supported Operators**: +- `eq` - Equals +- `ne` - Not equals +- `gt` - Greater than +- `gte` - Greater than or equal +- `lt` - Less than +- `lte` - Less than or equal +- `in` - In list +- `contains` - Contains substring + +**Example Condition**: +```json +{ + "field": "status", + "operator": "eq", + "value": "draft" +} +``` + +#### ActionExecutor +**Purpose**: Execute rule actions + +**Supported Actions**: +- `generate_ideas` - Generate content ideas from clusters +- `generate_content` - Generate content from tasks +- `cluster_keywords` - Cluster keywords +- `optimize_content` - Optimize content + +**Example Action**: +```json +{ + "type": "generate_ideas", + "params": { + "cluster_ids": [1, 2, 3] + } +} +``` + +### Celery Beat Tasks + +#### Scheduled Automation Task +**Purpose**: Execute scheduled automation rules + +**Schedule**: Every 15 minutes + +**Workflow**: +1. Query all active rules with `trigger='schedule'` +2. For each rule, check if schedule matches current time +3. If matches, execute rule via `AutomationService` +4. Log execution in ScheduledTask + +#### Monthly Credit Replenishment Task +**Purpose**: Add monthly credits to all active accounts + +**Schedule**: 1st day of month at midnight + +**Workflow**: +1. Query all active accounts +2. For each account, add `plan.monthly_credits` to balance +3. Log replenishment in `CreditUsageLog` with `operation_type='monthly_replenishment'` + +### Database Migrations + +**Migration**: `automation.0001_initial` +- **Purpose**: Create AutomationRule and ScheduledTask tables +- **Status**: ✅ Applied +- **Tables Created**: `igny8_automation_rules`, `igny8_scheduled_tasks` + +### API Endpoints + +**AutomationRuleViewSet**: +- `GET /api/v1/automation/rules/` - List rules +- `POST /api/v1/automation/rules/` - Create rule +- `GET /api/v1/automation/rules/{id}/` - Get rule +- `PUT /api/v1/automation/rules/{id}/` - Update rule +- `DELETE /api/v1/automation/rules/{id}/` - Delete rule +- `POST /api/v1/automation/rules/{id}/execute/` - Manually execute rule +- `POST /api/v1/automation/rules/{id}/test/` - Test rule conditions + +**ScheduledTaskViewSet**: +- `GET /api/v1/automation/scheduled-tasks/` - List scheduled tasks +- `GET /api/v1/automation/scheduled-tasks/{id}/` - Get scheduled task + +### Frontend Implementation + +**Automation Dashboard**: +- Active rules count +- Recent executions +- Success/failure rates +- Credit usage from automation +- Quick actions (create rule, view history) + +**Rules Management**: +- List all rules +- Create new rule (wizard) +- Edit existing rule +- Enable/disable rule +- Delete rule +- Test rule +- Manual execution + +**Scheduled Tasks History**: +- List scheduled tasks +- Filter by status, rule, date +- View execution results +- View error messages +- Retry failed tasks + +--- + +## PHASE 3: SITE BUILDER + +**Status**: ✅ **IMPLEMENTED** + +### Purpose + +Build Site Builder for creating sites via wizard with AI-powered structure generation, preview canvas, and file management. + +### Key Objectives + +- Create Site Builder wizard for site creation +- Generate site structure using AI +- Build preview canvas for site editing +- Create shared component library +- Support multiple layouts and templates +- Enable file management for site assets + +### Models + +#### SiteBlueprint Model +**Purpose**: Store site structure definitions + +**Key Fields**: +- `name` - Site name +- `description` - Site description +- `config_json` - Wizard configuration (business_type, style, objectives) +- `structure_json` - AI-generated structure (pages, layout, theme) +- `status` - Status (draft, generating, ready, deployed) +- `hosting_type` - Hosting platform (igny8_sites, wordpress, shopify, multi) +- `version` - Blueprint version +- `deployed_version` - Currently deployed version + +**Workflow**: Blueprint created via wizard, structure generated by AI, pages created from structure, content generated for pages. + +#### PageBlueprint Model +**Purpose**: Store page definitions within a site + +**Key Fields**: +- `site_blueprint` - ForeignKey to SiteBlueprint +- `slug` - Page slug +- `title` - Page title +- `type` - Page type (home, about, services, products, blog, contact, custom) +- `blocks_json` - Page content blocks +- `status` - Status (draft, generating, ready) +- `order` - Page order in navigation + +**Workflow**: Pages created from AI-generated structure, content generated via Writer module, pages rendered in preview. + +### Services + +#### StructureGenerationService +**Purpose**: Generate site structure using AI + +**Key Functions**: +- `generate_structure(site_blueprint, business_brief, objectives, style)` - Generate site structure +- `_create_page_blueprints(site_blueprint, structure)` - Create PageBlueprint records from structure + +**Workflow**: +1. Check credits for structure generation (50 credits) +2. Update blueprint status to 'generating' +3. Call AI function `GenerateSiteStructureFunction` +4. Parse AI response JSON +5. Update blueprint with structure JSON +6. Create/update/delete PageBlueprint records based on structure +7. Update blueprint status to 'ready' +8. Deduct credits + +#### PageGenerationService +**Purpose**: Generate page content from blueprints + +**Key Functions**: +- `generate_page_content(page_blueprint, account)` - Generate content for a page +- `regenerate_page(page_blueprint, account)` - Regenerate page content + +**Workflow**: +1. Check credits for page generation (20 credits per page) +2. Create Writer task from page blueprint +3. Use ContentGenerationService to generate content +4. Update page blueprint status +5. Deduct credits + +#### SiteBuilderFileService +**Purpose**: Manage site files and assets + +**Key Functions**: +- `get_user_accessible_sites(user)` - Get sites user can access +- `check_file_access(user, site_id)` - Validate user access to site files +- `upload_file(user, site_id, file, folder='images')` - Upload file to site assets +- `delete_file(user, site_id, file_path)` - Delete file from site assets +- `list_files(user, site_id, folder='images')` - List files in site folder +- `check_storage_quota(site_id, file_size)` - Validate storage quota + +**File Structure**: +``` +/data/app/sites-data/clients/{site_id}/v{version}/ +├── site.json # Site definition +├── pages/ # Page definitions +│ ├── home.json +│ ├── about.json +│ └── ... +└── assets/ # User-managed files + ├── images/ + ├── documents/ + └── media/ +``` + +**Access Control**: +- Owner/Admin: Full access to all account sites +- Editor: Access to granted sites (via SiteUserAccess) +- Viewer: Read-only access to granted sites + +### AI Functions + +#### GenerateSiteStructureFunction +**Purpose**: Generate site structure from business brief + +**Operation Type**: `site_structure_generation` +**Credit Cost**: 50 credits + +**Workflow**: +1. Build prompt from business brief, objectives, style preferences +2. Call AI with prompt +3. Parse JSON response +4. Validate structure format +5. Return structure JSON + +**Structure Format**: +```json +{ + "pages": [ + { + "slug": "home", + "title": "Home", + "type": "home", + "blocks": [...] + } + ], + "layout": "default", + "theme": {...} +} +``` + +### Database Migrations + +**Migration**: `site_building.0001_initial` +- **Purpose**: Create SiteBlueprint and PageBlueprint tables +- **Status**: ✅ Applied +- **Tables Created**: `igny8_site_blueprints`, `igny8_page_blueprints` +- **Dependencies**: `igny8_core_auth.0014_remove_plan_operation_limits_phase0`, `writer.0009_add_content_site_source_fields` + +### API Endpoints + +**SiteBuilderViewSet**: +- `GET /api/v1/site-builder/blueprints/` - List site blueprints +- `POST /api/v1/site-builder/blueprints/` - Create site blueprint +- `GET /api/v1/site-builder/blueprints/{id}/` - Get site blueprint +- `PUT /api/v1/site-builder/blueprints/{id}/` - Update site blueprint +- `DELETE /api/v1/site-builder/blueprints/{id}/` - Delete site blueprint +- `POST /api/v1/site-builder/blueprints/{id}/generate_structure/` - Generate site structure + +**PageBlueprintViewSet**: +- `GET /api/v1/site-builder/pages/` - List page blueprints +- `POST /api/v1/site-builder/pages/` - Create page blueprint +- `GET /api/v1/site-builder/pages/{id}/` - Get page blueprint +- `PUT /api/v1/site-builder/pages/{id}/` - Update page blueprint +- `DELETE /api/v1/site-builder/pages/{id}/` - Delete page blueprint +- `POST /api/v1/site-builder/pages/{id}/generate_content/` - Generate page content +- `POST /api/v1/site-builder/pages/{id}/regenerate/` - Regenerate page content + +**SiteAssetView**: +- `GET /api/v1/site-builder/assets/` - List files +- `POST /api/v1/site-builder/assets/` - Upload file +- `DELETE /api/v1/site-builder/assets/` - Delete file + +### Frontend Implementation + +**Site Builder Container** (`site-builder/`): +- Standalone Vite + React + TypeScript application +- Docker container on port 8025:5175 +- Routed to `builder.igny8.com` via Caddy reverse proxy + +**Wizard Steps**: +- Step 1: Business Details (Business type, industry, audience) +- Step 2: Business Brief (Description textarea) +- Step 3: Objectives (Multiple objectives with add/remove) +- Step 4: Style Preferences (Palette, typography, personality) + +**Preview Canvas**: +- Live preview of generated site structure +- Page navigation +- Block rendering + +**Site Dashboard**: +- List all site blueprints +- Create new blueprint +- View blueprint details +- Generate structure +- Deploy site + +**Shared Component Library** (`frontend/src/components/shared/`): +- **Blocks**: HeroBlock, FeatureGridBlock, StatsPanel +- **Layouts**: DefaultLayout, MinimalLayout +- **Templates**: MarketingTemplate, LandingTemplate + +**State Management**: +- `builderStore.ts` - Wizard state (currentStep, wizardData, activeBlueprint) +- `siteDefinitionStore.ts` - Site preview state (siteStructure, pages, activePageSlug) + +--- + +## PHASE 4: LINKER & OPTIMIZER + +**Status**: ✅ **IMPLEMENTED** + +### Purpose + +Add internal linking and content optimization as post-processing stages with multiple entry points for different content sources. + +### Key Objectives + +- Add internal linking to content +- Add content optimization +- Support multiple entry points (Writer, WordPress Sync, 3rd Party, Manual) +- Create content pipeline service +- Build UI for linker and optimizer + +### Content Model Extensions + +**Purpose**: Track content source and sync status + +**Fields Added to Content Model**: +- `source` - Content source (igny8, wordpress, shopify, custom) +- `sync_status` - Sync status (native, imported, synced) +- `external_id` - External platform ID +- `external_url` - External platform URL +- `sync_metadata` - Platform-specific sync metadata +- `internal_links` - JSON field for internal links added by linker +- `linker_version` - Version of linker processing +- `optimizer_version` - Version of optimizer processing +- `optimization_scores` - JSON field for optimization scores (SEO, readability, engagement) + +**Workflow**: Content source tracked from creation, sync status updated during import/sync, linking and optimization versions incremented after processing. + +### Models + +#### OptimizationTask Model +**Purpose**: Track optimization operations + +**Key Fields**: +- `content` - ForeignKey to Content +- `scores_before` - Optimization scores before optimization +- `scores_after` - Optimization scores after optimization +- `html_before` - HTML content before optimization +- `html_after` - HTML content after optimization +- `status` - Task status (pending, running, completed, failed) +- `credits_used` - Credits used for optimization +- `metadata` - Additional metadata + +**Workflow**: Task created before optimization, scores calculated before/after, HTML stored for comparison, credits logged. + +### Services + +#### LinkerService +**Purpose**: Add internal links to content + +**Key Functions**: +- `process(content_id)` - Process content for linking +- `batch_process(content_ids)` - Process multiple content items + +**Workflow**: +1. Check credits for linking (8 credits per content) +2. Find link candidates using CandidateEngine +3. Inject links using InjectionEngine +4. Update content with links and increment linker_version +5. Deduct credits and log usage + +#### CandidateEngine +**Purpose**: Find relevant content for linking + +**Key Functions**: +- `find_candidates(content)` - Find link candidates based on content relevance +- `_find_relevant_content(content)` - Query relevant content +- `_score_candidates(content, candidates)` - Score candidates by relevance + +**Workflow**: +1. Extract keywords from content +2. Query content with similar keywords +3. Score candidates by relevance (keyword overlap, semantic similarity) +4. Return top candidates + +#### InjectionEngine +**Purpose**: Inject links into HTML content + +**Key Functions**: +- `inject_links(content, candidates)` - Inject links into content HTML +- `_inject_link_into_html(html, link_data)` - Inject single link + +**Workflow**: +1. Parse HTML content +2. Find anchor text candidates +3. Inject links at appropriate positions +4. Respect max links per content +5. Prevent duplicate links +6. Return updated HTML + +#### OptimizerService +**Purpose**: Optimize content with multiple entry points + +**Key Functions**: +- `optimize_from_writer(content_id)` - Entry Point 1: Writer → Optimizer +- `optimize_from_wordpress_sync(content_id)` - Entry Point 2: WordPress Sync → Optimizer +- `optimize_from_external_sync(content_id)` - Entry Point 3: External Sync → Optimizer +- `optimize_manual(content_id)` - Entry Point 4: Manual Selection → Optimizer +- `optimize(content)` - Unified optimization logic + +**Workflow**: +1. Check credits for optimization (1 credit per 200 words) +2. Analyze content before optimization using ContentAnalyzer +3. Call AI function `OptimizeContentFunction` to optimize content +4. Analyze optimized content +5. Create OptimizationTask record +6. Update content with optimized HTML and scores +7. Increment optimizer_version +8. Deduct credits and log usage + +#### ContentAnalyzer +**Purpose**: Analyze content quality + +**Key Functions**: +- `analyze(content)` - Analyze content and return scores +- `_calculate_seo_score(content)` - Calculate SEO score +- `_calculate_readability_score(content)` - Calculate readability score +- `_calculate_engagement_score(content)` - Calculate engagement score + +**Scoring**: +- SEO Score: Keyword density, meta tags, heading structure +- Readability Score: Sentence length, paragraph length, Flesch reading ease +- Engagement Score: Call-to-action presence, internal links, formatting +- Overall Score: Weighted average of all scores + +#### ContentPipelineService +**Purpose**: Orchestrate content processing pipeline + +**Key Functions**: +- `process_writer_content(content_id, stages=['linking', 'optimization'])` - Full pipeline for Writer content +- `process_synced_content(content_id, stages=['optimization'])` - Optimization-only for synced content + +**Pipeline Workflow**: +1. Writer Content → Linker → Optimizer → Publish +2. Synced Content → Optimizer → Publish + +**Content States**: +- `draft` - Generated, not processed +- `linked` - Links added, ready for optimization +- `optimized` - Optimized, ready for review +- `review` - Ready for publishing +- `published` - Published to destination(s) + +### AI Functions + +#### OptimizeContentFunction +**Purpose**: Optimize content for SEO, readability, and engagement + +**Operation Type**: `optimize_content` +**Credit Cost**: 1 credit per 200 words + +**Workflow**: +1. Build prompt with content, target keywords, optimization goals +2. Call AI with prompt +3. Parse optimized HTML from response +4. Return optimized content + +**Optimization Goals**: +- SEO: Keyword optimization, meta tags, heading structure +- Readability: Sentence structure, paragraph length, clarity +- Engagement: Call-to-actions, formatting, internal links + +### Database Migrations + +**Migration**: `writer.0009_add_content_site_source_fields` +- **Purpose**: Add Phase 4 fields to Content model +- **Status**: ✅ Applied +- **Fields Added**: source, sync_status, external_id, external_url, sync_metadata, internal_links, linker_version, optimizer_version, optimization_scores +- **Indexes Added**: source, sync_status, source+sync_status + +**Migration**: `optimization.0001_initial` +- **Purpose**: Create OptimizationTask table +- **Status**: ✅ Applied +- **Table Created**: `igny8_optimization_tasks` +- **Dependencies**: `igny8_core_auth.0013_remove_ai_cost_per_request`, `writer.0009_add_content_site_source_fields` + +### API Endpoints + +**LinkerViewSet**: +- `POST /api/v1/linker/process/` - Process content for linking +- `POST /api/v1/linker/batch_process/` - Process multiple content items + +**OptimizerViewSet**: +- `POST /api/v1/optimizer/optimize/` - Optimize content (auto-detects entry point) +- `POST /api/v1/optimizer/batch_optimize/` - Batch optimize multiple content items +- `POST /api/v1/optimizer/analyze/` - Analyze content without optimizing + +**Throttle Rates**: +- Linker: 30 requests per minute +- Optimizer: 10 requests per minute + +### Frontend Implementation + +**Linker Pages**: +- Dashboard - Linker overview with stats and quick actions +- ContentList - Content list with link processing actions + +**Optimizer Pages**: +- Dashboard - Optimizer overview with stats and quick actions +- ContentSelector - Content selector with batch optimization and filters +- AnalysisPreview - Analysis preview page for content scores + +**Shared Components**: +- SourceBadge - Displays content source (igny8, wordpress, shopify, custom) +- SyncStatusBadge - Displays sync status (native, imported, synced) +- ContentFilter - Filters content by source and sync status +- LinkResults - Displays linking results with links added count +- OptimizationScores - Displays optimization scores (SEO, readability, engagement, overall) +- ScoreComparison - Compares before/after optimization scores + +**Writer Integration**: +- Source and sync status columns in Content table +- Source and sync status filters +- "Optimize" action button +- "Send to Optimizer" action + +--- + +## CROSS-PHASE INTEGRATION + +### Service Dependencies + +**Phase 1 Services Used by Phase 2-4**: +- `CreditService` - Used by all phases for credit checks +- `ContentGenerationService` - Used by Phase 3 for page generation +- `ClusteringService` - Used by Phase 2 automation actions +- `IdeasService` - Used by Phase 2 automation actions + +**Phase 2 Integration**: +- Automation rules can trigger Phase 1 services (clustering, ideas, content generation) +- Automation can trigger Phase 3 site structure generation +- Automation can trigger Phase 4 linking and optimization + +**Phase 3 Integration**: +- Site Builder uses Phase 1 ContentGenerationService for page content +- Site Builder uses Phase 0 CreditService for credit checks +- Site pages stored as Content records (Phase 1) + +**Phase 4 Integration**: +- Linker and Optimizer work on all Content records regardless of source +- ContentPipelineService orchestrates Writer → Linker → Optimizer pipeline +- Optimizer can optimize Site Builder page content + +### Workflow Integration + +**Complete Content Workflow**: +1. User creates content in Writer (Phase 1) +2. Content flows to Linker (Phase 4) +3. Linked content flows to Optimizer (Phase 4) +4. Optimized content ready for publishing +5. Automation rules can trigger any step (Phase 2) + +**Site Builder Workflow**: +1. User creates site blueprint via wizard (Phase 3) +2. AI generates site structure (Phase 3) +3. Pages created from structure (Phase 3) +4. Page content generated via Writer (Phase 1) +5. Pages can be optimized via Optimizer (Phase 4) + +--- + +## DATABASE MIGRATIONS SUMMARY + +### Phase 0 Migrations + +**Migration**: `igny8_core_auth.0014_remove_plan_operation_limits_phase0` +- **Status**: ✅ Applied +- **Purpose**: Remove plan limit fields +- **Risk**: LOW + +### Phase 1 Migrations + +**Status**: No new migrations required +- Models moved but kept same `app_label` +- Only import paths changed + +### Phase 2 Migrations + +**Migration**: `automation.0001_initial` +- **Status**: ✅ Applied +- **Purpose**: Create AutomationRule and ScheduledTask tables +- **Tables**: `igny8_automation_rules`, `igny8_scheduled_tasks` + +### Phase 3 Migrations + +**Migration**: `site_building.0001_initial` +- **Status**: ✅ Applied +- **Purpose**: Create SiteBlueprint and PageBlueprint tables +- **Tables**: `igny8_site_blueprints`, `igny8_page_blueprints` +- **Dependencies**: `igny8_core_auth.0014_remove_plan_operation_limits_phase0`, `writer.0009_add_content_site_source_fields` + +### Phase 4 Migrations + +**Migration**: `writer.0009_add_content_site_source_fields` +- **Status**: ✅ Applied +- **Purpose**: Add Phase 4 fields to Content model +- **Fields**: source, sync_status, external_id, external_url, sync_metadata, internal_links, linker_version, optimizer_version, optimization_scores + +**Migration**: `optimization.0001_initial` +- **Status**: ✅ Applied +- **Purpose**: Create OptimizationTask table +- **Table**: `igny8_optimization_tasks` +- **Dependencies**: `igny8_core_auth.0013_remove_ai_cost_per_request`, `writer.0009_add_content_site_source_fields` + +### Migration Dependencies + +``` +Phase 0: igny8_core_auth.0014_remove_plan_operation_limits_phase0 + ↓ +Phase 3: site_building.0001_initial (depends on Phase 0) + ↓ +Phase 4: optimization.0001_initial (depends on writer.0009, which is applied) +``` + +--- + +## TESTING STRATEGY + +### Phase 0 Testing + +**Credit System Tests**: +- All existing features work with credit checks +- Credit deduction happens correctly +- Insufficient credits show clear error +- Usage logging tracks all operations +- Frontend shows credit balance, not limits + +**Module Settings Tests**: +- Disabled modules don't appear in sidebar +- Disabled modules don't load routes +- Disabled modules return 403/404 appropriately +- Module settings persist correctly + +### Phase 1 Testing + +**Service Tests**: +- Services can be tested independently +- Services handle errors correctly +- Services check credits before operations +- Services deduct credits after operations + +**API Compatibility Tests**: +- All existing API endpoints work identically +- Response formats unchanged +- No breaking changes for frontend +- All ViewSet actions work correctly + +### Phase 2 Testing + +**Automation Service Tests**: +- Rules execute correctly +- Conditions evaluate correctly +- Actions execute correctly +- Execution limits enforced +- Credit checks work + +**Scheduled Tasks Tests**: +- Scheduled tasks run on time +- Credit replenishment works monthly +- Task status tracking works + +### Phase 3 Testing + +**Site Builder Tests**: +- Site Builder wizard works end-to-end +- Structure generation creates valid blueprints +- Preview renders correctly +- Page generation reuses existing content service +- File management works correctly + +**Component Library Tests**: +- Components render correctly +- Components work in Site Builder +- Components work in Sites Renderer + +### Phase 4 Testing + +**Linker Tests**: +- Linker finds appropriate link candidates +- Links inject correctly into content +- Credit deduction works +- Batch processing works + +**Optimizer Tests**: +- Optimizer works from Writer entry point +- Optimizer works from WordPress sync entry point +- Optimizer works from 3rd party sync entry point +- Optimizer works from manual selection +- Content source tracking works +- Pipeline orchestrates correctly + +**Backend Test Coverage**: +- 10 test files for Phase 4 +- 70+ test cases +- All services tested +- All API endpoints tested + +**Frontend Test Coverage**: +- 7 test files for Phase 4 +- 30+ test cases +- All components tested +- All pages tested + +--- + +## SUCCESS CRITERIA + +### Phase 0 Success Criteria + +✅ All existing features work with credit checks +✅ Credit deduction happens correctly for all operations +✅ Insufficient credits show clear error messages +✅ Usage logging tracks all operations +✅ Frontend shows credit balance, not limits +✅ Module settings enable/disable modules correctly +✅ Disabled modules don't appear in UI +✅ No breaking changes for existing users + +### Phase 1 Success Criteria + +✅ Services are testable independently +✅ Business logic extracted from ViewSets +✅ ViewSets are thin wrappers that delegate to services +✅ All models moved to business layer +✅ All imports updated correctly +✅ Services handle credit checks and business rules + +### Phase 2 Success Criteria + +✅ Automation rules execute correctly +✅ Scheduled tasks run on time +✅ Credit replenishment works monthly +✅ UI shows automation status +✅ Rules can be created, edited, deleted +✅ Execution history is tracked +✅ All automation respects credit limits + +### Phase 3 Success Criteria + +✅ Site Builder wizard works end-to-end +✅ Structure generation creates valid blueprints +✅ Preview renders correctly +✅ Page generation reuses existing content service +✅ File management works correctly +✅ Shared components work across all apps +✅ Multiple layouts supported + +### Phase 4 Success Criteria + +✅ Writer → Linker handover works +✅ Optimizer works from all entry points +✅ Content source tracking works +✅ Pipeline orchestrates correctly +✅ UI shows content sources and filters +✅ API endpoints functional and tested +✅ AI function integrated and working +✅ Credit deduction working at all stages +✅ Frontend UI complete with all dashboards and selectors +✅ Writer integration complete with badges and filters +✅ Navigation and routing complete +✅ Backend tests complete (10 test files) +✅ Frontend tests complete (7 test files) + +--- + +**END OF PHASES 0-4 DOCUMENTATION** + diff --git a/docs/planning/phases/PHASE-0-FOUNDATION-CREDIT-SYSTEM.md b/docs/planning/phases/PHASE-0-FOUNDATION-CREDIT-SYSTEM.md deleted file mode 100644 index dc296804..00000000 --- a/docs/planning/phases/PHASE-0-FOUNDATION-CREDIT-SYSTEM.md +++ /dev/null @@ -1,524 +0,0 @@ -# PHASE 0: FOUNDATION & CREDIT SYSTEM -**Detailed Implementation Plan** - -**Goal**: Migrate to credit-only model while preserving all existing functionality. - -**Timeline**: 1-2 weeks -**Priority**: HIGH -**Dependencies**: None - ---- - -## TABLE OF CONTENTS - -1. [Overview](#overview) -2. [Module Settings System](#module-settings-system) -3. [Credit System Updates](#credit-system-updates) -4. [Operational Limits](#operational-limits) -5. [Database Migrations](#database-migrations) -6. [Testing & Validation](#testing--validation) -7. [Implementation Checklist](#implementation-checklist) - ---- - -## OVERVIEW - -### Objectives -- ✅ Migrate from plan-based limits to credit-only system -- ✅ Implement module enable/disable functionality -- ✅ Add credit cost tracking for all operations -- ✅ Preserve all existing functionality -- ✅ Update frontend to show credits instead of limits - -### Key Principles -- **Backward Compatibility**: All existing APIs continue working -- **No Breaking Changes**: Frontend continues working without changes -- **Gradual Migration**: Add credit checks without removing existing code initially -- **Credit-Only Model**: Remove all plan limit fields, keep only credits - ---- - -## MODULE SETTINGS SYSTEM - -### 0.0 Module Settings System (Enable/Disable Modules) - -**Purpose**: Allow accounts to enable/disable modules per account. - -#### Backend Implementation - -| Task | File | Current State | Implementation | -|------|------|---------------|----------------| -| **Extend ModuleSettings Model** | `business/system/models.py` | EXISTING (ModuleSettings) | Add `enabled` boolean field per module | -| **Module Settings API** | `modules/system/views.py` | EXISTING | Extend ViewSet to handle enable/disable | -| **Module Settings Serializer** | `modules/system/serializers.py` | EXISTING | Add enabled field to serializer | - -**ModuleSettings Model Extension**: -```python -# business/system/models.py (or core/system/models.py if exists) -class ModuleSettings(AccountBaseModel): - # Existing fields... - - # NEW: Module enable/disable flags - planner_enabled = models.BooleanField(default=True) - writer_enabled = models.BooleanField(default=True) - thinker_enabled = models.BooleanField(default=True) - automation_enabled = models.BooleanField(default=True) - site_builder_enabled = models.BooleanField(default=True) - linker_enabled = models.BooleanField(default=True) - optimizer_enabled = models.BooleanField(default=True) - publisher_enabled = models.BooleanField(default=True) -``` - -**Modules to Control**: -- Planner -- Writer -- Thinker -- Automation -- Site Builder (NEW) -- Linker (NEW) -- Optimizer (NEW) -- Publisher (NEW) - -#### Frontend Implementation - -| Task | File | Current State | Implementation | -|------|------|---------------|----------------| -| **Module Settings UI** | `frontend/src/pages/Settings/Modules.tsx` | EXISTING (placeholder) | Implement toggle UI for each module | -| **Frontend Module Loader** | `frontend/src/config/modules.config.ts` | NEW | Define module config with enabled checks | -| **Route Guard** | `frontend/src/components/common/ModuleGuard.tsx` | NEW | Component to check module status before rendering | -| **Sidebar Filter** | `frontend/src/layout/AppSidebar.tsx` | EXISTING | Filter out disabled modules from sidebar | - -**Module Enable/Disable Logic**: -- Each module has `enabled` flag in ModuleSettings -- Frontend checks module status before loading routes -- Disabled modules don't appear in sidebar -- Disabled modules don't load code (lazy loading check) - -**Module Config Example**: -```typescript -// frontend/src/config/modules.config.ts -export const MODULES = { - planner: { - name: 'Planner', - route: '/planner', - enabled: true, // Checked from API - }, - writer: { - name: 'Writer', - route: '/writer', - enabled: true, - }, - // ... other modules -}; -``` - -**Route Guard Example**: -```typescript -// frontend/src/components/common/ModuleGuard.tsx -const ModuleGuard = ({ module, children }) => { - const { moduleSettings } = useSettingsStore(); - const isEnabled = moduleSettings[module]?.enabled ?? true; - - if (!isEnabled) { - return ; - } - - return children; -}; -``` - ---- - -## CREDIT SYSTEM UPDATES - -### 0.1 Credit System Updates - -**Purpose**: Migrate from plan-based limits to credit-only system. - -#### Plan Model Updates - -| Task | File | Current State | Implementation | -|------|------|---------------|----------------| -| **Remove Plan Limit Fields** | `core/auth/models.py` | EXISTING | Remove all limit fields, add migration | -| **Update Plan Model** | `core/auth/models.py` | EXISTING | Keep only `monthly_credits`, `support_level`, `billing_cycle`, `price` | - -**Plan Model (Simplified)**: -```python -# core/auth/models.py -class Plan(models.Model): - name = models.CharField(max_length=255) - monthly_credits = models.IntegerField(default=0) # KEEP - support_level = models.CharField(max_length=50) # KEEP - billing_cycle = models.CharField(max_length=20) # KEEP - price = models.DecimalField(max_digits=10, decimal_places=2) # KEEP - features = models.JSONField(default=dict) # KEEP (for future use) - - # REMOVE: All limit fields - # - max_keywords - # - max_clusters - # - max_content_ideas - # - daily_content_tasks - # - monthly_word_count_limit - # - daily_image_generation_limit - # - monthly_image_count - # - etc. -``` - -**Migration Strategy**: -1. Create migration to add defaults for removed fields (if needed) -2. Create migration to remove limit fields -3. Ensure existing accounts have credit balances set - -#### Credit Cost Constants - -| Task | File | Current State | Implementation | -|------|------|---------------|----------------| -| **Add Credit Costs** | `business/billing/constants.py` | NEW | Define credit costs per operation | - -**Credit Cost Constants**: -```python -# business/billing/constants.py -CREDIT_COSTS = { - 'clustering': 10, # Per clustering request - 'idea_generation': 15, # Per cluster → ideas request - 'content_generation': 1, # Per 100 words - 'image_prompt_extraction': 2, # Per content piece - 'image_generation': 5, # Per image - 'linking': 8, # Per content piece (NEW) - 'optimization': 1, # Per 200 words (NEW) - 'site_structure_generation': 50, # Per site blueprint (NEW) - 'site_page_generation': 20, # Per page (NEW) -} -``` - -#### CreditService Updates - -| Task | File | Current State | Implementation | -|------|------|---------------|----------------| -| **Update CreditService** | `business/billing/services/credit_service.py` | EXISTING | Add credit cost constants, update methods | - -**CreditService Methods**: -```python -# business/billing/services/credit_service.py -class CreditService: - def check_credits(self, account, operation_type, amount=None): - """Check if account has sufficient credits""" - required = self.get_credit_cost(operation_type, amount) - if account.credits < required: - raise InsufficientCreditsError(f"Need {required} credits, have {account.credits}") - return True - - def deduct_credits(self, account, operation_type, amount=None): - """Deduct credits after operation""" - cost = self.get_credit_cost(operation_type, amount) - account.credits -= cost - account.save() - # Log usage - CreditUsageLog.objects.create(...) - - def get_credit_cost(self, operation_type, amount=None): - """Get credit cost for operation""" - base_cost = CREDIT_COSTS.get(operation_type, 0) - if operation_type == 'content_generation' and amount: - return base_cost * (amount / 100) # Per 100 words - if operation_type == 'optimization' and amount: - return base_cost * (amount / 200) # Per 200 words - return base_cost -``` - -#### AI Engine Updates - -| Task | File | Current State | Implementation | -|------|------|---------------|----------------| -| **Update AI Engine** | `infrastructure/ai/engine.py` | EXISTING | Check credits before AI calls | - -**AI Engine Credit Check**: -```python -# infrastructure/ai/engine.py -class AIEngine: - def execute(self, function, payload, account): - # Check credits BEFORE AI call - operation_type = function.get_operation_type() - estimated_cost = function.get_estimated_cost(payload) - - credit_service.check_credits(account, operation_type, estimated_cost) - - # Execute AI function - result = function.execute(payload) - - # Deduct credits AFTER successful execution - credit_service.deduct_credits(account, operation_type, actual_cost) - - return result -``` - -#### Content Generation Updates - -| Task | File | Current State | Implementation | -|------|------|---------------|----------------| -| **Update Content Generation** | `business/content/services/content_generation_service.py` | NEW (Phase 1) | Check credits before generation | - -**Content Generation Credit Check**: -```python -# business/content/services/content_generation_service.py -class ContentGenerationService: - def generate_content(self, task, account): - # Check credits before generation - estimated_words = task.estimated_word_count or 1000 - credit_service.check_credits(account, 'content_generation', estimated_words) - - # Generate content - content = self._generate(task) - - # Deduct credits after generation - actual_words = content.word_count - credit_service.deduct_credits(account, 'content_generation', actual_words) - - return content -``` - -#### Image Generation Updates - -| Task | File | Current State | Implementation | -|------|------|---------------|----------------| -| **Update Image Generation** | `infrastructure/ai/functions/generate_images.py` | EXISTING | Check credits before generation | - -**Image Generation Credit Check**: -```python -# infrastructure/ai/functions/generate_images.py -class GenerateImagesFunction(BaseAIFunction): - def execute(self, payload, account): - image_ids = payload['image_ids'] - - # Check credits before generation - credit_service.check_credits(account, 'image_generation', len(image_ids)) - - # Generate images - results = self._generate_images(image_ids) - - # Deduct credits after generation - credit_service.deduct_credits(account, 'image_generation', len(results)) - - return results -``` - -#### Remove Limit Checks - -| Task | File | Current State | Implementation | -|------|------|---------------|----------------| -| **Remove Limit Checks** | All services | EXISTING | Remove all plan limit validations | - -**Files to Update**: -- `modules/planner/views.py` - Remove keyword/cluster limit checks -- `modules/writer/views.py` - Remove task/content limit checks -- `infrastructure/ai/engine.py` - Remove plan limit checks -- All ViewSets - Remove limit validation - -**Before (Remove)**: -```python -# OLD: Check plan limits -if account.plan.max_keywords and keywords_count > account.plan.max_keywords: - raise ValidationError("Exceeds plan limit") -``` - -**After (Credit Only)**: -```python -# NEW: Check credits only -credit_service.check_credits(account, 'clustering', keyword_count) -``` - -#### Usage Logging Updates - -| Task | File | Current State | Implementation | -|------|------|---------------|----------------| -| **Update Usage Logging** | `business/billing/models.py` | EXISTING | Ensure all operations log credits | - -**CreditUsageLog Model**: -```python -# business/billing/models.py -class CreditUsageLog(AccountBaseModel): - account = models.ForeignKey(Account, on_delete=models.CASCADE) - operation_type = models.CharField(max_length=50) - credits_used = models.IntegerField() - related_object_type = models.CharField(max_length=50, blank=True) - related_object_id = models.IntegerField(null=True, blank=True) - metadata = models.JSONField(default=dict) - created_at = models.DateTimeField(auto_now_add=True) -``` - -#### Frontend Updates - -| Task | File | Current State | Implementation | -|------|------|---------------|----------------| -| **Update Frontend Limits UI** | `frontend/src/pages/Billing/` | EXISTING | Replace limits display with credit display | - -**Frontend Changes**: -- Remove plan limit displays -- Show credit balance prominently -- Show credit costs per operation -- Show usage history by operation type - ---- - -## OPERATIONAL LIMITS - -### 0.2 Operational Limits (Keep) - -**Purpose**: Technical constraints, not business limits. - -| Limit | Value | Location | Implementation | Reason | -|-------|-------|----------|----------------|--------| -| **Keywords per request** | 50 | `modules/planner/views.py` | Request validation | API payload size, processing time | -| **Images per request** | 6 | `modules/writer/views.py` | Request validation | Queue management (user sees as batch) | -| **Images per AI call** | 1 | `infrastructure/ai/functions/generate_images.py` | Internal | Image API limitation | - -**Note**: These are **NOT** business limits - they're technical constraints for request processing. - ---- - -## DATABASE MIGRATIONS - -### 0.3 Database Migrations - -| Migration | Purpose | Risk | Implementation | -|-----------|---------|------|----------------| -| **Remove limit fields from Plan** | Clean up unused fields | LOW - Add defaults first | Create migration to remove fields | -| **Add credit cost tracking** | Enhance CreditUsageLog | LOW - Additive only | Add fields to CreditUsageLog | -| **Monthly credit replenishment** | Celery Beat task | LOW - New feature | Add scheduled task | - -**Migration 1: Remove Plan Limit Fields**: -```python -# core/auth/migrations/XXXX_remove_plan_limits.py -class Migration(migrations.Migration): - operations = [ - migrations.RemoveField(model_name='plan', name='max_keywords'), - migrations.RemoveField(model_name='plan', name='max_clusters'), - # ... remove all limit fields - ] -``` - -**Migration 2: Add Credit Cost Tracking**: -```python -# business/billing/migrations/XXXX_add_credit_tracking.py -class Migration(migrations.Migration): - operations = [ - migrations.AddField( - model_name='creditusagelog', - name='related_object_type', - field=models.CharField(max_length=50, blank=True), - ), - migrations.AddField( - model_name='creditusagelog', - name='related_object_id', - field=models.IntegerField(null=True, blank=True), - ), - migrations.AddField( - model_name='creditusagelog', - name='metadata', - field=models.JSONField(default=dict), - ), - ] -``` - -**Migration 3: Monthly Credit Replenishment**: -- Add Celery Beat task (see Automation section) - ---- - -## TESTING & VALIDATION - -### 0.4 Testing - -**Test Cases**: - -1. **Credit System Tests**: - - ✅ All existing features work with credit checks - - ✅ Credit deduction happens correctly - - ✅ Insufficient credits show clear error - - ✅ Usage logging tracks all operations - - ✅ Frontend shows credit balance, not limits - -2. **Module Settings Tests**: - - ✅ Disabled modules don't appear in sidebar - - ✅ Disabled modules don't load routes - - ✅ Disabled modules return 403/404 appropriately - - ✅ Module settings persist correctly - -3. **Backward Compatibility Tests**: - - ✅ All existing API endpoints work - - ✅ All existing workflows function - - ✅ Frontend continues working - - ✅ No data loss during migration - -**Test Files to Create**: -- `backend/tests/test_credit_system.py` -- `backend/tests/test_module_settings.py` -- `frontend/src/__tests__/ModuleGuard.test.tsx` - ---- - -## IMPLEMENTATION CHECKLIST - -### Backend Tasks - -- [ ] Create `business/billing/constants.py` with credit costs -- [ ] Update `CreditService` with credit cost methods -- [ ] Update `Plan` model - remove limit fields -- [ ] Create migration to remove plan limit fields -- [ ] Update `AIEngine` to check credits before AI calls -- [ ] Update content generation to check credits -- [ ] Update image generation to check credits -- [ ] Remove all plan limit checks from ViewSets -- [ ] Update `CreditUsageLog` model with tracking fields -- [ ] Create migration for credit tracking -- [ ] Extend `ModuleSettings` model with enabled flags -- [ ] Update module settings API -- [ ] Add monthly credit replenishment Celery Beat task - -### Frontend Tasks - -- [ ] Implement `frontend/src/pages/Settings/Modules.tsx` -- [ ] Create `frontend/src/config/modules.config.ts` -- [ ] Create `frontend/src/components/common/ModuleGuard.tsx` -- [ ] Update `frontend/src/App.tsx` with conditional route loading -- [ ] Update `frontend/src/layout/AppSidebar.tsx` to filter disabled modules -- [ ] Update `frontend/src/pages/Billing/` to show credits instead of limits -- [ ] Update billing UI to show credit costs per operation - -### Testing Tasks - -- [ ] Test credit deduction for all operations -- [ ] Test insufficient credits error handling -- [ ] Test module enable/disable functionality -- [ ] Test disabled modules don't load -- [ ] Test backward compatibility -- [ ] Test migration safety - ---- - -## RISK ASSESSMENT - -| Risk | Level | Mitigation | -|------|-------|------------| -| **Breaking existing functionality** | MEDIUM | Extensive testing, gradual rollout | -| **Credit calculation errors** | MEDIUM | Unit tests for credit calculations | -| **Migration data loss** | LOW | Backup before migration, test on staging | -| **Frontend breaking changes** | LOW | Backward compatible API changes | - ---- - -## SUCCESS CRITERIA - -- ✅ All existing features work with credit checks -- ✅ Credit deduction happens correctly for all operations -- ✅ Insufficient credits show clear error messages -- ✅ Usage logging tracks all operations -- ✅ Frontend shows credit balance, not limits -- ✅ Module settings enable/disable modules correctly -- ✅ Disabled modules don't appear in UI -- ✅ No breaking changes for existing users - ---- - -**END OF PHASE 0 DOCUMENT** - diff --git a/docs/planning/phases/PHASE-1-SERVICE-LAYER-REFACTORING.md b/docs/planning/phases/PHASE-1-SERVICE-LAYER-REFACTORING.md deleted file mode 100644 index 564b4dfb..00000000 --- a/docs/planning/phases/PHASE-1-SERVICE-LAYER-REFACTORING.md +++ /dev/null @@ -1,434 +0,0 @@ -# PHASE 1: SERVICE LAYER REFACTORING -**Detailed Implementation Plan** - -**Goal**: Extract business logic from ViewSets into services, preserving all existing functionality. - -**Timeline**: 2-3 weeks -**Priority**: HIGH -**Dependencies**: Phase 0 - ---- - -## TABLE OF CONTENTS - -1. [Overview](#overview) -2. [Create Business Structure](#create-business-structure) -3. [Move Models to Business](#move-models-to-business) -4. [Create Services](#create-services) -5. [Refactor ViewSets](#refactor-viewsets) -6. [Testing & Validation](#testing--validation) -7. [Implementation Checklist](#implementation-checklist) - ---- - -## OVERVIEW - -### Objectives -- ✅ Create `business/` folder structure -- ✅ Move models from `modules/` to `business/` -- ✅ Extract business logic from ViewSets to services -- ✅ Keep ViewSets as thin wrappers -- ✅ Preserve all existing API functionality - -### Key Principles -- **Service Layer Pattern**: Business logic in services, not ViewSets -- **Testable Services**: Services can be tested independently -- **Clean Architecture**: Clear separation between API layer (modules/) and business logic (business/) - ---- - -## CREATE BUSINESS STRUCTURE - -### 1.1 Create Business Structure - -**Purpose**: Organize code by business logic, not technical layers. - -#### Folder Structure - -``` -backend/igny8_core/ -├── business/ # NEW: Business logic layer -│ ├── content/ # Content business logic -│ │ ├── __init__.py -│ │ ├── models.py # Content, Tasks, Images -│ │ ├── services/ -│ │ │ ├── __init__.py -│ │ │ ├── content_generation_service.py -│ │ │ ├── content_pipeline_service.py -│ │ │ └── content_versioning_service.py -│ │ └── migrations/ -│ │ -│ ├── planning/ # Planning business logic -│ │ ├── __init__.py -│ │ ├── models.py # Keywords, Clusters, Ideas -│ │ ├── services/ -│ │ │ ├── __init__.py -│ │ │ ├── clustering_service.py -│ │ │ └── ideas_service.py -│ │ └── migrations/ -│ │ -│ ├── billing/ # Billing business logic (already exists) -│ │ ├── models.py # Credits, Transactions -│ │ └── services/ -│ │ └── credit_service.py # Already exists -│ │ -│ └── automation/ # Automation business logic (Phase 2) -│ ├── models.py -│ └── services/ -``` - -#### Implementation Tasks - -| Task | File | Current Location | New Location | Risk | -|------|------|------------------|--------------|------| -| **Create business/ folder** | `backend/igny8_core/business/` | N/A | NEW | LOW | -| **Create content business** | `business/content/` | N/A | NEW | LOW | -| **Create planning business** | `business/planning/` | N/A | NEW | LOW | -| **Create billing business** | `business/billing/` | `modules/billing/` | MOVE | LOW | -| **Create automation business** | `business/automation/` | N/A | NEW (Phase 2) | LOW | - ---- - -## MOVE MODELS TO BUSINESS - -### 1.2 Move Models to Business - -**Purpose**: Move models from `modules/` to `business/` to separate business logic from API layer. - -#### Content Models Migration - -| Model | Current Location | New Location | Changes Needed | -|------|------------------|--------------|----------------| -| `Content` | `modules/writer/models.py` | `business/content/models.py` | Move, update imports | -| `Tasks` | `modules/writer/models.py` | `business/content/models.py` | Move, update imports | -| `Images` | `modules/writer/models.py` | `business/content/models.py` | Move, update imports | - -**Migration Steps**: -1. Create `business/content/models.py` -2. Copy models from `modules/writer/models.py` -3. Update imports in `modules/writer/views.py` -4. Create migration to ensure no data loss -5. Update all references to models - -#### Planning Models Migration - -| Model | Current Location | New Location | Changes Needed | -|------|------------------|--------------|----------------| -| `Keywords` | `modules/planner/models.py` | `business/planning/models.py` | Move, update imports | -| `Clusters` | `modules/planner/models.py` | `business/planning/models.py` | Move, update imports | -| `ContentIdeas` | `modules/planner/models.py` | `business/planning/models.py` | Move, update imports | - -**Migration Steps**: -1. Create `business/planning/models.py` -2. Copy models from `modules/planner/models.py` -3. Update imports in `modules/planner/views.py` -4. Create migration to ensure no data loss -5. Update all references to models - -#### Billing Models Migration - -| Model | Current Location | New Location | Changes Needed | -|------|------------------|--------------|----------------| -| `CreditTransaction` | `modules/billing/models.py` | `business/billing/models.py` | Move, update imports | -| `CreditUsageLog` | `modules/billing/models.py` | `business/billing/models.py` | Move, update imports | - -**Migration Steps**: -1. Create `business/billing/models.py` -2. Copy models from `modules/billing/models.py` -3. Move `CreditService` to `business/billing/services/credit_service.py` -4. Update imports in `modules/billing/views.py` -5. Create migration to ensure no data loss - ---- - -## CREATE SERVICES - -### 1.3 Create Services - -**Purpose**: Extract business logic from ViewSets into reusable services. - -#### ContentService - -| Task | File | Purpose | Dependencies | -|------|------|---------|--------------| -| **Create ContentService** | `business/content/services/content_generation_service.py` | Unified content generation | Existing Writer logic, CreditService | - -**ContentService Methods**: -```python -# business/content/services/content_generation_service.py -class ContentGenerationService: - def __init__(self): - self.credit_service = CreditService() - - def generate_content(self, task, account): - """Generate content for a task""" - # Check credits - self.credit_service.check_credits(account, 'content_generation', task.estimated_word_count) - - # Generate content (existing logic from Writer ViewSet) - content = self._generate(task) - - # Deduct credits - self.credit_service.deduct_credits(account, 'content_generation', content.word_count) - - return content - - def _generate(self, task): - """Internal content generation logic""" - # Move logic from Writer ViewSet here - pass -``` - -#### PlanningService - -| Task | File | Purpose | Dependencies | -|------|------|---------|--------------| -| **Create PlanningService** | `business/planning/services/clustering_service.py` | Keyword clustering | Existing Planner logic, CreditService | - -**PlanningService Methods**: -```python -# business/planning/services/clustering_service.py -class ClusteringService: - def __init__(self): - self.credit_service = CreditService() - - def cluster_keywords(self, keyword_ids, account): - """Cluster keywords using AI""" - # Check credits - self.credit_service.check_credits(account, 'clustering', len(keyword_ids)) - - # Cluster keywords (existing logic from Planner ViewSet) - clusters = self._cluster(keyword_ids) - - # Deduct credits - self.credit_service.deduct_credits(account, 'clustering', len(keyword_ids)) - - return clusters -``` - -#### IdeasService - -| Task | File | Purpose | Dependencies | -|------|------|---------|--------------| -| **Create IdeasService** | `business/planning/services/ideas_service.py` | Generate content ideas | Existing Planner logic, CreditService | - -**IdeasService Methods**: -```python -# business/planning/services/ideas_service.py -class IdeasService: - def __init__(self): - self.credit_service = CreditService() - - def generate_ideas(self, cluster_ids, account): - """Generate content ideas from clusters""" - # Check credits - self.credit_service.check_credits(account, 'idea_generation', len(cluster_ids)) - - # Generate ideas (existing logic from Planner ViewSet) - ideas = self._generate_ideas(cluster_ids) - - # Deduct credits - self.credit_service.deduct_credits(account, 'idea_generation', len(ideas)) - - return ideas -``` - ---- - -## REFACTOR VIEWSETS - -### 1.4 Refactor ViewSets (Keep APIs Working) - -**Purpose**: Make ViewSets thin wrappers that delegate to services. - -#### Planner ViewSets Refactoring - -| ViewSet | Current | New | Risk | -|---------|---------|-----|------| -| **KeywordViewSet** | Business logic in views | Delegate to services | LOW | -| **ClusterViewSet** | Business logic in views | Delegate to services | LOW | -| **ContentIdeasViewSet** | Business logic in views | Delegate to services | LOW | - -**Before (Business Logic in ViewSet)**: -```python -# modules/planner/views.py -class ClusterViewSet(SiteSectorModelViewSet): - @action(detail=False, methods=['post']) - def auto_generate_ideas(self, request): - cluster_ids = request.data.get('cluster_ids') - # Business logic here (50+ lines) - clusters = Cluster.objects.filter(id__in=cluster_ids) - # AI call logic - # Idea creation logic - # etc. - return Response(...) -``` - -**After (Delegate to Service)**: -```python -# modules/planner/views.py -class ClusterViewSet(SiteSectorModelViewSet): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.ideas_service = IdeasService() - - @action(detail=False, methods=['post']) - def auto_generate_ideas(self, request): - cluster_ids = request.data.get('cluster_ids') - account = request.account - - # Delegate to service - ideas = self.ideas_service.generate_ideas(cluster_ids, account) - - # Serialize and return - serializer = ContentIdeasSerializer(ideas, many=True) - return Response(serializer.data) -``` - -#### Writer ViewSets Refactoring - -| ViewSet | Current | New | Risk | -|---------|---------|-----|------| -| **TasksViewSet** | Business logic in views | Delegate to services | LOW | -| **ImagesViewSet** | Business logic in views | Delegate to services | LOW | - -**Before (Business Logic in ViewSet)**: -```python -# modules/writer/views.py -class TasksViewSet(SiteSectorModelViewSet): - @action(detail=False, methods=['post']) - def auto_generate_content(self, request): - task_ids = request.data.get('task_ids') - # Business logic here (100+ lines) - tasks = Task.objects.filter(id__in=task_ids) - # AI call logic - # Content creation logic - # etc. - return Response(...) -``` - -**After (Delegate to Service)**: -```python -# modules/writer/views.py -class TasksViewSet(SiteSectorModelViewSet): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.content_service = ContentGenerationService() - - @action(detail=False, methods=['post']) - def auto_generate_content(self, request): - task_ids = request.data.get('task_ids') - account = request.account - - # Delegate to service - contents = [] - for task_id in task_ids: - task = Task.objects.get(id=task_id) - content = self.content_service.generate_content(task, account) - contents.append(content) - - # Serialize and return - serializer = ContentSerializer(contents, many=True) - return Response(serializer.data) -``` - -#### Billing ViewSets - -| ViewSet | Current | New | Risk | -|---------|---------|-----|------| -| **CreditTransactionViewSet** | Already uses CreditService | Keep as-is | NONE | -| **CreditUsageLogViewSet** | Already uses CreditService | Keep as-is | NONE | - -**Note**: Billing ViewSets already use CreditService, so no changes needed. - ---- - -## TESTING & VALIDATION - -### 1.5 Testing - -**Test Cases**: - -1. **Service Tests**: - - ✅ Services can be tested independently - - ✅ Services handle errors correctly - - ✅ Services check credits before operations - - ✅ Services deduct credits after operations - -2. **API Compatibility Tests**: - - ✅ All existing API endpoints work identically - - ✅ Response formats unchanged - - ✅ No breaking changes for frontend - - ✅ All ViewSet actions work correctly - -3. **Model Migration Tests**: - - ✅ Models work after migration - - ✅ All relationships preserved - - ✅ No data loss during migration - - ✅ All queries work correctly - -**Test Files to Create**: -- `backend/tests/test_content_service.py` -- `backend/tests/test_planning_service.py` -- `backend/tests/test_ideas_service.py` -- `backend/tests/test_viewset_refactoring.py` - ---- - -## IMPLEMENTATION CHECKLIST - -### Backend Tasks - -- [ ] Create `business/` folder structure -- [ ] Create `business/content/` folder -- [ ] Create `business/planning/` folder -- [ ] Create `business/billing/` folder (move existing) -- [ ] Move Content models to `business/content/models.py` -- [ ] Move Planning models to `business/planning/models.py` -- [ ] Move Billing models to `business/billing/models.py` -- [ ] Create migrations for model moves -- [ ] Create `ContentGenerationService` -- [ ] Create `ClusteringService` -- [ ] Create `IdeasService` -- [ ] Refactor `KeywordViewSet` to use services -- [ ] Refactor `ClusterViewSet` to use services -- [ ] Refactor `ContentIdeasViewSet` to use services -- [ ] Refactor `TasksViewSet` to use services -- [ ] Refactor `ImagesViewSet` to use services -- [ ] Update all imports -- [ ] Test all API endpoints - -### Testing Tasks - -- [ ] Test all existing API endpoints work -- [ ] Test response formats unchanged -- [ ] Test services independently -- [ ] Test model migrations -- [ ] Test backward compatibility - ---- - -## RISK ASSESSMENT - -| Risk | Level | Mitigation | -|------|-------|------------| -| **Import errors** | MEDIUM | Update all imports systematically | -| **Data loss during migration** | LOW | Backup before migration, test on staging | -| **Service logic errors** | MEDIUM | Unit tests for all services | -| **Model migration complexity** | MEDIUM | Use Django migrations, test thoroughly | - ---- - -## SUCCESS CRITERIA - -- ✅ Services are testable independently -- ✅ Business logic extracted from ViewSets -- ✅ ViewSets are thin wrappers that delegate to services -- ✅ All models moved to business layer -- ✅ All imports updated correctly -- ✅ Services handle credit checks and business rules - ---- - -**END OF PHASE 1 DOCUMENT** - diff --git a/docs/planning/phases/PHASE-2-AUTOMATION-SYSTEM.md b/docs/planning/phases/PHASE-2-AUTOMATION-SYSTEM.md deleted file mode 100644 index 9ae4a746..00000000 --- a/docs/planning/phases/PHASE-2-AUTOMATION-SYSTEM.md +++ /dev/null @@ -1,594 +0,0 @@ -# PHASE 2: AUTOMATION SYSTEM -**Detailed Implementation Plan** - -**Goal**: Implement automation rules and scheduled tasks. - -**Timeline**: 2-3 weeks -**Priority**: HIGH -**Dependencies**: Phase 1 - ---- - -## TABLE OF CONTENTS - -1. [Overview](#overview) -2. [Automation Models](#automation-models) -3. [Automation Service](#automation-service) -4. [Celery Beat Tasks](#celery-beat-tasks) -5. [Automation API](#automation-api) -6. [Automation UI](#automation-ui) -7. [Testing & Validation](#testing--validation) -8. [Implementation Checklist](#implementation-checklist) - ---- - -## OVERVIEW - -### Objectives -- ✅ Create AutomationRule and ScheduledTask models -- ✅ Build AutomationService with rule execution engine -- ✅ Implement Celery Beat scheduled tasks -- ✅ Create automation API endpoints -- ✅ Build automation UI (Dashboard, Rules, History) - -### Key Principles -- **Rule-Based**: Users create rules with triggers, conditions, actions -- **Scheduled Execution**: Rules can run on schedule or event triggers -- **Credit-Aware**: Automation respects credit limits -- **Audit Trail**: All automation executions logged - ---- - -## AUTOMATION MODELS - -### 2.1 Automation Models - -**Purpose**: Store automation rules and scheduled task records. - -#### AutomationRule Model - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **AutomationRule Model** | `business/automation/models.py` | Phase 1 | Create model with trigger, conditions, actions, schedule | - -**AutomationRule Model**: -```python -# business/automation/models.py -class AutomationRule(SiteSectorBaseModel): - name = models.CharField(max_length=255) - description = models.TextField(blank=True) - - # Trigger configuration - trigger = models.CharField( - max_length=50, - choices=[ - ('schedule', 'Scheduled'), - ('keyword_added', 'Keyword Added'), - ('cluster_created', 'Cluster Created'), - ('idea_created', 'Idea Created'), - ('content_generated', 'Content Generated'), - ('task_created', 'Task Created'), - ] - ) - - # Condition evaluation - conditions = models.JSONField(default=dict) - # Example: {'field': 'status', 'operator': 'eq', 'value': 'draft'} - - # Actions to execute - actions = models.JSONField(default=list) - # Example: [{'type': 'generate_ideas', 'params': {'cluster_ids': [1, 2]}}] - - # Schedule configuration (for scheduled triggers) - schedule = models.JSONField(default=dict) - # Example: {'cron': '0 9 * * *', 'timezone': 'UTC'} - - # Execution limits - is_active = models.BooleanField(default=True) - max_executions_per_day = models.IntegerField(default=10) - credit_limit_per_execution = models.IntegerField(default=100) - - # Tracking - last_executed_at = models.DateTimeField(null=True, blank=True) - execution_count_today = models.IntegerField(default=0) - last_reset_at = models.DateTimeField(auto_now_add=True) - - class Meta: - ordering = ['-created_at'] -``` - -#### ScheduledTask Model - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **ScheduledTask Model** | `business/automation/models.py` | Phase 1 | Create model to track scheduled executions | - -**ScheduledTask Model**: -```python -# business/automation/models.py -class ScheduledTask(SiteSectorBaseModel): - automation_rule = models.ForeignKey(AutomationRule, on_delete=models.CASCADE) - scheduled_at = models.DateTimeField() - executed_at = models.DateTimeField(null=True, blank=True) - status = models.CharField( - max_length=20, - choices=[ - ('pending', 'Pending'), - ('running', 'Running'), - ('completed', 'Completed'), - ('failed', 'Failed'), - ('skipped', 'Skipped'), - ], - default='pending' - ) - result = models.JSONField(default=dict, blank=True) - error_message = models.TextField(blank=True) - credits_used = models.IntegerField(default=0) - - class Meta: - ordering = ['-scheduled_at'] -``` - -#### Automation Migrations - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Automation Migrations** | `business/automation/migrations/` | Phase 1 | Create initial migrations | - ---- - -## AUTOMATION SERVICE - -### 2.2 Automation Service - -**Purpose**: Execute automation rules with condition evaluation and action execution. - -#### AutomationService - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **AutomationService** | `business/automation/services/automation_service.py` | Phase 1 services | Main service for rule execution | - -**AutomationService Methods**: -```python -# business/automation/services/automation_service.py -class AutomationService: - def __init__(self): - self.rule_engine = RuleEngine() - self.condition_evaluator = ConditionEvaluator() - self.action_executor = ActionExecutor() - self.credit_service = CreditService() - - def execute_rule(self, rule, context=None): - """Execute an automation rule""" - # Check if rule is active - if not rule.is_active: - return {'status': 'skipped', 'reason': 'Rule is inactive'} - - # Check execution limits - if not self._check_execution_limits(rule): - return {'status': 'skipped', 'reason': 'Execution limit reached'} - - # Check credits - if not self.credit_service.check_credits(rule.account, 'automation', rule.credit_limit_per_execution): - return {'status': 'skipped', 'reason': 'Insufficient credits'} - - # Evaluate conditions - if not self.condition_evaluator.evaluate(rule.conditions, context): - return {'status': 'skipped', 'reason': 'Conditions not met'} - - # Execute actions - results = self.action_executor.execute(rule.actions, context) - - # Update rule tracking - rule.last_executed_at = timezone.now() - rule.execution_count_today += 1 - rule.save() - - return {'status': 'completed', 'results': results} - - def _check_execution_limits(self, rule): - """Check if rule can execute (daily limit)""" - # Reset counter if new day - if rule.last_reset_at.date() < timezone.now().date(): - rule.execution_count_today = 0 - rule.last_reset_at = timezone.now() - rule.save() - - return rule.execution_count_today < rule.max_executions_per_day -``` - -#### Rule Execution Engine - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Rule Execution Engine** | `business/automation/services/rule_engine.py` | Phase 1 services | Orchestrates rule execution | - -**RuleEngine Methods**: -```python -# business/automation/services/rule_engine.py -class RuleEngine: - def execute_rule(self, rule, context): - """Orchestrate rule execution""" - # Validate rule - # Check conditions - # Execute actions - # Handle errors - pass -``` - -#### Condition Evaluator - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Condition Evaluator** | `business/automation/services/condition_evaluator.py` | None | Evaluates rule conditions | - -**ConditionEvaluator Methods**: -```python -# business/automation/services/condition_evaluator.py -class ConditionEvaluator: - def evaluate(self, conditions, context): - """Evaluate rule conditions""" - # Support operators: eq, ne, gt, gte, lt, lte, in, contains - # Example: {'field': 'status', 'operator': 'eq', 'value': 'draft'} - pass -``` - -#### Action Executor - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Action Executor** | `business/automation/services/action_executor.py` | Phase 1 services | Executes rule actions | - -**ActionExecutor Methods**: -```python -# business/automation/services/action_executor.py -class ActionExecutor: - def __init__(self): - self.clustering_service = ClusteringService() - self.ideas_service = IdeasService() - self.content_service = ContentGenerationService() - - def execute(self, actions, context): - """Execute rule actions""" - results = [] - for action in actions: - action_type = action['type'] - params = action.get('params', {}) - - if action_type == 'generate_ideas': - result = self.ideas_service.generate_ideas(params['cluster_ids'], context['account']) - elif action_type == 'generate_content': - result = self.content_service.generate_content(params['task_id'], context['account']) - # ... other action types - - results.append(result) - - return results -``` - ---- - -## CELERY BEAT TASKS - -### 2.3 Celery Beat Tasks - -**Purpose**: Schedule automation rules and monthly credit replenishment. - -#### Scheduled Automation Task - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Scheduled Automation Task** | `infrastructure/messaging/automation_tasks.py` | AutomationService | Periodic task to execute scheduled rules | - -**Scheduled Automation Task**: -```python -# infrastructure/messaging/automation_tasks.py -from celery import shared_task -from celery.schedules import crontab - -@shared_task -def execute_scheduled_automation_rules(): - """Execute all scheduled automation rules""" - from business.automation.services.automation_service import AutomationService - - service = AutomationService() - rules = AutomationRule.objects.filter( - trigger='schedule', - is_active=True - ) - - for rule in rules: - # Check if rule should execute based on schedule - if should_execute_now(rule.schedule): - service.execute_rule(rule) -``` - -#### Monthly Credit Replenishment - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Monthly Credit Replenishment** | `infrastructure/messaging/automation_tasks.py` | CreditService | Add credits monthly to accounts | - -**Monthly Credit Replenishment Task**: -```python -# infrastructure/messaging/automation_tasks.py -@shared_task -def replenish_monthly_credits(): - """Replenish monthly credits for all active accounts""" - from business.billing.services.credit_service import CreditService - - service = CreditService() - accounts = Account.objects.filter(status='active') - - for account in accounts: - if account.plan: - monthly_credits = account.plan.monthly_credits - if monthly_credits > 0: - service.add_credits(account, monthly_credits, 'monthly_replenishment') -``` - -#### Celery Beat Configuration - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Celery Beat Configuration** | `backend/igny8_core/celery.py` | None | Configure periodic tasks | - -**Celery Beat Configuration**: -```python -# backend/igny8_core/celery.py -from celery.schedules import crontab - -app.conf.beat_schedule = { - 'execute-scheduled-automation-rules': { - 'task': 'infrastructure.messaging.automation_tasks.execute_scheduled_automation_rules', - 'schedule': crontab(minute='*/15'), # Every 15 minutes - }, - 'replenish-monthly-credits': { - 'task': 'infrastructure.messaging.automation_tasks.replenish_monthly_credits', - 'schedule': crontab(hour=0, minute=0, day_of_month=1), # First day of month - }, -} -``` - ---- - -## AUTOMATION API - -### 2.4 Automation API - -**Purpose**: CRUD API for automation rules and scheduled tasks. - -#### AutomationRule ViewSet - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **AutomationRule ViewSet** | `modules/automation/views.py` | AutomationService | CRUD operations for rules | - -**AutomationRule ViewSet**: -```python -# modules/automation/views.py -class AutomationRuleViewSet(AccountModelViewSet): - queryset = AutomationRule.objects.all() - serializer_class = AutomationRuleSerializer - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.automation_service = AutomationService() - - @action(detail=True, methods=['post']) - def execute(self, request, pk=None): - """Manually execute a rule""" - rule = self.get_object() - result = self.automation_service.execute_rule(rule, {'account': request.account}) - return Response(result) - - @action(detail=True, methods=['post']) - def test(self, request, pk=None): - """Test rule conditions without executing""" - rule = self.get_object() - # Test condition evaluation - pass -``` - -#### ScheduledTask ViewSet - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **ScheduledTask ViewSet** | `modules/automation/views.py` | AutomationService | View scheduled task history | - -**ScheduledTask ViewSet**: -```python -# modules/automation/views.py -class ScheduledTaskViewSet(AccountModelViewSet): - queryset = ScheduledTask.objects.all() - serializer_class = ScheduledTaskSerializer - filterset_fields = ['status', 'automation_rule'] - ordering = ['-scheduled_at'] -``` - -#### Automation URLs - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Automation URLs** | `modules/automation/urls.py` | None | Register automation routes | - -**Automation URLs**: -```python -# modules/automation/urls.py -from rest_framework.routers import DefaultRouter -from .views import AutomationRuleViewSet, ScheduledTaskViewSet - -router = DefaultRouter() -router.register(r'rules', AutomationRuleViewSet, basename='automation-rule') -router.register(r'scheduled-tasks', ScheduledTaskViewSet, basename='scheduled-task') - -urlpatterns = router.urls -``` - ---- - -## AUTOMATION UI - -### 2.5 Automation UI - -**Purpose**: User interface for managing automation rules and viewing history. - -#### Automation Dashboard - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Automation Dashboard** | `frontend/src/pages/Automation/Dashboard.tsx` | EXISTING (placeholder) | Overview of automation status | - -**Dashboard Features**: -- Active rules count -- Recent executions -- Success/failure rates -- Credit usage from automation -- Quick actions (create rule, view history) - -#### Rules Management - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Rules Management** | `frontend/src/pages/Automation/Rules.tsx` | NEW | CRUD interface for rules | - -**Rules Management Features**: -- List all rules -- Create new rule (wizard) -- Edit existing rule -- Enable/disable rule -- Delete rule -- Test rule -- Manual execution - -#### Schedules (Part of Automation Menu) - -**Note**: Schedules functionality will be integrated into the Automation menu group, not as a separate page. - -**Schedules Features** (within Automation Dashboard): -- List scheduled tasks -- Filter by status, rule, date -- View execution results -- View error messages -- Retry failed tasks - -#### Automation API Client - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Automation API Client** | `frontend/src/services/automation.api.ts` | NEW | API client for automation endpoints | - -**Automation API Client**: -```typescript -// frontend/src/services/automation.api.ts -export const automationApi = { - getRules: () => fetchAPI('/automation/rules/'), - createRule: (data) => fetchAPI('/automation/rules/', { method: 'POST', body: data }), - updateRule: (id, data) => fetchAPI(`/automation/rules/${id}/`, { method: 'PUT', body: data }), - deleteRule: (id) => fetchAPI(`/automation/rules/${id}/`, { method: 'DELETE' }), - executeRule: (id) => fetchAPI(`/automation/rules/${id}/execute/`, { method: 'POST' }), - getScheduledTasks: (filters) => fetchAPI('/automation/scheduled-tasks/', { params: filters }), -}; -``` - ---- - -## TESTING & VALIDATION - -### 2.6 Testing - -**Test Cases**: - -1. **Automation Service Tests**: - - ✅ Rules execute correctly - - ✅ Conditions evaluate correctly - - ✅ Actions execute correctly - - ✅ Execution limits enforced - - ✅ Credit checks work - -2. **Scheduled Tasks Tests**: - - ✅ Scheduled tasks run on time - - ✅ Credit replenishment works monthly - - ✅ Task status tracking works - -3. **API Tests**: - - ✅ CRUD operations work - - ✅ Rule execution endpoint works - - ✅ Scheduled task history works - -4. **UI Tests**: - - ✅ Dashboard displays correctly - - ✅ Rules management works - - ✅ Schedule history displays correctly - ---- - -## IMPLEMENTATION CHECKLIST - -### Backend Tasks - -- [ ] Create `business/automation/models.py` -- [ ] Create AutomationRule model -- [ ] Create ScheduledTask model -- [ ] Create automation migrations -- [ ] Create `business/automation/services/automation_service.py` -- [ ] Create `business/automation/services/rule_engine.py` -- [ ] Create `business/automation/services/condition_evaluator.py` -- [ ] Create `business/automation/services/action_executor.py` -- [ ] Create `infrastructure/messaging/automation_tasks.py` -- [ ] Add scheduled automation task -- [ ] Add monthly credit replenishment task -- [ ] Configure Celery Beat -- [ ] Create `modules/automation/views.py` -- [ ] Create AutomationRule ViewSet -- [ ] Create ScheduledTask ViewSet -- [ ] Create `modules/automation/serializers.py` -- [ ] Create `modules/automation/urls.py` -- [ ] Register automation URLs in main urls.py - -### Frontend Tasks - -- [ ] Implement `frontend/src/pages/Automation/Dashboard.tsx` -- [ ] Create `frontend/src/pages/Automation/Rules.tsx` -- [ ] Integrate schedules functionality into Automation Dashboard (not as separate page) -- [ ] Create `frontend/src/services/automation.api.ts` -- [ ] Create rule creation wizard -- [ ] Create rule editor -- [ ] Create schedule history table (within Automation Dashboard) - -### Testing Tasks - -- [ ] Test automation rule execution -- [ ] Test scheduled tasks -- [ ] Test credit replenishment -- [ ] Test API endpoints -- [ ] Test UI components - ---- - -## RISK ASSESSMENT - -| Risk | Level | Mitigation | -|------|-------|------------| -| **Rule execution errors** | MEDIUM | Comprehensive error handling, logging | -| **Credit limit violations** | MEDIUM | Credit checks before execution | -| **Scheduled task failures** | MEDIUM | Retry mechanism, error logging | -| **Performance issues** | LOW | Background processing, rate limiting | - ---- - -## SUCCESS CRITERIA - -- ✅ Automation rules execute correctly -- ✅ Scheduled tasks run on time -- ✅ Credit replenishment works monthly -- ✅ UI shows automation status -- ✅ Rules can be created, edited, deleted -- ✅ Execution history is tracked -- ✅ All automation respects credit limits - ---- - -**END OF PHASE 2 DOCUMENT** - diff --git a/docs/planning/phases/PHASE-3-SITE-BUILDER.md b/docs/planning/phases/PHASE-3-SITE-BUILDER.md deleted file mode 100644 index cac505b3..00000000 --- a/docs/planning/phases/PHASE-3-SITE-BUILDER.md +++ /dev/null @@ -1,642 +0,0 @@ -# PHASE 3: SITE BUILDER -**Detailed Implementation Plan** - -**Goal**: Build Site Builder for creating sites via wizard. - -**Timeline**: 3-4 weeks -**Priority**: HIGH -**Dependencies**: Phase 1, Phase 2 - ---- - -## TABLE OF CONTENTS - -1. [Overview](#overview) -2. [Sites Folder Access & File Management](#sites-folder-access--file-management) -3. [Site Builder Models](#site-builder-models) -4. [Site Structure Generation](#site-structure-generation) -5. [Site Builder API](#site-builder-api) -6. [Site Builder Frontend](#site-builder-frontend) -7. [Global Component Library](#global-component-library) -8. [Page Generation](#page-generation) -9. [Testing & Validation](#testing--validation) -10. [Implementation Checklist](#implementation-checklist) - ---- - -## OVERVIEW - -### Objectives -- ✅ Create Site Builder wizard for site creation -- ✅ Generate site structure using AI -- ✅ Build preview canvas for site editing -- ✅ Create shared component library -- ✅ Support multiple layouts and templates -- ✅ Enable file management for site assets - -### Key Principles -- **Wizard-Based**: Step-by-step site creation process -- **AI-Powered**: AI generates site structure from business brief -- **Component Reuse**: Shared components across Site Builder, Sites Renderer, Main App -- **User-Friendly**: "Website Builder" or "Site Creator" in UI - ---- - -## SITES FOLDER ACCESS & FILE MANAGEMENT - -### 3.0 Sites Folder Access & File Management - -**Purpose**: Manage site files and assets with proper access control. - -#### Sites Folder Structure - -``` -/data/app/sites-data/ -└── clients/ - └── {site_id}/ - └── v{version}/ - ├── site.json # Site definition - ├── pages/ # Page definitions - │ ├── home.json - │ ├── about.json - │ └── ... - └── assets/ # User-managed files - ├── images/ - ├── documents/ - └── media/ -``` - -#### User Access Rules - -- **Owner/Admin**: Full access to all account sites -- **Editor**: Access to granted sites (via SiteUserAccess) -- **Viewer**: Read-only access to granted sites -- **File operations**: Scoped to user's accessible sites only - -#### Site File Management Service - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Site File Management Service** | `business/site_building/services/file_management_service.py` | Phase 1 | File upload, delete, organize | - -**FileManagementService**: -```python -# business/site_building/services/file_management_service.py -class SiteBuilderFileService: - def get_user_accessible_sites(self, user): - """Get sites user can access for file management""" - if user.is_owner_or_admin(): - return Site.objects.filter(account=user.account) - return user.get_accessible_sites() - - def get_site_files_path(self, site_id, version=1): - """Get site's files directory""" - return f"/data/app/sites-data/clients/{site_id}/v{version}/assets/" - - def check_file_access(self, user, site_id): - """Check if user can access site's files""" - accessible_sites = self.get_user_accessible_sites(user) - return any(site.id == site_id for site in accessible_sites) - - def upload_file(self, user, site_id, file, folder='images'): - """Upload file to site's assets folder""" - if not self.check_file_access(user, site_id): - raise PermissionDenied("No access to this site") - - # Check storage quota - if not self.check_storage_quota(site_id, file.size): - raise ValidationError("Storage quota exceeded") - - # Upload file - file_path = self._save_file(site_id, file, folder) - return file_path -``` - -#### File Upload API - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **File Upload API** | `modules/site_builder/views.py` | File Management Service | Handle file uploads | - -#### File Browser UI - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **File Browser UI** | `site-builder/src/components/files/FileBrowser.tsx` | NEW | File browser component | - -#### Storage Quota Check - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Storage Quota Check** | `infrastructure/storage/file_storage.py` | Phase 1 | Check site storage quota | - ---- - -## SITE BUILDER MODELS - -### 3.1 Site Builder Models - -**Purpose**: Store site blueprints and page definitions. - -#### SiteBlueprint Model - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **SiteBlueprint Model** | `business/site_building/models.py` | Phase 1 | Store site structure | - -**SiteBlueprint Model**: -```python -# business/site_building/models.py -class SiteBlueprint(SiteSectorBaseModel): - name = models.CharField(max_length=255) - description = models.TextField(blank=True) - - # Site configuration - config_json = models.JSONField(default=dict) - # Example: {'business_type': 'ecommerce', 'style': 'modern'} - - # Generated structure - structure_json = models.JSONField(default=dict) - # Example: {'pages': [...], 'layout': 'default', 'theme': {...}} - - # Status tracking - status = models.CharField( - max_length=20, - choices=[ - ('draft', 'Draft'), - ('generating', 'Generating'), - ('ready', 'Ready'), - ('deployed', 'Deployed'), - ], - default='draft' - ) - - # Hosting configuration - hosting_type = models.CharField( - max_length=50, - choices=[ - ('igny8_sites', 'IGNY8 Sites'), - ('wordpress', 'WordPress'), - ('shopify', 'Shopify'), - ('multi', 'Multiple Destinations'), - ], - default='igny8_sites' - ) - - # Version tracking - version = models.IntegerField(default=1) - deployed_version = models.IntegerField(null=True, blank=True) - - class Meta: - ordering = ['-created_at'] -``` - -#### PageBlueprint Model - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **PageBlueprint Model** | `business/site_building/models.py` | Phase 1 | Store page definitions | - -**PageBlueprint Model**: -```python -# business/site_building/models.py -class PageBlueprint(SiteSectorBaseModel): - site_blueprint = models.ForeignKey(SiteBlueprint, on_delete=models.CASCADE, related_name='pages') - slug = models.SlugField(max_length=255) - title = models.CharField(max_length=255) - - # Page type - type = models.CharField( - max_length=50, - choices=[ - ('home', 'Home'), - ('about', 'About'), - ('services', 'Services'), - ('products', 'Products'), - ('blog', 'Blog'), - ('contact', 'Contact'), - ('custom', 'Custom'), - ] - ) - - # Page content (blocks) - blocks_json = models.JSONField(default=list) - # Example: [{'type': 'hero', 'data': {...}}, {'type': 'features', 'data': {...}}] - - # Status - status = models.CharField( - max_length=20, - choices=[ - ('draft', 'Draft'), - ('generating', 'Generating'), - ('ready', 'Ready'), - ], - default='draft' - ) - - # Order - order = models.IntegerField(default=0) - - class Meta: - ordering = ['order', 'created_at'] - unique_together = [['site_blueprint', 'slug']] -``` - -#### Site Builder Migrations - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Site Builder Migrations** | `business/site_building/migrations/` | Phase 1 | Create initial migrations | - ---- - -## SITE STRUCTURE GENERATION - -### 3.2 Site Structure Generation - -**Purpose**: Use AI to generate site structure from business brief. - -#### Structure Generation AI Function - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Structure Generation AI Function** | `infrastructure/ai/functions/generate_site_structure.py` | Existing AI framework | AI function for structure generation | - -**GenerateSiteStructureFunction**: -```python -# infrastructure/ai/functions/generate_site_structure.py -class GenerateSiteStructureFunction(BaseAIFunction): - def get_operation_type(self): - return 'site_structure_generation' - - def get_estimated_cost(self, payload): - return CREDIT_COSTS['site_structure_generation'] - - def execute(self, payload, account): - """Generate site structure from business brief""" - business_brief = payload['business_brief'] - objectives = payload.get('objectives', []) - style_preferences = payload.get('style', {}) - - # Build prompt - prompt = self._build_prompt(business_brief, objectives, style_preferences) - - # Call AI - response = self.ai_core.generate(prompt, model='gpt-4') - - # Parse response to structure JSON - structure = self._parse_structure(response) - - return structure -``` - -#### Structure Generation Service - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Structure Generation Service** | `business/site_building/services/structure_generation_service.py` | Phase 1, AI framework | Service to generate site structure | - -**StructureGenerationService**: -```python -# business/site_building/services/structure_generation_service.py -class StructureGenerationService: - def __init__(self): - self.ai_function = GenerateSiteStructureFunction() - self.credit_service = CreditService() - - def generate_structure(self, site_blueprint, business_brief, objectives, style): - """Generate site structure for blueprint""" - account = site_blueprint.account - - # Check credits - self.credit_service.check_credits(account, 'site_structure_generation') - - # Update status - site_blueprint.status = 'generating' - site_blueprint.save() - - # Generate structure - payload = { - 'business_brief': business_brief, - 'objectives': objectives, - 'style': style, - } - structure = self.ai_function.execute(payload, account) - - # Deduct credits - self.credit_service.deduct_credits(account, 'site_structure_generation') - - # Update blueprint - site_blueprint.structure_json = structure - site_blueprint.status = 'ready' - site_blueprint.save() - - # Create page blueprints - self._create_page_blueprints(site_blueprint, structure) - - return site_blueprint -``` - -#### Site Structure Prompts - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Site Structure Prompts** | `infrastructure/ai/prompts.py` | Existing prompt system | Add site structure prompts | - ---- - -## SITE BUILDER API - -### 3.3 Site Builder API - -**Purpose**: API endpoints for site builder operations. - -#### Site Builder ViewSet - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Site Builder ViewSet** | `modules/site_builder/views.py` | Structure Generation Service | CRUD operations for site blueprints | - -**SiteBuilderViewSet**: -```python -# modules/site_builder/views.py -class SiteBuilderViewSet(AccountModelViewSet): - queryset = SiteBlueprint.objects.all() - serializer_class = SiteBlueprintSerializer - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.structure_service = StructureGenerationService() - - @action(detail=True, methods=['post']) - def generate_structure(self, request, pk=None): - """Generate site structure""" - blueprint = self.get_object() - business_brief = request.data.get('business_brief') - objectives = request.data.get('objectives', []) - style = request.data.get('style', {}) - - blueprint = self.structure_service.generate_structure( - blueprint, business_brief, objectives, style - ) - - serializer = self.get_serializer(blueprint) - return Response(serializer.data) -``` - -#### Site Builder URLs - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Site Builder URLs** | `modules/site_builder/urls.py` | None | Register site builder routes | - -#### Site Builder Serializers - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Site Builder Serializers** | `modules/site_builder/serializers.py` | None | Serializers for SiteBlueprint and PageBlueprint | - ---- - -## SITE BUILDER FRONTEND - -### 3.4 Site Builder Frontend (New Container) - -**User-Friendly Name**: "Website Builder" or "Site Creator" - -#### Create Site Builder Container - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Create Site Builder Container** | `docker-compose.app.yml` | None | Add new container for site builder | - -**Docker Compose Configuration**: -```yaml -# docker-compose.app.yml -igny8_site_builder: - build: ./site-builder - ports: - - "8022:5175" - volumes: - - /data/app/igny8/site-builder:/app - environment: - - VITE_API_URL=http://igny8_backend:8010 -``` - -#### Wizard Steps - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Wizard Steps** | `site-builder/src/pages/wizard/` | NEW | Step-by-step wizard components | - -**Wizard Steps**: -- Step 1: Type Selection (Business type, industry) -- Step 2: Business Brief (Description, goals) -- Step 3: Objectives (What pages needed) -- Step 4: Style Preferences (Colors, fonts, layout) - -#### Preview Canvas - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Preview Canvas** | `site-builder/src/pages/preview/` | NEW | Live preview of site | - -#### Site Builder State - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Site Builder State** | `site-builder/src/state/builderStore.ts` | NEW | Zustand store for builder state | - -#### Site Builder API Client - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Site Builder API Client** | `site-builder/src/api/builder.api.ts` | NEW | API client for site builder | - -#### Layout Selection - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Layout Selection** | `site-builder/src/components/layouts/` | NEW | Layout selector component | - -#### Template Library - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Template Library** | `site-builder/src/components/templates/` | NEW | Template selector component | - -#### Block Components - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Block Components** | `site-builder/src/components/blocks/` | NEW | Block components (imports from shared) | - ---- - -## GLOBAL COMPONENT LIBRARY - -### 3.7 Global Component Library - -**Purpose**: Shared components across Site Builder, Sites Renderer, and Main App. - -#### Create Shared Component Library - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Create Shared Component Library** | `frontend/src/components/shared/` | None | Create shared component structure | - -**Component Library Structure**: -``` -frontend/src/components/shared/ -├── blocks/ -│ ├── Hero.tsx -│ ├── Features.tsx -│ ├── Services.tsx -│ ├── Products.tsx -│ ├── Testimonials.tsx -│ ├── ContactForm.tsx -│ └── ... -├── layouts/ -│ ├── DefaultLayout.tsx -│ ├── MinimalLayout.tsx -│ ├── MagazineLayout.tsx -│ ├── EcommerceLayout.tsx -│ ├── PortfolioLayout.tsx -│ ├── BlogLayout.tsx -│ └── CorporateLayout.tsx -└── templates/ - ├── BlogTemplate.tsx - ├── BusinessTemplate.tsx - ├── PortfolioTemplate.tsx - └── ... -``` - -**Usage**: Site Builder, Sites Renderer, and Main App all use same components (no duplicates) - -#### Component Documentation - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Component Documentation** | `frontend/src/components/shared/README.md` | None | Document all shared components | - ---- - -## PAGE GENERATION - -### 3.5 Page Generation (Reuse Content Service) - -**Purpose**: Generate page content using existing ContentService. - -#### Extend ContentService - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Extend ContentService** | `business/content/services/content_generation_service.py` | Phase 1 | Add site page generation method | - -#### Add Site Page Type - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Add Site Page Type** | `business/content/models.py` | Phase 1 | Add site page content type | - -#### Page Generation Prompts - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Page Generation Prompts** | `infrastructure/ai/prompts.py` | Existing prompt system | Add page generation prompts | - ---- - -## TESTING & VALIDATION - -### 3.6 Testing - -**Test Cases**: - -1. **Site Builder Tests**: - - ✅ Site Builder wizard works end-to-end - - ✅ Structure generation creates valid blueprints - - ✅ Preview renders correctly - - ✅ Page generation reuses existing content service - -2. **File Management Tests**: - - ✅ File upload works - - ✅ File access control works - - ✅ Storage quota enforced - -3. **Component Library Tests**: - - ✅ Components render correctly - - ✅ Components work in Site Builder - - ✅ Components work in Sites Renderer - ---- - -## IMPLEMENTATION CHECKLIST - -### Backend Tasks - -- [ ] Create `business/site_building/models.py` -- [ ] Create SiteBlueprint model -- [ ] Create PageBlueprint model -- [ ] Create site builder migrations -- [ ] Create `business/site_building/services/file_management_service.py` -- [ ] Create `business/site_building/services/structure_generation_service.py` -- [ ] Create `infrastructure/ai/functions/generate_site_structure.py` -- [ ] Add site structure prompts -- [ ] Create `modules/site_builder/views.py` -- [ ] Create SiteBuilder ViewSet -- [ ] Create `modules/site_builder/serializers.py` -- [ ] Create `modules/site_builder/urls.py` -- [ ] Extend ContentService for page generation - -### Frontend Tasks - -- [ ] Create `site-builder/` folder structure -- [ ] Create Site Builder container in docker-compose -- [ ] Create wizard steps -- [ ] Create preview canvas -- [ ] Create builder state store -- [ ] Create API client -- [ ] Create layout selector -- [ ] Create template library -- [ ] Create `frontend/src/components/shared/` structure -- [ ] Create block components -- [ ] Create layout components -- [ ] Create template components -- [ ] Create component documentation - -### Testing Tasks - -- [ ] Test site builder wizard -- [ ] Test structure generation -- [ ] Test file management -- [ ] Test component library -- [ ] Test page generation - ---- - -## RISK ASSESSMENT - -| Risk | Level | Mitigation | -|------|-------|------------| -| **AI structure generation quality** | MEDIUM | Prompt engineering, validation | -| **Component compatibility** | MEDIUM | Shared component library, testing | -| **File management security** | MEDIUM | Access control, validation | -| **Performance with large sites** | LOW | Optimization, caching | - ---- - -## SUCCESS CRITERIA - -- ✅ Site Builder wizard works end-to-end -- ✅ Structure generation creates valid blueprints -- ✅ Preview renders correctly -- ✅ Page generation reuses existing content service -- ✅ File management works correctly -- ✅ Shared components work across all apps -- ✅ Multiple layouts supported - ---- - -**END OF PHASE 3 DOCUMENT** - diff --git a/docs/planning/phases/PHASE-4-LINKER-OPTIMIZER.md b/docs/planning/phases/PHASE-4-LINKER-OPTIMIZER.md deleted file mode 100644 index e480dae2..00000000 --- a/docs/planning/phases/PHASE-4-LINKER-OPTIMIZER.md +++ /dev/null @@ -1,391 +0,0 @@ -# PHASE 4: LINKER & OPTIMIZER -**Detailed Implementation Plan** - -**Goal**: Add linking and optimization as post-processing stages with multiple entry points. - -**Timeline**: 4-5 weeks -**Priority**: MEDIUM -**Dependencies**: Phase 1 - ---- - -## TABLE OF CONTENTS - -1. [Overview](#overview) -2. [Content Workflow & Entry Points](#content-workflow--entry-points) -3. [Content Model Extensions](#content-model-extensions) -4. [Linker Implementation](#linker-implementation) -5. [Optimizer Implementation](#optimizer-implementation) -6. [Content Pipeline Service](#content-pipeline-service) -7. [Linker & Optimizer APIs](#linker--optimizer-apis) -8. [Linker & Optimizer UI](#linker--optimizer-ui) -9. [Testing & Validation](#testing--validation) -10. [Implementation Checklist](#implementation-checklist) - ---- - -## OVERVIEW - -### Objectives -- ✅ Add internal linking to content -- ✅ Add content optimization -- ✅ Support multiple entry points (Writer, WordPress Sync, 3rd Party, Manual) -- ✅ Create content pipeline service -- ✅ Build UI for linker and optimizer - -### Key Principles -- **Multiple Entry Points**: Optimizer works from any content source -- **Unified Content Model**: All content stored in same model with source tracking -- **Pipeline Orchestration**: Linker → Optimizer → Publish workflow -- **Source Agnostic**: Optimizer works on any content regardless of source - ---- - -## CONTENT WORKFLOW & ENTRY POINTS - -### 4.0 Content Workflow & Entry Points - -**Content Sources**: -1. **IGNY8 Generated** - Content created via Writer module -2. **WordPress Synced** - Content synced from WordPress via plugin -3. **3rd Party Synced** - Content synced from external sources (Shopify, custom APIs) - -**Workflow Entry Points**: -``` -Entry Point 1: Writer → Linker → Optimizer → Publish -Entry Point 2: WordPress Sync → Optimizer → Publish -Entry Point 3: 3rd Party Sync → Optimizer → Publish -Entry Point 4: Manual Selection → Linker/Optimizer -``` - -**Content Storage Strategy**: -- All content stored in unified `Content` model -- `source` field: `'igny8'`, `'wordpress'`, `'shopify'`, `'custom'` -- `sync_status` field: `'native'`, `'imported'`, `'synced'` - ---- - -## CONTENT MODEL EXTENSIONS - -### 4.1 Content Model Extensions - -**Purpose**: Add fields to track content source and sync status. - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Add source field** | `business/content/models.py` | Phase 1 | Track content source | -| **Add sync_status field** | `business/content/models.py` | Phase 1 | Track sync status | -| **Add external_id field** | `business/content/models.py` | Phase 1 | Store external platform ID | -| **Add sync_metadata field** | `business/content/models.py` | Phase 1 | Store platform-specific metadata | - -**Content Model Extensions**: -```python -# business/content/models.py -class Content(SiteSectorBaseModel): - # Existing fields... - - # NEW: Source tracking - source = models.CharField( - max_length=50, - choices=[ - ('igny8', 'IGNY8 Generated'), - ('wordpress', 'WordPress Synced'), - ('shopify', 'Shopify Synced'), - ('custom', 'Custom API Synced'), - ], - default='igny8' - ) - - # NEW: Sync status - sync_status = models.CharField( - max_length=50, - choices=[ - ('native', 'Native IGNY8 Content'), - ('imported', 'Imported from External'), - ('synced', 'Synced from External'), - ], - default='native' - ) - - # NEW: External reference - external_id = models.CharField(max_length=255, blank=True, null=True) - external_url = models.URLField(blank=True, null=True) - sync_metadata = models.JSONField(default=dict) - - # NEW: Linking fields - internal_links = models.JSONField(default=list) - linker_version = models.IntegerField(default=0) - - # NEW: Optimization fields - optimizer_version = models.IntegerField(default=0) - optimization_scores = models.JSONField(default=dict) -``` - ---- - -## LINKER IMPLEMENTATION - -### 4.2 Linker Models - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **InternalLink Model** | `business/linking/models.py` | Phase 1 | Store link relationships | -| **LinkGraph Model** | `business/linking/models.py` | Phase 1 | Store link graph | - -### 4.3 Linker Service - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **LinkerService** | `business/linking/services/linker_service.py` | Phase 1, ContentService | Main linking service | -| **Link Candidate Engine** | `business/linking/services/candidate_engine.py` | Phase 1 | Find link candidates | -| **Link Injection Engine** | `business/linking/services/injection_engine.py` | Phase 1 | Inject links into content | - -**LinkerService**: -```python -# business/linking/services/linker_service.py -class LinkerService: - def process(self, content_id): - """Process content for linking""" - content = Content.objects.get(id=content_id) - - # Check credits - credit_service.check_credits(content.account, 'linking') - - # Find link candidates - candidates = self.candidate_engine.find_candidates(content) - - # Inject links - linked_content = self.injection_engine.inject_links(content, candidates) - - # Update content - content.internal_links = linked_content['links'] - content.linker_version += 1 - content.save() - - # Deduct credits - credit_service.deduct_credits(content.account, 'linking') - - return content -``` - ---- - -## OPTIMIZER IMPLEMENTATION - -### 4.5 Optimizer Models - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **OptimizationTask Model** | `business/optimization/models.py` | Phase 1 | Store optimization results | -| **OptimizationScores Model** | `business/optimization/models.py` | Phase 1 | Store optimization scores | - -### 4.6 Optimizer Service (Multiple Entry Points) - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **OptimizerService** | `business/optimization/services/optimizer_service.py` | Phase 1, ContentService | Main optimization service | -| **Content Analyzer** | `business/optimization/services/analyzer.py` | Phase 1 | Analyze content quality | -| **Optimization AI Function** | `infrastructure/ai/functions/optimize_content.py` | Existing AI framework | AI optimization function | - -**OptimizerService**: -```python -# business/optimization/services/optimizer_service.py -class OptimizerService: - def optimize_from_writer(self, content_id): - """Entry Point 1: Writer → Optimizer""" - content = Content.objects.get(id=content_id, source='igny8') - return self.optimize(content) - - def optimize_from_wordpress_sync(self, content_id): - """Entry Point 2: WordPress Sync → Optimizer""" - content = Content.objects.get(id=content_id, source='wordpress') - return self.optimize(content) - - def optimize_from_external_sync(self, content_id): - """Entry Point 3: External Sync → Optimizer""" - content = Content.objects.get(id=content_id, source__in=['shopify', 'custom']) - return self.optimize(content) - - def optimize_manual(self, content_id): - """Entry Point 4: Manual Selection → Optimizer""" - content = Content.objects.get(id=content_id) - return self.optimize(content) - - def optimize(self, content): - """Unified optimization logic""" - # Check credits - credit_service.check_credits(content.account, 'optimization', content.word_count) - - # Analyze content - scores_before = self.analyzer.analyze(content) - - # Optimize content - optimized = self.ai_function.optimize(content) - - # Analyze optimized content - scores_after = self.analyzer.analyze(optimized) - - # Store optimization task - OptimizationTask.objects.create( - content=content, - scores_before=scores_before, - scores_after=scores_after, - html_before=content.html_content, - html_after=optimized['html_content'], - ) - - # Update content - content.optimizer_version += 1 - content.optimization_scores = scores_after - content.save() - - # Deduct credits - credit_service.deduct_credits(content.account, 'optimization', content.word_count) - - return content -``` - ---- - -## CONTENT PIPELINE SERVICE - -### 4.7 Content Pipeline Service - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **ContentPipelineService** | `business/content/services/content_pipeline_service.py` | LinkerService, OptimizerService | Orchestrate content pipeline | - -**Pipeline Workflow States**: -``` -Content States: -- 'draft' → Generated, not processed -- 'linked' → Links added, ready for optimization -- 'optimized' → Optimized, ready for review -- 'review' → Ready for publishing -- 'published' → Published to destination(s) -``` - -**ContentPipelineService**: -```python -# business/content/services/content_pipeline_service.py -class ContentPipelineService: - def process_writer_content(self, content_id, stages=['linking', 'optimization']): - """Writer → Linker → Optimizer pipeline""" - content = Content.objects.get(id=content_id, source='igny8') - - if 'linking' in stages: - content = linker_service.process(content.id) - - if 'optimization' in stages: - content = optimizer_service.optimize_from_writer(content.id) - - return content - - def process_synced_content(self, content_id, stages=['optimization']): - """Synced Content → Optimizer (skip linking if needed)""" - content = Content.objects.get(id=content_id) - - if 'optimization' in stages: - content = optimizer_service.optimize_manual(content.id) - - return content -``` - ---- - -## LINKER & OPTIMIZER APIs - -### 4.8 Linker & Optimizer APIs - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Linker ViewSet** | `modules/linker/views.py` | LinkerService | API for linker operations | -| **Optimizer ViewSet** | `modules/optimizer/views.py` | OptimizerService | API for optimizer operations | - ---- - -## LINKER & OPTIMIZER UI - -### 4.9 Linker & Optimizer UI - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Linker Dashboard** | `frontend/src/pages/Linker/Dashboard.tsx` | NEW | Linker overview | -| **Optimizer Dashboard** | `frontend/src/pages/Optimizer/Dashboard.tsx` | NEW | Optimizer overview | -| **Content Selection UI** | `frontend/src/components/optimizer/ContentSelector.tsx` | NEW | Select content for optimization | -| **Source Badge Component** | `frontend/src/components/content/SourceBadge.tsx` | NEW | Show content source | - -**Optimizer UI Features**: -- Show content source (IGNY8, WordPress, Shopify badge) -- Show sync status (Native, Synced, Imported badge) -- Entry point selection (from Writer, from Sync, Manual) -- Content list with source filters -- "Send to Optimizer" button (works for any source) - -### 4.10 Content Filtering & Display - -| Task | File | Dependencies | Implementation | -|------|------|--------------|----------------| -| **Content Filter Component** | `frontend/src/components/content/ContentFilter.tsx` | NEW | Filter content by source | -| **Source Filter** | `frontend/src/components/content/SourceFilter.tsx` | NEW | Filter by source | -| **Sync Status Filter** | `frontend/src/components/content/SyncStatusFilter.tsx` | NEW | Filter by sync status | - ---- - -## TESTING & VALIDATION - -### 4.11 Testing - -**Test Cases**: -- ✅ Writer → Linker handover works -- ✅ Linker finds appropriate link candidates -- ✅ Links inject correctly into content -- ✅ Optimizer works from Writer entry point -- ✅ Optimizer works from WordPress sync entry point -- ✅ Optimizer works from 3rd party sync entry point -- ✅ Optimizer works from manual selection -- ✅ Synced content stored correctly with source flags -- ✅ Content filtering works (by source, sync_status) -- ✅ Pipeline orchestrates correctly -- ✅ All entry points use same optimization logic - ---- - -## IMPLEMENTATION CHECKLIST - -### Backend Tasks - -- [ ] Extend Content model with source/sync fields -- [ ] Create `business/linking/models.py` -- [ ] Create LinkerService -- [ ] Create `business/optimization/models.py` -- [ ] Create OptimizerService -- [ ] Create optimization AI function -- [ ] Create ContentPipelineService -- [ ] Create Linker ViewSet -- [ ] Create Optimizer ViewSet -- [ ] Create content sync service (for Phase 6) - -### Frontend Tasks - -- [ ] Create Linker Dashboard -- [ ] Create Optimizer Dashboard -- [ ] Create content selection UI -- [ ] Create source badge component -- [ ] Create content filters -- [ ] Update content list with filters - ---- - -## SUCCESS CRITERIA - -- ✅ Writer → Linker handover works -- ✅ Optimizer works from all entry points -- ✅ Content source tracking works -- ✅ Pipeline orchestrates correctly -- ✅ UI shows content sources and filters - ---- - -**END OF PHASE 4 DOCUMENT** -