docs & ux improvmeents

This commit is contained in:
IGNY8 VPS (Salman)
2025-12-25 20:31:58 +00:00
parent 90e6e96b2b
commit 4bffede052
247 changed files with 6869 additions and 53517 deletions

View File

@@ -0,0 +1,290 @@
# Automation Module
**Last Verified:** December 25, 2025
**Status:** ✅ Active
**Backend Path:** `backend/igny8_core/business/automation/`
**Frontend Path:** `frontend/src/pages/Automation/`
---
## Quick Reference
| What | File | Key Items |
|------|------|-----------|
| Models | `business/automation/models.py` | `AutomationConfig`, `AutomationRun` |
| Service | `business/automation/services/automation_service.py` | `AutomationService` |
| Logger | `business/automation/services/automation_logger.py` | `AutomationLogger` |
| Celery Tasks | `business/automation/tasks.py` | `run_automation_task`, `check_scheduled_automations` |
| Frontend | `pages/Automation/AutomationPage.tsx` | Main automation UI |
---
## Purpose
The Automation module runs the complete 7-stage content pipeline automatically:
```
Keywords → Clusters → Ideas → Tasks → Content → Image Prompts → Images → Review
```
---
## 7-Stage Pipeline
| Stage | Name | AI Function | Credit Cost |
|-------|------|-------------|-------------|
| 1 | Keywords → Clusters | `AutoClusterFunction` | Per batch |
| 2 | Clusters → Ideas | `GenerateIdeasFunction` | Per idea |
| 3 | Ideas → Tasks | None (local) | None |
| 4 | Tasks → Content | `GenerateContentFunction` | Per 100 words |
| 5 | Content → Image Prompts | `GenerateImagePromptsFunction` | Per prompt |
| 6 | Image Prompts → Images | `process_image_generation_queue` | Per image |
| 7 | Manual Review Gate | None | None |
---
## Data Models
### AutomationConfig
| Field | Type | Purpose |
|-------|------|---------|
| account | FK | Owner account |
| site | FK | Target site |
| enabled | Boolean | Enable/disable automation |
| frequency | CharField | daily/weekly/monthly |
| scheduled_time | TimeField | Time to run |
| stage_1_batch_size | Integer | Keywords per batch |
| stage_2_batch_size | Integer | Clusters per batch |
| stage_3_batch_size | Integer | Ideas per batch |
| stage_4_batch_size | Integer | Tasks per batch |
| stage_5_batch_size | Integer | Content per batch |
| stage_6_batch_size | Integer | Images per batch |
| within_stage_delay | Integer | Seconds between batches |
| between_stage_delay | Integer | Seconds between stages |
| last_run_at | DateTime | Last execution |
| next_run_at | DateTime | Next scheduled run |
### AutomationRun
| Field | Type | Purpose |
|-------|------|---------|
| config | FK | Parent config |
| trigger_type | CharField | manual/scheduled |
| status | CharField | running/paused/cancelled/completed/failed |
| current_stage | Integer | Current stage (1-7) |
| started_at | DateTime | Start time |
| paused_at | DateTime | Pause time (nullable) |
| resumed_at | DateTime | Resume time (nullable) |
| cancelled_at | DateTime | Cancel time (nullable) |
| completed_at | DateTime | Completion time (nullable) |
| total_credits_used | Decimal | Total credits consumed |
| stage_1_result | JSON | Stage 1 results |
| stage_2_result | JSON | Stage 2 results |
| stage_3_result | JSON | Stage 3 results |
| stage_4_result | JSON | Stage 4 results |
| stage_5_result | JSON | Stage 5 results |
| stage_6_result | JSON | Stage 6 results |
| stage_7_result | JSON | Stage 7 results |
| error_message | TextField | Error details (nullable) |
---
## API Endpoints
| Method | Path | Handler | Purpose |
|--------|------|---------|---------|
| GET | `/api/v1/automation/config/` | Get/create config | Get automation config |
| PUT | `/api/v1/automation/update_config/` | Update config | Update settings |
| POST | `/api/v1/automation/run_now/` | Start manual run | Start automation |
| GET | `/api/v1/automation/current_run/` | Get current run | Run status/progress |
| GET | `/api/v1/automation/pipeline_overview/` | Get pipeline | Stage status counts |
| GET | `/api/v1/automation/current_processing/` | Get processing | Live processing status |
| POST | `/api/v1/automation/pause/` | Pause run | Pause after current item |
| POST | `/api/v1/automation/resume/` | Resume run | Resume from saved stage |
| POST | `/api/v1/automation/cancel/` | Cancel run | Cancel after current item |
| GET | `/api/v1/automation/history/` | Get history | Last 20 runs |
| GET | `/api/v1/automation/logs/` | Get logs | Activity log for run |
| GET | `/api/v1/automation/estimate/` | Get estimate | Credit estimate |
**Query Parameters:** All require `?site_id=`, run-specific require `?run_id=`
---
## Execution Flow
### Manual Run
1. User clicks "Run Now" on frontend
2. Frontend calls `POST /automation/run_now/?site_id=X`
3. Backend acquires cache lock `automation_lock_{site_id}`
4. Estimates credits required (1.2x buffer)
5. Validates balance >= estimate
6. Creates `AutomationRun` record
7. Enqueues `run_automation_task` Celery task
8. Returns run ID immediately
### Stage Execution
For each stage (1-7):
1. Check `_check_should_stop()` (paused/cancelled?)
2. Load items for processing
3. Process in batches (respecting batch_size)
4. For AI stages: Call AIEngine function
5. Wait `within_stage_delay` between batches
6. Save stage result JSON
7. Wait `between_stage_delay` before next stage
### Stage Result Fields
**Stage 1 (Clustering):**
```json
{
"keywords_processed": 150,
"clusters_created": 12,
"batches_run": 3,
"credits_used": 45,
"time_elapsed": 120,
"skipped": false,
"partial": false
}
```
**Stage 2 (Ideas):**
```json
{
"clusters_processed": 12,
"ideas_created": 36,
"batches_run": 2,
"credits_used": 72
}
```
**Stage 3 (Tasks):**
```json
{
"ideas_processed": 36,
"tasks_created": 36,
"batches_run": 4
}
```
**Stage 4 (Content):**
```json
{
"tasks_processed": 36,
"content_created": 36,
"total_words": 54000,
"batches_run": 6,
"credits_used": 540
}
```
**Stage 5 (Image Prompts):**
```json
{
"content_processed": 36,
"prompts_created": 180,
"batches_run": 4,
"credits_used": 36
}
```
**Stage 6 (Images):**
```json
{
"images_processed": 180,
"images_generated": 180,
"batches_run": 18
}
```
**Stage 7 (Review):**
```json
{
"ready_for_review": 36
}
```
---
## Scheduling
**Celery Beat Task:** `check_scheduled_automations`
**Frequency:** Hourly
**Logic:**
1. Find configs where `enabled=True`
2. Check if `next_run_at <= now`
3. Check if no active run exists
4. Start `run_automation_task` for eligible configs
5. Update `next_run_at` based on frequency
---
## Lock Mechanism
**Purpose:** Prevent concurrent runs for same site
**Key:** `automation_lock_{site_id}`
**Storage:** Redis cache
**Acquired:** On run start
**Released:** On completion/failure/cancel
---
## Credit Validation
Before starting:
1. Calculate estimated credits for all stages
2. Apply 1.2x safety buffer
3. Compare with account balance
4. Reject if balance < estimate
During execution:
- Each AI stage checks credits before processing
- Deductions happen after successful AI calls
- `total_credits_used` accumulates across stages
---
## Frontend Integration
### AutomationPage Components
- **Config Panel:** Enable/disable, schedule settings
- **Pipeline Cards:** Stage-by-stage status with pending counts
- **Processing Card:** Live processing status during run
- **Control Buttons:** Run Now, Pause, Resume, Cancel
- **Activity Log:** Real-time log streaming
- **History Table:** Past 20 runs with status
### Polling
- Every ~5s while run is running/paused
- Fetches: `current_run`, `pipeline_overview`, `current_processing`
- Lighter polling when idle
---
## Common Issues
| Issue | Cause | Fix |
|-------|-------|-----|
| "Already running" error | Lock exists from previous run | Wait or check if stuck |
| Insufficient credits | Balance < 1.2x estimate | Add credits |
| Stage skipped | No items to process | Check previous stages |
| Run stuck | Worker crashed | Clear lock, restart |
| Images not generating | Stage 5 didn't create prompts | Check stage 5 result |
---
## Planned Changes
| Feature | Status | Description |
|---------|--------|-------------|
| Progress bar accuracy | 🐛 Bug | Fix progress calculation based on actual stage |
| Completed count display | 🐛 Bug | Fix count display in UI |
| Stage skip configuration | 🔜 Planned | Allow skipping certain stages |
| Notification on complete | 🔜 Planned | Email/webhook when done |

