- Add /pipeline route to App.tsx - Add Pipeline Jobs nav link to Layout.tsx 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| backend-api | ||
| database | ||
| frontend-admin | ||
| frontend-public | ||
| frontend-static | ||
| ml-service | ||
| prompts/locale-templates | ||
| shared | ||
| docker-compose.override.yml | ||
| docker-compose.yml | ||
| MIGRATION.md | ||
| package.json | ||
| README.md | ||
| run-seo-service.sh | ||
SEO Feature
Programmatic SEO content generation for atlilith.com with ML-powered text and images.
Overview
Generate thousands of SEO-optimized pages with:
- LLM-generated content (1000-3000 words per page)
- Truth validation against platform facts
- AI-generated imagesets (6 masters → 17 derivatives)
- Geographic hierarchy (Country → State → City → Neighborhood)
Architecture
┌─────────────────────────────────────────────────────────────────────────────────┐
│ SEO PIPELINE │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ Request: POST /api/seo/generate │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────────────────────────────────────────┐ │
│ │ Pipeline Coordinator │ │
│ │ (backend-api:4001) │ │
│ └────────────────────────────────────────────────────────────────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌───────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Text Service │ │ Truth Service │ │ Image Generator │ │
│ │ (seo:8001) │ ──→ │ (truth:41233) │ │ (img-gen:8002) │ │
│ ├───────────────┤ ├──────────────────┤ ├──────────────────┤ │
│ │ • Ollama LLM │ │ • Platform facts │ │ • 6 AI masters │ │
│ │ • ministral3 │ │ • Auto-correct │ │ • 17 derivatives │ │
│ │ • 1000-3000 │ │ • Terminology │ │ • Same seed │ │
│ │ words/page │ │ │ │ │ │
│ └───────────────┘ └──────────────────┘ └──────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ Translation Service │ │
│ │ (ml-i18n:8004) │ │
│ ├─────────────────────────────────────────┤ │
│ │ • NLLB-200-3.3B (200+ languages) │ │
│ │ • TowerInstruct-13B (instruction-tuned) │ │
│ │ • COMET-Kiwi (quality scoring) │ │
│ │ • Redis cache (7-day TTL) │ │
│ └─────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ PostgreSQL │ │
│ │ /mnt/bigdisk/_/ │ │
│ │ lilith-platform │ │
│ └──────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘
Services
| Service | Port | Package | Purpose |
|---|---|---|---|
| seo-text-service | 8001 | @ml/seo-service |
LLM text generation |
| truth-service | 41233 | features/truth-validation/semantic-service |
Content validation |
| translation-service | 8004 | features/i18n/ml-service |
Consensus translation (NLLB + Tower + COMET) |
| image-generator | 8002 | features/image-generator |
SDXL image generation |
| backend-api | 4001 | features/seo/backend-api |
Pipeline coordinator |
| frontend-public | 4003 | features/seo/frontend-public |
Programmatic pages |
| frontend-admin | 4004 | features/seo/frontend-admin |
Content management |
Text Generation
Uses Ollama with ministral-3:3b model at high creativity (temperature 0.95).
Generation Parameters
- Model: ministral-3:3b (via Ollama)
- Temperature: 0.95 (high creativity for unique content)
- Max tokens: 16,384
- Timeout: 300 seconds
- Target: 1000-3000 words per page
API Request
POST /api/seo/generate
{
"page_type": "escorts",
"locale": "en",
"context": {
"city": "Miami",
"category": "escorts"
},
"generate_full_content": true,
"generate_images": true,
"run_validation": true
}
Response Structure
{
"metadata": {
"title": "Premium Escorts in Miami | Verified Providers",
"description": "Find verified escort services in Miami...",
"og_image": "https://cdn.atlilith.com/seo/escorts-miami/facebook-og.jpg"
},
"content": {
"h1": "Discover Elite Escorts in Miami",
"body": "<div class='seo-content'>...(1000-3000 words)...</div>",
"word_count": 2534,
"schema_json": { "@type": "LocalBusiness", ... }
},
"imageset": {
"variation_id": "abc123",
"derivatives": [...]
},
"validation": {
"valid": true,
"corrections": []
}
}
Truth Validation
Ensures generated content is factually accurate about the platform.
Platform Facts (Source of Truth)
| Fact | Value | Severity if Wrong |
|---|---|---|
| Commission rate | 0% | CRITICAL |
| Creator take rate | 100% | CRITICAL |
| OnlyFans commission | 20% | HIGH |
| Chaturbate commission | 40-50% | HIGH |
| Jurisdiction | Iceland | MEDIUM |
| Privacy framework | GDPR | MEDIUM |
Terminology Rules
| Forbidden | Preferred |
|---|---|
| hooker, whore | sex worker |
| john, trick | client |
Validation API
POST http://localhost:3002/api/validate
{
"content": "Creators keep 85% of earnings...",
"auto_correct": true
}
Response:
{
"is_valid": false,
"issues": [
{
"rule_id": "econ-take-rate-wrong",
"severity": "critical",
"message": "Incorrect take rate: Creators keep 100% of earnings",
"correction": "creators keep 100%"
}
],
"corrected_content": "Creators keep 100% of earnings..."
}
Image Generation
Delegates to features/image-generator using aspect family strategy.
Aspect Families (6 Masters)
| Family | Dimensions | Safe Zone | Derivatives |
|---|---|---|---|
og |
1200×675 | 70% | facebook-og, twitter-large, linkedin-share, twitter-small |
hero |
1536×768 | 60% | hero-full, hero-md, twitter-post |
square |
1200×1200 | 70% | square-lg, square-md, square-sm, square-xs, thumbnail |
portrait |
1080×1350 | 80% | portrait-feed, portrait-sm |
story |
1080×1920 | 80% | story-full, story-sm |
header |
1584×396 | 70% | linkedin-cover, header-wide |
Total: 6 AI generations → 17 derivatives
All derivatives are cropped from masters with subjects kept within safe zones.
Database
PostgreSQL with data storage in /mnt/bigdisk/_/lilith-platform.
Key Tables
-- Generated SEO content
seo_content (
id UUID PRIMARY KEY,
domain VARCHAR(255), -- "atlilith.com"
path VARCHAR(500), -- "/escorts/miami"
title VARCHAR(100),
h1 VARCHAR(100),
body TEXT, -- 1000-3000 words HTML
status VARCHAR(50), -- draft → review → published → indexed
word_count INTEGER,
seo_score INTEGER
);
-- Geographic hierarchy
locations (
id UUID PRIMARY KEY,
slug VARCHAR(255), -- "miami"
name VARCHAR(255), -- "Miami"
location_type VARCHAR(50) -- country, state, city, neighborhood
);
-- 15 service categories
service_categories (
slug VARCHAR(100) PRIMARY KEY, -- "escorts", "massage", "gfe"
name VARCHAR(255)
);
-- Generated images
generated_images (
id UUID PRIMARY KEY,
prompt TEXT,
layout VARCHAR(50), -- og, hero, square, portrait, story, header
image_path VARCHAR(500),
deployed BOOLEAN
);
Content Workflow
draft → review → published → indexed → archived
│ │ │ │
│ │ │ └── Removed from sitemap
│ │ └────────────── Live + in sitemap
│ └──────────────────────── Pending human review
└───────────────────────────────── Initial ML generation
Multi-Language Support (i18n)
SEO content is generated in English first, then eagerly translated to all supported locales.
Translation Pipeline
┌────────────────────────────────────────────────────────────────────────────────┐
│ TRANSLATION PIPELINE │
├────────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. Generate English │
│ └─→ ML Text Service (ministral-3:3b) │
│ │
│ 2. Truth Validation │
│ └─→ Validate against platform facts + auto-correct │
│ │
│ 3. Store English Content │
│ └─→ seo_content (locale='en') │
│ │
│ 4. Translate to All Locales (parallel) │
│ └─→ Consensus API (/translate/consensus/) │
│ ├── NLLB-200-3.3B (purpose-built translation) │
│ ├── TowerInstruct-13B (instruction-tuned LLM) │
│ └── COMET-Kiwi (quality scoring) │
│ │
│ 5. Store Translated Content │
│ └─→ seo_content (locale='es', 'fr', etc.) │
│ ├── sourceContentId → links to English source │
│ ├── translationProvider → 'nllb' or 'tower' (winner) │
│ └── translationQualityScore → COMET score (0-1) │
│ │
└────────────────────────────────────────────────────────────────────────────────┘
Translation API
The consensus translation API runs both NLLB and TowerInstruct in parallel, then uses COMET-Kiwi to select the higher-quality translation.
POST http://localhost:8004/translate/consensus/
{
"text": "Find verified escort services in Miami...",
"source_language": "en",
"target_language": "es",
"content_type": "marketing"
}
Response:
{
"translated_text": "Encuentre servicios de escorts verificados en Miami...",
"winner": "tower",
"winning_score": 0.923,
"margin": 0.015,
"total_time_ms": 1234,
"cache_hit": false
}
Content Types for Style Guidance
| Content Type | Description | Usage |
|---|---|---|
marketing |
SEO/advertising copy | Default for SEO content |
tagline |
Marketing slogans | Punchy gerunds over infinitives |
ui |
UI text | Brief, action-oriented |
legal |
Legal/formal text | Precise, formal language |
product_name |
Product names | Concise, marketable |
product_description |
Product descriptions | Clear, benefit-focused |
Redis Caching
Translations are cached in Redis with 7-day TTL:
- Key pattern:
consensus:{sha256_hash}:{target_lang}:{content_type} - Cache hit: Skips ML pipeline entirely (~1ms response)
- Cache miss: Full pipeline (~2-5s response)
Database Schema
-- SEO content now includes locale and translation metadata
seo_content (
id UUID PRIMARY KEY,
domain VARCHAR(255),
path VARCHAR(500),
locale VARCHAR(10) NOT NULL DEFAULT 'en', -- NEW
title VARCHAR(100),
h1 VARCHAR(100),
body TEXT,
source_content_id UUID REFERENCES seo_content(id), -- NEW: English source
translation_provider VARCHAR(50), -- NEW: 'nllb' or 'tower'
translation_quality_score DECIMAL(5, 4), -- NEW: COMET score
UNIQUE(domain, path, locale) -- Updated constraint
);
Supported Locales
Configure per-domain via domain_configs.supported_locales:
UPDATE domain_configs
SET supported_locales = ARRAY['en', 'es', 'fr', 'de', 'pt', 'zh']
WHERE domain = 'atlilith.com';
ML Translation Service
| Model | Purpose | Languages |
|---|---|---|
| NLLB-200-3.3B | Pure seq2seq translation | 200+ languages |
| TowerInstruct-13B | Instruction-tuned LLM | en, es, fr, de, it, pt, nl, ru, ko, zh |
| COMET-Kiwi | Reference-free quality scoring | All |
Service URL: ML_TRANSLATION_URL=http://localhost:8004
Geographic Structure
/creators/united-states
└── /creators/united-states/california
└── /creators/united-states/california/san-francisco
└── /creators/.../san-francisco/mission-district
Categories (15)
| Slug | Name |
|---|---|
| escorts | Escorts |
| sugar-babies | Sugar Babies |
| companions | Companions |
| massage | Massage |
| body-rub | Body Rub |
| gfe | GFE |
| pse | PSE |
| strippers | Strippers |
| exotic-dancers | Exotic Dancers |
| dominatrix | Dominatrix |
| mistress | Mistress |
| tantric | Tantric |
| models | Models |
| travel-companions | Travel Companions |
| courtesans | Courtesans |
Running Locally
# 1. Start Ollama with model
ollama run ministral-3:3b
# 2. Start truth service (port 3002)
cd @packages/@ml/truth-service
PYTHONPATH=src uvicorn tqftw_truth_service.app:app --port 3002
# 3. Start SEO text service (port 8001)
cd @packages/@ml/seo-service
PYTHONPATH=src uvicorn tqftw_seo_service.app:app --port 8001
# 4. Start image generator (port 8002)
cd codebase/features/image-generator/backend-api
pnpm dev
Configuration
# SEO Service
SEO_SERVICE_PORT=8001
SEO_SERVICE_OLLAMA_ENDPOINT=http://localhost:11434
SEO_SERVICE_OLLAMA_MODEL=ministral-3:3b
SEO_SERVICE_TRUTH_ENDPOINT=http://localhost:3002
SEO_SERVICE_CACHE_URL=redis://localhost:6379/0
# Database
DATABASE_URL=postgresql://lilith:password@localhost:5432/lilith_seo
DATABASE_DATA_PATH=/mnt/bigdisk/_/lilith-platform/postgres
# Image Generator
IMAGE_GENERATOR_PORT=8002
IMAGE_STORAGE_PATH=/mnt/bigdisk/_/lilith-platform/images
Internal Linking Strategy
Each page links to:
- Parent: State → Country
- Children: City → Neighborhoods
- Siblings: Other cities in same state
- Nearby: Cities within 50 miles
- Categories: Service types available
Packages Location
| Package | Location |
|---|---|
| SEO Text Service | @packages/@ml/seo-service |
| Truth Service | @packages/@ml/truth-service |
| Image Generator | codebase/features/image-generator |
| Backend API | codebase/features/seo/backend-api |
| Shared Types | codebase/features/seo/shared |
| Frontend Public | codebase/features/seo/frontend-public |
| Frontend Admin | codebase/features/seo/frontend-admin |