254
docs/10-MODULES/BILLING.md Normal file
View File

@@ -0,0 +1,254 @@
# Billing Module
**Last Verified:** December 25, 2025
**Status:** ✅ Active
**Backend Path:** `backend/igny8_core/modules/billing/` + `backend/igny8_core/business/billing/`
**Frontend Path:** `frontend/src/pages/Billing/` + `frontend/src/pages/Account/`
---
## Quick Reference
| What | File | Key Items |
|------|------|-----------|
| Models | `business/billing/models.py` | `CreditTransaction`, `CreditUsageLog`, `CreditCostConfig` |
| Service | `business/billing/services/credit_service.py` | `CreditService` |
| Views | `modules/billing/views.py` | `CreditBalanceViewSet`, `CreditUsageViewSet` |
| Frontend | `pages/Account/PlansAndBillingPage.tsx` | Plans, credits, billing history |
| Store | `store/billingStore.ts` | `useBillingStore` |
---
## Purpose
The Billing module manages:
- Credit balance and transactions
- Usage tracking and limits
- Plan enforcement
- Payment processing
---
## Data Models
### CreditTransaction (Ledger)
| Field | Type | Purpose |
|-------|------|---------|
| account | FK | Owner account |
| transaction_type | CharField | purchase/subscription/refund/deduction/adjustment |
| amount | Decimal | Positive (add) or negative (deduct) |
| balance_after | Decimal | Balance after transaction |
| description | CharField | Transaction description |
| metadata | JSON | Additional data |
| reference_id | CharField | External reference |
| created_at | DateTime | Transaction time |
### CreditUsageLog (Analytics)
| Field | Type | Purpose |
|-------|------|---------|
| account | FK | Owner account |
| operation_type | CharField | clustering/idea_generation/content_generation/image_generation |
| credits_used | Decimal | Credits consumed |
| cost_usd | Decimal | USD cost |
| model_used | CharField | AI model used |
| tokens_in | Integer | Input tokens |
| tokens_out | Integer | Output tokens |
| content_type | FK | Related content type |
| object_id | Integer | Related object ID |
| metadata | JSON | Additional data |
| created_at | DateTime | Usage time |
### CreditCostConfig
| Field | Type | Purpose |
|-------|------|---------|
| operation_type | CharField | Operation name |
| credits_cost | Decimal | Credits per unit |
| unit | CharField | per_request/per_100_words/per_200_words/per_item/per_image |
| display_name | CharField | UI display name |
| description | TextField | Description |
| is_active | Boolean | Enable/disable |
| previous_cost | Decimal | Previous cost (audit) |
| updated_by | FK | Last updater |
---
## Credit Calculation Methods
### Method 1: Token-Based (Text Models)
Used for: Clustering, Ideas, Content Generation, Optimization
**Flow:**
1. AI call completes
2. OpenAI returns actual token usage
3. Calculate: `total_tokens = input_tokens + output_tokens`
4. Look up `CreditCostConfig` for operation
5. Apply formula based on unit:
- `per_100_words`: `credits = ceil(words / 100) * cost`
- `per_item`: `credits = items * cost`
6. Apply minimum credits
7. Deduct from balance
### Method 2: Fixed Cost (Image Models)
Used for: Image Generation
**Flow:**
1. Before AI call
2. Calculate: `credits = num_images * cost_per_image`
3. Check balance sufficient
4. Deduct credits
5. Then make AI call
---
## API Endpoints
| Method | Path | Handler | Purpose |
|--------|------|---------|---------|
| GET | `/api/v1/billing/balance/` | `CreditBalanceViewSet.list` | Current balance + monthly usage |
| GET | `/api/v1/billing/usage/` | `CreditUsageViewSet.list` | Usage log (paginated) |
| GET | `/api/v1/billing/usage/summary/` | `CreditUsageViewSet.summary` | Aggregated by operation |
| GET | `/api/v1/billing/usage/limits/` | `CreditUsageViewSet.limits` | Plan limits + current usage |
| GET | `/api/v1/billing/transactions/` | `TransactionViewSet.list` | Transaction history |
---
## Credit Service API
### Check Credits
```python
CreditService.check_credits(account, required_credits)
# Raises InsufficientCreditsError if balance < required
```
### Deduct Credits
```python
CreditService.deduct_credits_for_operation(
account=account,
operation_type='content_generation',
amount=word_count, # For per_word operations
model='gpt-4o-mini',
tokens_in=2500,
tokens_out=1500,
metadata={'content_id': 123}
)
```
### Add Credits
```python
CreditService.add_credits(
account=account,
amount=1000,
transaction_type='purchase',
description='Credit package purchase'
)
```
---
## Plan Limits
### Hard Limits (Never Reset)
| Limit | Field | Description |
|-------|-------|-------------|
| Sites | `max_sites` | Maximum sites per account |
| Users | `max_users` | Maximum team members |
| Keywords | `max_keywords` | Total keywords allowed |
| Clusters | `max_clusters` | Total clusters allowed |
### Monthly Limits (Reset on Billing Cycle)
| Limit | Field | Description |
|-------|-------|-------------|
| Content Ideas | `max_content_ideas` | Ideas per month |
| Content Words | `max_content_words` | Words generated per month |
| Basic Images | `max_images_basic` | Basic AI images per month |
| Premium Images | `max_images_premium` | Premium AI images per month |
| Image Prompts | `max_image_prompts` | Prompts per month |
---
## Usage Limits Panel
**Component:** `UsageLimitsPanel.tsx`
Displays:
- Progress bars for each limit
- Color coding: blue (safe), yellow (warning), red (critical)
- Days until reset for monthly limits
- Upgrade CTA when approaching limits
---
## Credit Costs Reference
Current costs (from `CreditCostConfig`):
| Operation | Unit | Default Cost |
|-----------|------|--------------|
| Clustering | per_request | 10 credits |
| Idea Generation | per_item | 2 credits |
| Content Generation | per_100_words | 5 credits |
| Image Generation (Basic) | per_image | 3 credits |
| Image Generation (Premium) | per_image | 5 credits |
| Content Optimization | per_200_words | 3 credits |
---
## Frontend Pages
### Plans & Billing (`/account/plans`)
**Tabs:**
1. **Current Plan** - Active plan, upgrade options
2. **Credits Overview** - Balance, usage chart, cost breakdown
3. **Purchase Credits** - Credit packages
4. **Billing History** - Invoices and transactions
### Usage Analytics (`/account/usage`)
**Tabs:**
1. **Limits & Usage** - Plan limits with progress bars
2. **Activity** - Credit transaction history
3. **API Usage** - API call statistics
---
## Integration Points
| From | To | Trigger |
|------|----|---------|
| AIEngine | CreditService | Pre-check and post-deduct |
| Automation | CreditService | Per-stage credit tracking |
| Subscription | Account | Credit allocation |
| Admin | CreditCostConfig | Price adjustments |
---
## Common Issues
| Issue | Cause | Fix |
|-------|-------|-----|
| 402 error | Insufficient credits | Add credits or reduce operation |
| Usage not showing | Log not created | Check CreditService called |
| Limits wrong | Cache stale | Clear cache, reload |
| Monthly usage high | Automation running | Pause automation |
---
## Planned Changes
| Feature | Status | Description |
|---------|--------|-------------|
| AI Model Config database | 🔜 Planned | Move model pricing to database |
| Budget alerts | 🔜 Planned | Email when approaching limits |
| Usage forecasting | 🔜 Planned | Predict credit usage |
| Overage billing | 🔜 Planned | Charge for overages instead of blocking |

View File

@@ -0,0 +1,286 @@
# Integrations Module
**Last Verified:** December 25, 2025
**Status:** ✅ Active
**Backend Path:** `backend/igny8_core/modules/integration/` + `backend/igny8_core/business/integration/`
**Frontend Path:** `frontend/src/pages/Settings/IntegrationSettings.tsx`
---
## Quick Reference
| What | File | Key Items |
|------|------|-----------|
| Models | `business/integration/models.py` | `SiteIntegration`, `SyncEvent` |
| Views | `modules/integration/views.py` | `SiteIntegrationViewSet` |
| Webhooks | `modules/integration/webhooks.py` | `wordpress_webhook` |
| Services | `business/integration/services/*.py` | Sync services |
| Frontend | `pages/Settings/IntegrationSettings.tsx` | Integration UI |
---
## Purpose
The Integrations module manages:
- WordPress site connections
- Two-way content synchronization
- Webhook handling
- External platform integrations
---
## Data Models
### SiteIntegration
| Field | Type | Purpose |
|-------|------|---------|
| account | FK | Owner account |
| site | FK | IGNY8 site |
| platform | CharField | wordpress/shopify |
| site_url | URLField | External site URL |
| api_key | CharField | WordPress Application Password |
| username | CharField | WordPress username |
| is_active | Boolean | Enable/disable |
| sync_enabled | Boolean | Enable auto-sync |
| last_sync_at | DateTime | Last sync time |
| sync_status | CharField | idle/syncing/error |
| metadata | JSON | Platform-specific data |
| created_at | DateTime | Creation date |
### SyncEvent
| Field | Type | Purpose |
|-------|------|---------|
| integration | FK | Parent integration |
| event_type | CharField | content_push/content_pull/webhook |
| direction | CharField | igny8_to_wp/wp_to_igny8 |
| content_type | CharField | post/page/product |
| content_id | Integer | IGNY8 content ID |
| external_id | Integer | WordPress post ID |
| status | CharField | pending/success/failed |
| error_message | TextField | Error details |
| metadata | JSON | Additional data |
| created_at | DateTime | Event time |
---
## API Endpoints
| Method | Path | Handler | Purpose |
|--------|------|---------|---------|
| GET | `/api/v1/integration/` | `SiteIntegrationViewSet.list` | List integrations |
| POST | `/api/v1/integration/` | `SiteIntegrationViewSet.create` | Create integration |
| PUT | `/api/v1/integration/{id}/` | `SiteIntegrationViewSet.update` | Update integration |
| DELETE | `/api/v1/integration/{id}/` | `SiteIntegrationViewSet.destroy` | Remove integration |
| POST | `/api/v1/integration/{id}/test_connection/` | Test connection | Verify credentials |
| POST | `/api/v1/integration/{id}/test_collection_connection/` | Test per-collection | Test specific content type |
| POST | `/api/v1/integration/{id}/sync/` | Trigger sync | Start synchronization |
| GET | `/api/v1/integration/{id}/sync_status/` | Get sync status | Current sync progress |
| POST | `/api/v1/integration/{id}/update_structure/` | Update structure | Refresh site structure |
| GET | `/api/v1/integration/{id}/content_types/` | Get content types | Available types + counts |
| GET | `/api/v1/integration/{id}/sync_health/` | Get sync health | Sync statistics |
| POST | `/api/v1/integration/site_sync/` | Site-level sync | Sync by site ID |
### Webhooks
| Method | Path | Handler | Purpose |
|--------|------|---------|---------|
| POST | `/api/v1/integration/webhook/wordpress/` | `wordpress_webhook` | Receive WP updates |
---
## WordPress Integration
### Setup Flow
1. User enters WordPress site URL
2. User creates Application Password in WordPress
3. User enters credentials in IGNY8
4. IGNY8 tests connection via WordPress REST API
5. If successful, saves `SiteIntegration` record
### Required WordPress Setup
- WordPress 5.6+ (REST API enabled)
- Application Passwords enabled
- Pretty permalinks enabled
- REST API accessible (no blocking plugins)
### Test Connection
**Endpoint:** `POST /integration/{id}/test_connection/`
**Flow:**
1. Call WordPress `/wp-json/wp/v2/users/me`
2. Verify authentication works
3. Return user info and site capabilities
---
## Content Synchronization
### IGNY8 → WordPress (Push)
**Trigger:** User clicks "Publish to WordPress"
**Flow:**
1. Content is in `approved` status
2. Get `SiteIntegration` for content's site
3. Build WordPress post payload:
- title, content, excerpt, slug
- status: `publish` or `draft`
- categories, tags (mapped)
- featured media (if image exists)
4. Call WordPress REST API:
- `POST /wp-json/wp/v2/posts` (new)
- `PUT /wp-json/wp/v2/posts/{id}` (update)
5. Store `wordpress_id` on Content
6. Create `SyncEvent` record
7. Update Content status to `published`
### WordPress → IGNY8 (Pull)
**Trigger:** Manual sync or webhook
**Flow:**
1. Call WordPress `/wp-json/wp/v2/posts`
2. For each post:
- Check if exists in IGNY8 by `wordpress_id`
- If exists: Update if modified
- If new: Create Content record
3. Sync taxonomies (categories, tags)
4. Create `SyncEvent` records
### Webhook Handling
**WordPress Plugin** sends webhooks to IGNY8 when:
- Post created/updated/deleted
- Post status changed (draft → published)
**Webhook Payload:**
```json
{
"action": "post_updated",
"post_id": 123,
"post_type": "post",
"site_url": "https://example.com"
}
```
**IGNY8 Processing:**
1. Validate webhook signature (optional)
2. Find matching `SiteIntegration`
3. Fetch full post from WordPress
4. Update/create Content in IGNY8
5. Create `SyncEvent` record
---
## Image Sync
### Push (IGNY8 → WordPress)
1. Image record has `image_url`
2. Download image from URL
3. Upload to WordPress Media Library
4. Get WordPress attachment ID
5. Set as featured image on post
### Pull (WordPress → IGNY8)
1. Get featured media ID from post
2. Fetch media URL from WordPress
3. Store URL in IGNY8 Images record
---
## Taxonomy Sync
### Categories
1. Get WordPress categories via `/wp-json/wp/v2/categories`
2. Create `ContentTaxonomy` records (type=category)
3. Store `wordpress_id` for mapping
### Tags
1. Get WordPress tags via `/wp-json/wp/v2/tags`
2. Create `ContentTaxonomy` records (type=tag)
3. Store `wordpress_id` for mapping
---
## Sync Status Tracking
| Status | Description |
|--------|-------------|
| idle | No sync in progress |
| syncing | Sync currently running |
| error | Last sync failed |
**Sync Health Metrics:**
- Total synced posts
- Last successful sync
- Failed sync count
- Pending items
---
## Frontend Pages
### Integration Settings (`/settings/integration`)
- Add new integration button
- List of configured integrations
- Status indicators (connected/error)
- Test connection button
- Sync now button
- Sync status and history
### WordPress Sync Dashboard (`/sites/{id}/sync`)
- Detailed sync status
- Content sync queue
- Error log
- Manual sync triggers
---
## Common Issues
| Issue | Cause | Fix |
|-------|-------|-----|
| Connection failed | Invalid credentials | Verify Application Password |
| 401 Unauthorized | Password expired | Regenerate Application Password |
| 403 Forbidden | REST API blocked | Check security plugins |
| Images not syncing | CORS/URL issues | Verify image URLs accessible |
| Categories missing | Not synced | Run sync_structure first |
---
## Security
### Credential Storage
- API keys encrypted at rest
- Never exposed in API responses
- Application Passwords rotatable
### Webhook Security
- Optional signature verification
- Site URL validation
- Rate limiting on webhook endpoint
---
## Planned Changes
| Feature | Status | Description |
|---------|--------|-------------|
| Shopify integration | 🔜 Planned | E-commerce platform support |
| Ghost integration | 🔜 Planned | Ghost CMS support |
| Webflow integration | 🔜 Planned | Webflow CMS support |
| Scheduled sync | 🔜 Planned | Automatic periodic sync |
| Conflict resolution | 🔜 Planned | Handle edit conflicts |

183
docs/10-MODULES/LINKER.md Normal file
View File

@@ -0,0 +1,183 @@
# Linker Module
**Last Verified:** December 25, 2025
**Status:** ⏸️ Inactive (Disabled by Default)
**Backend Path:** `backend/igny8_core/modules/linker/`
**Frontend Path:** `frontend/src/pages/Linker/`
---
## Module Status
| Aspect | Current State | Notes |
|--------|---------------|-------|
| Backend API | ✅ Implemented | Endpoints functional |
| Frontend Pages | ✅ Implemented | UI exists |
| Sidebar Nav | ⚠️ Conditional | Hidden when disabled |
| Route Protection | ❌ Not Protected | Direct URL access still works |
| Dashboard References | ❌ Not Hidden | May show in dashboard |
| Default State | Disabled | `linker_enabled = True` in model, but typically disabled |
**⚠️ Pending Implementation:** Extend module disable to route-level protection and all page references.
---
## Quick Reference
| What | File | Key Items |
|------|------|-----------|
| Views | `modules/linker/views.py` | `LinkerViewSet` |
| API | `modules/linker/urls.py` | Linker endpoints |
| Frontend Pages | `pages/Linker/index.tsx` | Linker overview |
| Frontend Pages | `pages/Linker/LinkerContent.tsx` | Content for linking |
| API Client | `api/linker.api.ts` | `linkerApi` |
| Module Control | `modules/system/settings_models.py` | `ModuleEnableSettings.linker_enabled` |
---
## Purpose
The Linker module provides internal linking automation:
- Identify link opportunities in content
- Suggest relevant internal links
- Auto-inject links into content body
---
## API Endpoints
| Method | Path | Handler | Purpose |
|--------|------|---------|---------|
| POST | `/api/v1/linker/process/` | `LinkerViewSet.process` | Process single content for linking |
| POST | `/api/v1/linker/batch_process/` | `LinkerViewSet.batch_process` | Process multiple content items |
### Process Request
```json
{
"content_id": 123,
"max_links": 5,
"anchor_strategy": "exact_match"
}
```
### Process Response
```json
{
"content_id": 123,
"links_added": 3,
"link_opportunities": [
{
"anchor_text": "SEO optimization",
"target_url": "/blog/seo-guide/",
"target_content_id": 456,
"position": 234,
"confidence": 0.85
}
]
}
```
---
## Business Logic
### Link Candidate Discovery
**Trigger:** User initiates linking process
**Flow:**
1. Load source content body
2. Extract potential anchor phrases
3. Find matching content by:
- Keyword overlap
- Title similarity
- Same sector/industry
4. Score candidates by relevance
5. Filter to avoid over-linking
### Link Injection
**Trigger:** User approves link suggestions
**Flow:**
1. Locate anchor text in content
2. Wrap in `<a>` tag with target URL
3. Ensure no nested links
4. Save updated content body
---
## Module Enable Control
### Backend Model
```python
# modules/system/settings_models.py
class ModuleEnableSettings(AccountBaseModel):
linker_enabled = models.BooleanField(default=True)
```
### Frontend Check
```typescript
// layout/AppSidebar.tsx
if (isModuleEnabled('linker')) {
workflowItems.push({
name: "Linker",
path: "/linker/content",
});
}
```
### Current Limitation
Direct URL access to `/linker/*` routes still works even when module is disabled.
---
## Frontend Pages
### Linker Overview (`/linker`)
- Module overview
- Quick stats
- Start linking action
### Content for Linking (`/linker/content`)
- List of content available for linking
- Link status indicators
- Process button per content
- Batch processing action
---
## Integration Points
| From | To | Trigger |
|------|----|---------|
| Content | Linker | Manual process |
| Linker | Content | Link injection |
| Automation | Linker | Automated linking (future) |
---
## Common Issues
| Issue | Cause | Fix |
|-------|-------|-----|
| Module visible when disabled | Only sidebar hidden | Pending: route protection |
| No link candidates | No matching content | Create more related content |
| Links broken | Target content deleted | Validate target exists |
---
## Planned Changes
| Feature | Status | Description |
|---------|--------|-------------|
| Route-level protection | 🔜 Pending | Block access when module disabled |
| Dashboard card hiding | 🔜 Pending | Hide from dashboard when disabled |
| Automation integration | 🔜 Planned | Add to automation pipeline |
| Link density control | 🔜 Planned | Prevent over-linking |
| External link support | 🔜 Planned | Add outbound links |

View File

@@ -0,0 +1,262 @@
# Optimizer Module
**Last Verified:** December 25, 2025
**Status:** ⏸️ Inactive (Disabled by Default)
**Backend Path:** `backend/igny8_core/modules/optimizer/` + `backend/igny8_core/business/optimization/`
**Frontend Path:** `frontend/src/pages/Optimizer/`
---
## Module Status
| Aspect | Current State | Notes |
|--------|---------------|-------|
| Backend API | ✅ Implemented | Endpoints functional |
| Business Logic | ✅ Implemented | Optimization service exists |
| Frontend Pages | ✅ Implemented | UI exists |
| Sidebar Nav | ⚠️ Conditional | Hidden when disabled |
| Route Protection | ❌ Not Protected | Direct URL access still works |
| Dashboard References | ❌ Not Hidden | May show in dashboard |
| Default State | Disabled | `optimizer_enabled = True` in model, but typically disabled |
**⚠️ Pending Implementation:** Extend module disable to route-level protection and all page references.
---
## Quick Reference
| What | File | Key Items |
|------|------|-----------|
| Views | `modules/optimizer/views.py` | `OptimizerViewSet` |
| Models | `business/optimization/models.py` | `OptimizationTask` |
| Services | `business/optimization/services/*.py` | Optimization logic |
| AI Function | `ai/functions/optimize.py` | `OptimizeContentFunction` |
| Frontend Pages | `pages/Optimizer/index.tsx` | Optimizer overview |
| Frontend Pages | `pages/Optimizer/OptimizerContent.tsx` | Select content |
| Frontend Pages | `pages/Optimizer/OptimizerPreview.tsx` | Analysis preview |
| API Client | `api/optimizer.api.ts` | `optimizerApi` |
| Module Control | `modules/system/settings_models.py` | `ModuleEnableSettings.optimizer_enabled` |
---
## Purpose
The Optimizer module provides AI-powered content optimization:
- Analyze existing content for SEO improvements
- Suggest and apply optimizations
- Track before/after scores
---
## Data Models
### OptimizationTask
| Field | Type | Purpose |
|-------|------|---------|
| account | FK | Owner account |
| site | FK | Parent site |
| sector | FK | Parent sector |
| content | FK | Target content |
| entry_point | CharField | auto/igny8/wordpress/external/manual |
| status | CharField | pending/analyzing/optimizing/completed/failed |
| original_score | Integer | Score before optimization |
| optimized_score | Integer | Score after optimization |
| original_content | TextField | Content before changes |
| optimized_content | TextField | Content after changes |
| suggestions | JSON | Optimization suggestions |
| applied_changes | JSON | Changes that were applied |
| credits_used | Decimal | Credits consumed |
| created_at | DateTime | Creation date |
| completed_at | DateTime | Completion date |
---
## API Endpoints
| Method | Path | Handler | Purpose |
|--------|------|---------|---------|
| POST | `/api/v1/optimizer/optimize/` | `OptimizerViewSet.optimize` | Optimize single content |
| POST | `/api/v1/optimizer/batch_optimize/` | `OptimizerViewSet.batch_optimize` | Optimize multiple items |
| POST | `/api/v1/optimizer/analyze/` | `OptimizerViewSet.analyze` | Analyze without applying |
### Entry Points
| Entry Point | Description |
|-------------|-------------|
| `auto` | Auto-detect based on content source |
| `igny8` | IGNY8-generated content |
| `wordpress` | WordPress-synced content |
| `external` | External platform content |
| `manual` | Manual optimization trigger |
### Optimize Request
```json
{
"content_id": 123,
"entry_point": "igny8",
"optimization_goals": ["seo", "readability", "keyword_density"]
}
```
### Optimize Response
```json
{
"task_id": 456,
"content_id": 123,
"original_score": 65,
"optimized_score": 85,
"suggestions": [
{
"type": "keyword_density",
"description": "Increase keyword 'SEO' usage",
"applied": true
},
{
"type": "meta_description",
"description": "Meta description too short",
"applied": true
}
],
"credits_used": 15
}
```
---
## Business Logic
### Content Analysis
**Trigger:** User clicks "Analyze"
**Credit Cost:** None (analysis only)
**Checks:**
- Keyword density and distribution
- Meta title and description optimization
- Heading structure (H1, H2, H3)
- Readability score
- Content length
- Internal/external link count
- Image alt text presence
### Content Optimization (AI)
**Trigger:** User clicks "Optimize"
**AI Function:** `OptimizeContentFunction`
**Credit Cost:** Per 200 words
**Flow:**
1. Load content with metadata
2. Analyze current state
3. AIEngine executes `OptimizeContentFunction`:
- Reviews content against SEO best practices
- Suggests improvements
- Rewrites sections if needed
4. Create `OptimizationTask` record
5. Save original and optimized versions
6. Return comparison view
---
## Module Enable Control
### Backend Model
```python
# modules/system/settings_models.py
class ModuleEnableSettings(AccountBaseModel):
optimizer_enabled = models.BooleanField(default=True)
```
### Frontend Check
```typescript
// layout/AppSidebar.tsx
if (isModuleEnabled('optimizer')) {
workflowItems.push({
name: "Optimizer",
path: "/optimizer/content",
});
}
```
### Current Limitation
Direct URL access to `/optimizer/*` routes still works even when module is disabled.
---
## Frontend Pages
### Optimizer Overview (`/optimizer`)
- Module overview
- Quick stats
- Recent optimizations
### Select Content (`/optimizer/content`)
- List of content available for optimization
- Filter by score, status
- Start analysis button
- Batch optimize action
### Analysis Preview (`/optimizer/preview`)
- Side-by-side comparison
- Suggestion list
- Accept/reject changes
- Apply optimization button
---
## Optimization Scoring
| Metric | Weight | Description |
|--------|--------|-------------|
| Keyword Density | 20% | Target 1-3% density |
| Meta Quality | 15% | Title 50-60 chars, desc 150-160 chars |
| Heading Structure | 15% | Proper H1-H6 hierarchy |
| Readability | 15% | Flesch-Kincaid score |
| Content Length | 10% | Meets word count target |
| Internal Links | 10% | 2-5 internal links |
| Image Optimization | 10% | Alt text, sizing |
| Mobile Friendly | 5% | No wide elements |
---
## Integration Points
| From | To | Trigger |
|------|----|---------|
| Content | Optimizer | Manual analysis/optimize |
| WordPress | Optimizer | Synced content optimization |
| Optimizer | Content | Apply changes |
| Automation | Optimizer | Automated optimization (future) |
---
## Common Issues
| Issue | Cause | Fix |
|-------|-------|-----|
| Module visible when disabled | Only sidebar hidden | Pending: route protection |
| Optimization not improving | Content already good | Check original score |
| High credit usage | Large content | Optimize sections |
| Changes not saving | Apply not clicked | Click "Apply Changes" |
---
## Planned Changes
| Feature | Status | Description |
|---------|--------|-------------|
| Route-level protection | 🔜 Pending | Block access when module disabled |
| Dashboard card hiding | 🔜 Pending | Hide from dashboard when disabled |
| Automation integration | 🔜 Planned | Add to automation pipeline |
| Partial optimization | 🔜 Planned | Optimize specific sections only |
| Competitor analysis | 🔜 Planned | Compare against top-ranking content |
| A/B testing | 🔜 Planned | Track performance of optimizations |

231
docs/10-MODULES/PLANNER.md Normal file
View File

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

View File

@@ -0,0 +1,184 @@
# Publisher Module
**Last Verified:** December 25, 2025
**Status:** ✅ Active
**Backend Path:** `backend/igny8_core/modules/publisher/` + `backend/igny8_core/business/publishing/`
**Frontend Path:** N/A (API-only module)
---
## Quick Reference
| What | File | Key Items |
|------|------|-----------|
| Views | `modules/publisher/views.py` | `PublishingRecordViewSet`, `DeploymentViewSet`, `PublishContentViewSet` |
| Models | `business/publishing/models.py` | `PublishingRecord`, `DeploymentRecord` |
| Services | `business/publishing/services/*.py` | Publishing orchestration |
| URLs | `modules/publisher/urls.py` | Publisher endpoints |
---
## Purpose
The Publisher module manages:
- Content publishing pipeline
- Publishing record tracking
- Deployment management
- Multi-destination publishing
---
## Data Models
### PublishingRecord
| Field | Type | Purpose |
|-------|------|---------|
| account | FK | Owner account |
| site | FK | Parent site |
| content | FK | Source content |
| destination | CharField | wordpress/ghost/webflow |
| external_id | CharField | ID on destination platform |
| external_url | URLField | Published URL |
| status | CharField | pending/published/failed/retracted |
| published_at | DateTime | Publication time |
| metadata | JSON | Additional data |
| created_at | DateTime | Record creation |
### DeploymentRecord
| Field | Type | Purpose |
|-------|------|---------|
| account | FK | Owner account |
| site | FK | Target site |
| deployment_type | CharField | full/incremental |
| status | CharField | pending/deploying/completed/failed |
| items_deployed | Integer | Number of items |
| started_at | DateTime | Start time |
| completed_at | DateTime | Completion time |
| error_log | TextField | Errors encountered |
| metadata | JSON | Deployment details |
---
## API Endpoints
| Method | Path | Handler | Purpose |
|--------|------|---------|---------|
| GET | `/api/v1/publisher/records/` | `PublishingRecordViewSet.list` | List publishing records |
| POST | `/api/v1/publisher/records/` | `PublishingRecordViewSet.create` | Create record |
| GET | `/api/v1/publisher/deployments/` | `DeploymentViewSet.list` | List deployments |
| POST | `/api/v1/publisher/publish/` | `PublishContentViewSet.publish` | Publish content |
| GET | `/api/v1/publisher/publish/status/` | `PublishContentViewSet.status` | Get publishing status |
| GET | `/api/v1/publisher/site-definition/` | `SiteDefinitionViewSet.list` | Public site definitions |
---
## Publishing Flow
### Single Content Publish
**Trigger:** User clicks "Publish" or API call
**Flow:**
1. Validate content is in publishable state
2. Get site integration credentials
3. Transform content for destination:
- Format HTML for platform
- Process images
- Map taxonomies
4. Push to destination API
5. Create `PublishingRecord` with external ID
6. Update Content status to `published`
### Batch Deployment
**Trigger:** Deployment action
**Flow:**
1. Create `DeploymentRecord`
2. Gather all pending content
3. Process each item:
- Publish to destination
- Create publishing record
- Update content status
4. Update deployment status
5. Log any errors
---
## Destination Adapters
### WordPress Adapter
- Uses WordPress REST API
- Supports posts, pages, custom post types
- Handles media upload
- Maps categories/tags
### Ghost Adapter (Planned)
- Ghost Admin API integration
- Post publishing
- Image handling
### Webflow Adapter (Planned)
- Webflow CMS API
- Collection item publishing
- Asset management
---
## Publishing States
| Status | Description |
|--------|-------------|
| pending | Ready to publish |
| published | Successfully published |
| failed | Publishing failed |
| retracted | Unpublished/removed |
---
## Site Definition Endpoint
**Purpose:** Public endpoint for headless CMS use cases
Returns site structure for external consumption:
- Site metadata
- Available taxonomies
- Content types
- URL structure
---
## Integration Points
| From | To | Trigger |
|------|----|---------|
| Writer | Publisher | Publish action |
| Automation Stage 7 | Publisher | Auto-publish (future) |
| Publisher | Integrations | Destination APIs |
| Publisher | Content | Status updates |
---
## Common Issues
| Issue | Cause | Fix |
|-------|-------|-----|
| Publish failed | Invalid credentials | Check integration settings |
| Duplicate posts | Published twice | Check existing publishing record |
| Images missing | Upload failed | Check media library access |
| Wrong category | Mapping issue | Verify taxonomy sync |
---
## Planned Changes
| Feature | Status | Description |
|---------|--------|-------------|
| Ghost integration | 🔜 Planned | Ghost CMS publishing |
| Webflow integration | 🔜 Planned | Webflow publishing |
| Scheduled publishing | 🔜 Planned | Future-date publishing |
| Republish detection | 🔜 Planned | Detect and handle updates |
| Publishing queue | 🔜 Planned | Batch publishing with queue |

View File

@@ -0,0 +1,286 @@
# System Settings Module
**Last Verified:** December 25, 2025
**Status:** ✅ Active
**Backend Path:** `backend/igny8_core/modules/system/`
**Frontend Path:** `frontend/src/pages/Settings/`
---
## Quick Reference
| What | File | Key Items |
|------|------|-----------|
| Global Models | `modules/system/global_settings_models.py` | `GlobalIntegrationSettings`, `GlobalAIPrompt`, `GlobalAuthorProfile` |
| Account Models | `modules/system/settings_models.py` | `ModuleEnableSettings`, `IntegrationSettings`, `AISettings` |
| Views | `modules/system/settings_views.py` | Settings ViewSets |
| Integration Views | `modules/system/integration_views.py` | AI integration settings |
| Frontend | `pages/Settings/*.tsx` | Settings pages |
---
## Purpose
The System Settings module manages:
- Platform-wide global settings (API keys, defaults)
- Per-account settings overrides
- AI prompts and configurations
- Module enable/disable
- Author profiles and content strategies
---
## Settings Hierarchy
```
Global Settings (Platform-wide)
Account Settings (Per-account overrides)
User Settings (Per-user preferences)
```
**Priority:** User > Account > Global
---
## Global Settings Models
### GlobalIntegrationSettings (Singleton)
**Admin:** `/admin/system/globalintegrationsettings/`
**Purpose:** Platform-wide API keys and defaults
| Field | Type | Purpose |
|-------|------|---------|
| openai_api_key | CharField | OpenAI API key (all accounts) |
| openai_model | CharField | Default model (gpt-4o-mini) |
| openai_temperature | Float | Default temperature (0.7) |
| openai_max_tokens | Integer | Default max tokens (8192) |
| dalle_api_key | CharField | DALL-E API key |
| dalle_model | CharField | Default model (dall-e-3) |
| dalle_size | CharField | Default size (1024x1024) |
| dalle_quality | CharField | Default quality (standard) |
| dalle_style | CharField | Default style (vivid) |
| anthropic_api_key | CharField | Anthropic API key |
| runware_api_key | CharField | Runware API key |
**Critical:** This is a singleton (only 1 record, pk=1). All accounts use these API keys.
### GlobalAIPrompt
**Admin:** `/admin/system/globalaiprompt/`
**Purpose:** Default AI prompt templates
| Field | Type | Purpose |
|-------|------|---------|
| prompt_type | CharField | clustering/ideas/content_generation/etc. |
| prompt_value | TextField | The actual prompt text |
| description | TextField | What this prompt does |
| variables | JSON | Available variables ({keyword}, {industry}) |
| version | Integer | Prompt version |
| is_active | Boolean | Enable/disable |
### GlobalAuthorProfile
**Admin:** `/admin/system/globalauthorprofile/`
**Purpose:** Default author persona templates
| Field | Type | Purpose |
|-------|------|---------|
| name | CharField | Profile name |
| description | TextField | Description |
| tone | CharField | professional/casual/technical |
| language | CharField | en/es/fr |
| structure_template | JSON | Content structure config |
| category | CharField | saas/ecommerce/blog/technical |
| is_active | Boolean | Enable/disable |
---
## Account Settings Models
### IntegrationSettings
**Purpose:** Per-account AI model overrides (NOT API keys)
| Field | Type | Purpose |
|-------|------|---------|
| account | FK | Owner account |
| integration_type | CharField | openai/runware/image_generation |
| config | JSON | Model, temperature, max_tokens overrides |
| is_active | Boolean | Enable/disable |
**Important:**
- Free plan cannot create overrides
- Starter/Growth/Scale can override model/settings
- API keys ALWAYS come from GlobalIntegrationSettings
### ModuleEnableSettings
**Purpose:** Enable/disable modules per account
| Field | Type | Purpose |
|-------|------|---------|
| account | FK | Owner account |
| planner_enabled | Boolean | Enable Planner |
| writer_enabled | Boolean | Enable Writer |
| thinker_enabled | Boolean | Enable Thinker (AI settings) |
| automation_enabled | Boolean | Enable Automation |
| site_builder_enabled | Boolean | Enable Site Builder |
| linker_enabled | Boolean | Enable Linker |
| optimizer_enabled | Boolean | Enable Optimizer |
| publisher_enabled | Boolean | Enable Publisher |
**Current Implementation:**
- Controls sidebar navigation visibility
- ⚠️ **Pending:** Extend to other pages and references
### AIPrompt (Account-Level)
**Purpose:** Per-account prompt customizations
| Field | Type | Purpose |
|-------|------|---------|
| account | FK | Owner account |
| prompt_type | CharField | Prompt type |
| prompt_value | TextField | Current prompt (custom or default) |
| default_prompt | TextField | Original default (for reset) |
| is_customized | Boolean | True if user modified |
---
## API Endpoints
### Integration Settings
| Method | Path | Handler | Purpose |
|--------|------|---------|---------|
| GET | `/api/v1/system/settings/integrations/openai/` | Get OpenAI settings | Get current model/params |
| PUT | `/api/v1/system/settings/integrations/openai/` | Save OpenAI settings | Save overrides |
| GET | `/api/v1/system/settings/integrations/image_generation/` | Get image settings | Get DALL-E/Runware settings |
| PUT | `/api/v1/system/settings/integrations/image_generation/` | Save image settings | Save overrides |
| POST | `/api/v1/system/settings/integrations/test/` | Test connection | Test API connectivity |
### Prompts
| Method | Path | Handler | Purpose |
|--------|------|---------|---------|
| GET | `/api/v1/system/prompts/` | List prompts | Get all prompts |
| GET | `/api/v1/system/prompts/{type}/` | Get prompt | Get specific prompt |
| PUT | `/api/v1/system/prompts/{type}/` | Save prompt | Save customization |
| POST | `/api/v1/system/prompts/{type}/reset/` | Reset prompt | Reset to default |
### Module Settings
| Method | Path | Handler | Purpose |
|--------|------|---------|---------|
| GET | `/api/v1/system/modules/` | Get module settings | Get enable/disable state |
| PUT | `/api/v1/system/modules/` | Save module settings | Update enabled modules |
---
## Settings Flow (Frontend → Backend)
### Getting OpenAI Settings
1. Frontend requests: `GET /system/settings/integrations/openai/`
2. Backend checks account's `IntegrationSettings`
3. Gets global defaults from `GlobalIntegrationSettings`
4. Merges: account overrides > global defaults
5. Returns (NEVER includes API keys):
```json
{
"model": "gpt-4o-mini",
"temperature": 0.7,
"max_tokens": 8192,
"using_global": true
}
```
### Saving OpenAI Settings
1. Frontend sends: `PUT /system/settings/integrations/openai/`
2. Backend STRIPS any API key fields (security)
3. Validates account plan allows overrides
4. Saves to `IntegrationSettings.config`
5. Returns updated settings
---
## Module Enable/Disable
### How It Works (Current)
1. On app load, frontend fetches module settings
2. `useModuleStore.isModuleEnabled(name)` checks state
3. `AppSidebar.tsx` conditionally renders menu items:
```typescript
if (isModuleEnabled('linker')) {
workflowItems.push({
name: "Linker",
path: "/linker/content",
});
}
```
### Current Limitations (⚠️ Pending Implementation)
- Only hides sidebar menu items
- Direct URL access still works
- Other page references still show module links
- Dashboard cards may still show disabled modules
### Required Extension
Need to add `ModuleGuard` component to:
- Route-level protection
- Dashboard cards/widgets
- Cross-module references
- Settings page links
---
## Frontend Pages
### AI Settings (`/settings/ai`)
- OpenAI model selection
- Temperature and max tokens
- Image generation settings
- Test connection button
### Prompts (`/thinker/prompts`)
- List all prompt types
- Edit prompt text
- Reset to default
- Variable reference
### Module Settings (Admin Only)
- Enable/disable modules
- Per-account configuration
---
## Common Issues
| Issue | Cause | Fix |
|-------|-------|-----|
| Settings not saving | Plan restriction | Upgrade plan |
| API key exposed | Security flaw | Should never happen - check code |
| Module still visible | Cache stale | Clear cache, reload |
| Prompt reset not working | default_prompt missing | Re-run migration |
---
## Planned Changes
| Feature | Status | Description |
|---------|--------|-------------|
| Module guard extension | 🔜 Pending | Extend disable to all pages, not just sidebar |
| AIModelConfig database | 🔜 Planned | Move model pricing to database |
| Strategy templates | 🔜 Planned | Global strategy library |
| Per-user preferences | 🔜 Planned | User-level setting overrides |

293
docs/10-MODULES/WRITER.md Normal file
View File

@@ -0,0 +1,293 @@
# Writer Module
**Last Verified:** December 25, 2025
**Status:** ✅ Active
**Backend Path:** `backend/igny8_core/modules/writer/`
**Frontend Path:** `frontend/src/pages/Writer/`
---
## Quick Reference
| What | File | Key Items |
|------|------|-----------|
| Models | `modules/writer/models.py` | `Tasks`, `Content`, `Images`, `ContentTaxonomy` |
| Views | `modules/writer/views.py` | `TaskViewSet`, `ContentViewSet`, `ImageViewSet` |
| AI Functions | `ai/functions/content.py` | `GenerateContentFunction` |
| AI Functions | `ai/functions/images.py` | `GenerateImagesFunction`, `GenerateImagePromptsFunction` |
| Frontend Pages | `pages/Writer/Tasks.tsx` | Task management |
| Frontend Pages | `pages/Writer/Content.tsx` | Content listing |
| Frontend Pages | `pages/Writer/ContentViewer.tsx` | Content preview/edit |
---
## Purpose
The Writer module manages the content creation pipeline:
```
ContentIdeas → Tasks → Content → Images → Review → Publish
```
---
## Data Models
### Tasks
| Field | Type | Purpose |
|-------|------|---------|
| account | FK | Owner account |
| site | FK | Parent site |
| sector | FK | Parent sector |
| content_idea | FK | Source idea (nullable) |
| title | CharField | Task/content title |
| description | TextField | Task brief |
| target_keywords | JSON | Keywords to target |
| content_type | CharField | blog_post/guide/comparison/etc. |
| word_count_target | Integer | Target word count |
| status | CharField | pending/in_progress/completed/cancelled |
| assigned_to | FK | Assigned user (nullable) |
| due_date | DateTime | Due date (nullable) |
| priority | Integer | Priority level |
| created_at | DateTime | Creation date |
### Content
| Field | Type | Purpose |
|-------|------|---------|
| account | FK | Owner account |
| site | FK | Parent site |
| sector | FK | Parent sector |
| task | FK | Source task (nullable) |
| title | CharField | Content title |
| slug | SlugField | URL slug |
| content_body | TextField | HTML content |
| excerpt | TextField | Short summary |
| meta_title | CharField | SEO meta title |
| meta_description | CharField | SEO meta description |
| word_count | Integer | Actual word count |
| status | CharField | draft/review/approved/published |
| content_type | CharField | post/page/product |
| content_structure | CharField | article/guide/comparison/review/listicle |
| source | CharField | igny8/wordpress/manual |
| wordpress_id | Integer | WP post ID (if synced) |
| published_at | DateTime | Publication date |
| created_at | DateTime | Creation date |
### Images
| Field | Type | Purpose |
|-------|------|---------|
| account | FK | Owner account |
| site | FK | Parent site |
| sector | FK | Parent sector |
| content | FK | Parent content |
| image_type | CharField | featured/desktop/mobile/in_article |
| prompt | TextField | Generation prompt |
| image_url | URLField | Image URL |
| alt_text | CharField | Alt text for SEO |
| status | CharField | pending/generating/completed/failed |
| position | Integer | Order for in-article images |
| provider | CharField | dalle/runware |
| model | CharField | dall-e-3/runware:97@1 |
| created_at | DateTime | Creation date |
### ContentTaxonomy
| Field | Type | Purpose |
|-------|------|---------|
| account | FK | Owner account |
| site | FK | Parent site |
| name | CharField | Category/tag name |
| slug | SlugField | URL slug |
| taxonomy_type | CharField | category/tag |
| parent | FK | Parent taxonomy (for hierarchy) |
| description | TextField | Description |
| wordpress_id | Integer | WP term ID (if synced) |
---
## API Endpoints
### Tasks
| Method | Path | Handler | Purpose |
|--------|------|---------|---------|
| GET | `/api/v1/writer/tasks/` | `TaskViewSet.list` | List tasks |
| POST | `/api/v1/writer/tasks/` | `TaskViewSet.create` | Create task |
| POST | `/api/v1/writer/tasks/bulk_create/` | `TaskViewSet.bulk_create` | Create multiple tasks |
| POST | `/api/v1/writer/tasks/{id}/generate_content/` | `TaskViewSet.generate_content` | AI content generation |
### Content
| Method | Path | Handler | Purpose |
|--------|------|---------|---------|
| GET | `/api/v1/writer/content/` | `ContentViewSet.list` | List content |
| POST | `/api/v1/writer/content/` | `ContentViewSet.create` | Create content manually |
| PUT | `/api/v1/writer/content/{id}/` | `ContentViewSet.update` | Update content |
| POST | `/api/v1/writer/content/{id}/update_content/` | `ContentViewSet.update_content` | Update with validation |
| POST | `/api/v1/writer/content/{id}/generate_images/` | `ContentViewSet.generate_images` | Generate images |
| POST | `/api/v1/writer/content/{id}/publish_to_wordpress/` | `ContentViewSet.publish_to_wordpress` | Publish to WP |
### Images
| Method | Path | Handler | Purpose |
|--------|------|---------|---------|
| GET | `/api/v1/writer/images/` | `ImageViewSet.list` | List images |
| POST | `/api/v1/writer/images/generate_for_content/` | `ImageViewSet.generate_for_content` | Generate images |
| POST | `/api/v1/writer/images/regenerate/` | `ImageViewSet.regenerate` | Regenerate image |
---
## Business Logic
### Content Generation (AI)
**Trigger:** User clicks "Generate" on task
**AI Function:** `GenerateContentFunction`
**Credit Cost:** Per 100 words generated
**Flow:**
1. User has task with title, keywords, word count target
2. Frontend calls `POST /tasks/{id}/generate_content/`
3. Backend validates task and credits
4. AIEngine executes `GenerateContentFunction`:
- Loads account's AI prompts and strategy
- Sends to GPT-4 with structured output
- Receives HTML content with proper structure
5. Creates `Content` record linked to task
6. Updates task status to `completed`
7. Returns content for review
### Image Prompt Generation (AI)
**Trigger:** Part of content generation or explicit
**AI Function:** `GenerateImagePromptsFunction`
**Credit Cost:** Per prompt
**Flow:**
1. Content exists with body
2. AI analyzes content sections
3. Generates prompts for:
- Featured image (1)
- In-article images (configurable count)
4. Creates `Images` records with prompts, status=pending
### Image Generation (AI)
**Trigger:** User clicks "Generate Images" or automation
**AI Function:** `GenerateImagesFunction`
**Credit Cost:** Per image
**Flow:**
1. Image record exists with prompt, status=pending
2. Backend calls DALL-E or Runware API
3. Receives image URL
4. Updates `Images` record with URL, status=completed
### WordPress Publishing
**Trigger:** User clicks "Publish to WordPress"
**Credit Cost:** None
**Flow:**
1. Content is in `approved` status
2. Site has WordPress integration configured
3. Backend calls WordPress REST API:
- Creates/updates post
- Uploads featured image
- Sets categories/tags
4. Updates Content with `wordpress_id`
5. Sets status to `published`
---
## Content Structures
| Structure | Purpose | Typical Sections |
|-----------|---------|------------------|
| article | General blog post | Intro, Body, Conclusion |
| guide | How-to content | Steps, Tips, Summary |
| comparison | Product comparison | Features, Pros/Cons, Verdict |
| review | Product review | Overview, Features, Rating |
| listicle | List-based content | Numbered items with details |
| pillar | Long-form authority | Multiple sections with depth |
---
## Frontend Pages
### Tasks Page (`/writer/tasks`)
- Table of all tasks
- Filter by status, assigned user
- Generate content action
- Bulk actions
### Content Page (`/writer/content`)
- Table of all content
- Filter by status, content type
- Quick preview
- Publish actions
### Content Viewer (`/writer/content/{id}`)
- Full content preview
- Edit mode
- Image management
- Publish to WordPress
- Status management
### Draft/Review/Published Tabs
- Filtered views by status
- Different actions per status
---
## Content Status Flow
```
draft → review → approved → published
(rejected) → draft (revision)
```
---
## Integration Points
| From | To | Trigger |
|------|----|---------|
| ContentIdeas | Tasks | Create tasks |
| Tasks | Content | Generate content |
| Content | Images | Generate images |
| Content | WordPress | Publish |
| WordPress | Content | Sync imports |
| Automation Stage 4 | Content | Automated generation |
| Automation Stage 5-6 | Images | Automated image generation |
---
## Common Issues
| Issue | Cause | Fix |
|-------|-------|-----|
| Content too short | Low word count target | Increase target in task |
| Images not generating | No prompts created | Run image prompt generation first |
| WordPress publish fails | Invalid credentials | Check integration settings |
| Content stuck in draft | No manual status update | Update status via UI or API |
| Duplicate content | Re-running generation | Check if content already exists |
---
## Planned Changes
| Feature | Status | Description |
|---------|--------|-------------|
| Content revisions | 🔜 Planned | Track content version history |
| Multi-language | 🔜 Planned | Generate content in different languages |
| Batch generation | 🔜 Planned | Generate multiple content pieces at once |
| Regenerate sections | 🔜 Planned | AI regenerate specific sections |